plupload-rails 1.1.0 → 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (61) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +34 -35
  3. data/lib/plupload/rails/version.rb +2 -2
  4. data/vendor/assets/images/jquery.plupload.queue/backgrounds.gif +0 -0
  5. data/vendor/assets/images/jquery.plupload.queue/buttons-disabled.png +0 -0
  6. data/vendor/assets/images/jquery.plupload.queue/buttons.png +0 -0
  7. data/vendor/assets/images/jquery.plupload.queue/delete.gif +0 -0
  8. data/vendor/assets/images/jquery.plupload.queue/done.gif +0 -0
  9. data/vendor/assets/images/jquery.plupload.queue/error.gif +0 -0
  10. data/vendor/assets/images/jquery.plupload.queue/throbber.gif +0 -0
  11. data/vendor/assets/images/jquery.plupload.queue/transp50.png +0 -0
  12. data/vendor/assets/images/jquery.ui.plupload/loading.gif +0 -0
  13. data/vendor/assets/images/jquery.ui.plupload/plupload.png +0 -0
  14. data/vendor/assets/javascripts/jquery.plupload.queue.js +27 -17
  15. data/vendor/assets/javascripts/jquery.ui.plupload.js +308 -217
  16. data/vendor/assets/javascripts/moxie.js +906 -661
  17. data/vendor/assets/javascripts/plupload.dev.js +727 -537
  18. data/vendor/assets/javascripts/plupload/i18n/ar.js +2 -0
  19. data/vendor/assets/javascripts/plupload/i18n/bs.js +1 -0
  20. data/vendor/assets/javascripts/plupload/i18n/ca.js +2 -0
  21. data/vendor/assets/javascripts/plupload/i18n/cs.js +1 -0
  22. data/vendor/assets/javascripts/plupload/i18n/cy.js +1 -0
  23. data/vendor/assets/javascripts/plupload/i18n/da.js +1 -0
  24. data/vendor/assets/javascripts/plupload/i18n/de.js +2 -1
  25. data/vendor/assets/javascripts/plupload/i18n/el.js +1 -0
  26. data/vendor/assets/javascripts/plupload/i18n/en.js +1 -0
  27. data/vendor/assets/javascripts/plupload/i18n/es.js +2 -1
  28. data/vendor/assets/javascripts/plupload/i18n/et.js +1 -0
  29. data/vendor/assets/javascripts/plupload/i18n/fa.js +1 -0
  30. data/vendor/assets/javascripts/plupload/i18n/fi.js +1 -0
  31. data/vendor/assets/javascripts/plupload/i18n/fr.js +2 -1
  32. data/vendor/assets/javascripts/plupload/i18n/he.js +2 -0
  33. data/vendor/assets/javascripts/plupload/i18n/hr.js +1 -0
  34. data/vendor/assets/javascripts/plupload/i18n/hu.js +2 -1
  35. data/vendor/assets/javascripts/plupload/i18n/hy.js +1 -0
  36. data/vendor/assets/javascripts/plupload/i18n/id.js +2 -0
  37. data/vendor/assets/javascripts/plupload/i18n/it.js +1 -0
  38. data/vendor/assets/javascripts/plupload/i18n/ja.js +1 -0
  39. data/vendor/assets/javascripts/plupload/i18n/ka.js +1 -0
  40. data/vendor/assets/javascripts/plupload/i18n/kk.js +2 -0
  41. data/vendor/assets/javascripts/plupload/i18n/ko.js +1 -0
  42. data/vendor/assets/javascripts/plupload/i18n/lt.js +1 -0
  43. data/vendor/assets/javascripts/plupload/i18n/lv.js +2 -1
  44. data/vendor/assets/javascripts/plupload/i18n/nl.js +1 -0
  45. data/vendor/assets/javascripts/plupload/i18n/pl.js +1 -0
  46. data/vendor/assets/javascripts/plupload/i18n/pt_BR.js +1 -0
  47. data/vendor/assets/javascripts/plupload/i18n/ro.js +2 -1
  48. data/vendor/assets/javascripts/plupload/i18n/ru.js +2 -1
  49. data/vendor/assets/javascripts/plupload/i18n/sk.js +1 -0
  50. data/vendor/assets/javascripts/plupload/i18n/sr.js +1 -0
  51. data/vendor/assets/javascripts/plupload/i18n/sv.js +1 -0
  52. data/vendor/assets/javascripts/plupload/i18n/th_TH.js +1 -0
  53. data/vendor/assets/javascripts/plupload/i18n/tr.js +1 -0
  54. data/vendor/assets/javascripts/plupload/i18n/uk_UA.js +1 -0
  55. data/vendor/assets/javascripts/plupload/i18n/zh_CN.js +1 -0
  56. data/vendor/assets/javascripts/plupload/i18n/zh_TW.js +2 -0
  57. data/vendor/assets/misc/Moxie.swf +0 -0
  58. data/vendor/assets/misc/Moxie.xap +0 -0
  59. data/vendor/assets/stylesheets/{jquery.plupload.queue.scss → jquery.plupload.queue.css.erb} +15 -11
  60. data/vendor/assets/stylesheets/{jquery.ui.plupload.scss → jquery.ui.plupload.css.erb} +3 -3
  61. metadata +18 -12
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * mOxie - multi-runtime File API & XMLHttpRequest L2 Polyfill
3
- * v1.0.0
3
+ * v1.2.0
4
4
  *
5
5
  * Copyright 2013, Moxiecode Systems AB
6
6
  * Released under GPL License.
@@ -8,7 +8,7 @@
8
8
  * License: http://www.plupload.com/license
9
9
  * Contributing: http://www.plupload.com/contributing
10
10
  *
11
- * Date: 2013-09-23
11
+ * Date: 2014-01-16
12
12
  */
13
13
  /**
14
14
  * Compiled inline version. (Library mode)
@@ -252,6 +252,42 @@ define('moxie/core/utils/Basic', [], function() {
252
252
  }
253
253
  callNext(i);
254
254
  };
255
+
256
+
257
+ /**
258
+ Recieve an array of functions (usually async) to call in parallel, each function
259
+ receives a callback as first argument that it should call, when it completes. After
260
+ everything is complete, main callback is called. Passing truthy value to the
261
+ callback as a first argument will interrupt the process and invoke main callback
262
+ immediately.
263
+
264
+ @method inParallel
265
+ @static
266
+ @param {Array} queue Array of functions to call in sequence
267
+ @param {Function} cb Main callback that is called in the end, or in case of erro
268
+ */
269
+ var inParallel = function(queue, cb) {
270
+ var count = 0, num = queue.length, cbArgs = new Array(num);
271
+
272
+ each(queue, function(fn, i) {
273
+ fn(function(error) {
274
+ if (error) {
275
+ return cb(error);
276
+ }
277
+
278
+ var args = [].slice.call(arguments);
279
+ args.shift(); // strip error - undefined or not
280
+
281
+ cbArgs[i] = args;
282
+ count++;
283
+
284
+ if (count === num) {
285
+ cbArgs.unshift(null);
286
+ cb.apply(this, cbArgs);
287
+ }
288
+ });
289
+ });
290
+ };
255
291
 
256
292
 
257
293
  /**
@@ -429,6 +465,7 @@ define('moxie/core/utils/Basic', [], function() {
429
465
  each: each,
430
466
  isEmptyObj: isEmptyObj,
431
467
  inSeries: inSeries,
468
+ inParallel: inParallel,
432
469
  inArray: inArray,
433
470
  arrayDiff: arrayDiff,
434
471
  arrayIntersect: arrayIntersect,
@@ -493,15 +530,12 @@ define("moxie/core/I18n", [
493
530
  * @return {String} String with replaced tokens
494
531
  */
495
532
  sprintf: function(str) {
496
- var args = [].slice.call(arguments, 1), reStr = '';
533
+ var args = [].slice.call(arguments, 1);
497
534
 
498
- Basic.each(str.split(/%[a-z]/), function(part) {
499
- reStr += part;
500
- if (args.length) {
501
- reStr += args.shift();
502
- }
535
+ return str.replace(/%[a-z]/g, function() {
536
+ var value = args.shift();
537
+ return Basic.typeOf(value) !== 'undefined' ? value : '';
503
538
  });
504
- return reStr;
505
539
  }
506
540
  };
507
541
  });
@@ -543,7 +577,7 @@ define("moxie/core/utils/Mime", [
543
577
  "application/json,json," +
544
578
  "audio/mpeg,mp3 mpga mpega mp2," +
545
579
  "audio/x-wav,wav," +
546
- "audio/mp4,m4a," +
580
+ "audio/x-m4a,m4a," +
547
581
  "audio/ogg,oga ogg," +
548
582
  "audio/aiff,aiff aif," +
549
583
  "audio/flac,flac," +
@@ -715,109 +749,518 @@ define("moxie/core/utils/Env", [
715
749
  "moxie/core/utils/Basic"
716
750
  ], function(Basic) {
717
751
 
718
- var browser = [{
719
- s1: navigator.userAgent,
720
- s2: "Android",
721
- id: "Android Browser", // default or Dolphin
722
- sv: "Version"
723
- },{
724
- s1: navigator.userAgent, // string
725
- s2: "Chrome", // substring
726
- id: "Chrome" // identity
727
- },{
728
- s1: navigator.vendor,
729
- s2: "Apple",
730
- id: "Safari",
731
- sv: "Version" // version
732
- },{
733
- prop: window.opera && window.opera.buildNumber,
734
- id: "Opera",
735
- sv: "Version"
736
- },{
737
- s1: navigator.vendor,
738
- s2: "KDE",
739
- id: "Konqueror"
740
- },{
741
- s1: navigator.userAgent,
742
- s2: "Firefox",
743
- id: "Firefox"
744
- },{
745
- s1: navigator.vendor,
746
- s2: "Camino",
747
- id: "Camino"
748
- },{
749
- // for newer Netscapes (6+)
750
- s1: navigator.userAgent,
751
- s2: "Netscape",
752
- id: "Netscape"
753
- },{
754
- s1: navigator.userAgent,
755
- s2: "MSIE",
756
- id: "IE",
757
- sv: "MSIE"
758
- },{
759
- s1: navigator.userAgent,
760
- s2: "Gecko",
761
- id: "Mozilla",
762
- sv: "rv"
763
- }],
764
-
765
- os = [{
766
- s1: navigator.platform,
767
- s2: "Win",
768
- id: "Windows"
769
- },{
770
- s1: navigator.platform,
771
- s2: "Mac",
772
- id: "Mac"
773
- },{
774
- s1: navigator.userAgent,
775
- s2: "iPhone",
776
- id: "iOS"
777
- },{
778
- s1: navigator.userAgent,
779
- s2: "iPad",
780
- id: "iOS"
781
- },{
782
- s1: navigator.userAgent,
783
- s2: "Android",
784
- id: "Android"
785
- },{
786
- s1: navigator.platform,
787
- s2: "Linux",
788
- id: "Linux"
789
- }]
790
- , version;
791
-
792
- function getStr(data) {
793
- var str, prop;
794
-
795
- for (var i = 0; i < data.length; i++) {
796
- str = data[i].s1;
797
- prop = data[i].prop;
798
- version = data[i].sv || data[i].id;
799
-
800
- if (str) {
801
- if (str.indexOf(data[i].s2) != -1) {
802
- return data[i].id;
803
- }
804
- } else if (prop) {
805
- return data[i].id;
806
- }
807
- }
808
- }
809
-
810
-
811
- function getVer(str) {
812
- var index = str.indexOf(version);
752
+ // UAParser.js v0.6.2
753
+ // Lightweight JavaScript-based User-Agent string parser
754
+ // https://github.com/faisalman/ua-parser-js
755
+ //
756
+ // Copyright © 2012-2013 Faisalman <fyzlman@gmail.com>
757
+ // Dual licensed under GPLv2 & MIT
758
+
759
+ var UAParser = (function (undefined) {
760
+
761
+ //////////////
762
+ // Constants
763
+ /////////////
764
+
765
+
766
+ var EMPTY = '',
767
+ UNKNOWN = '?',
768
+ FUNC_TYPE = 'function',
769
+ UNDEF_TYPE = 'undefined',
770
+ OBJ_TYPE = 'object',
771
+ MAJOR = 'major',
772
+ MODEL = 'model',
773
+ NAME = 'name',
774
+ TYPE = 'type',
775
+ VENDOR = 'vendor',
776
+ VERSION = 'version',
777
+ ARCHITECTURE= 'architecture',
778
+ CONSOLE = 'console',
779
+ MOBILE = 'mobile',
780
+ TABLET = 'tablet';
781
+
782
+
783
+ ///////////
784
+ // Helper
785
+ //////////
786
+
787
+
788
+ var util = {
789
+ has : function (str1, str2) {
790
+ return str2.toLowerCase().indexOf(str1.toLowerCase()) !== -1;
791
+ },
792
+ lowerize : function (str) {
793
+ return str.toLowerCase();
794
+ }
795
+ };
813
796
 
814
- if (index == -1) {
815
- return;
816
- }
817
797
 
818
- return parseFloat(str.substring(index + version.length + 1));
798
+ ///////////////
799
+ // Map helper
800
+ //////////////
801
+
802
+
803
+ var mapper = {
804
+
805
+ rgx : function () {
806
+
807
+ // loop through all regexes maps
808
+ for (var result, i = 0, j, k, p, q, matches, match, args = arguments; i < args.length; i += 2) {
809
+
810
+ var regex = args[i], // even sequence (0,2,4,..)
811
+ props = args[i + 1]; // odd sequence (1,3,5,..)
812
+
813
+ // construct object barebones
814
+ if (typeof(result) === UNDEF_TYPE) {
815
+ result = {};
816
+ for (p in props) {
817
+ q = props[p];
818
+ if (typeof(q) === OBJ_TYPE) {
819
+ result[q[0]] = undefined;
820
+ } else {
821
+ result[q] = undefined;
822
+ }
823
+ }
824
+ }
825
+
826
+ // try matching uastring with regexes
827
+ for (j = k = 0; j < regex.length; j++) {
828
+ matches = regex[j].exec(this.getUA());
829
+ if (!!matches) {
830
+ for (p = 0; p < props.length; p++) {
831
+ match = matches[++k];
832
+ q = props[p];
833
+ // check if given property is actually array
834
+ if (typeof(q) === OBJ_TYPE && q.length > 0) {
835
+ if (q.length == 2) {
836
+ if (typeof(q[1]) == FUNC_TYPE) {
837
+ // assign modified match
838
+ result[q[0]] = q[1].call(this, match);
839
+ } else {
840
+ // assign given value, ignore regex match
841
+ result[q[0]] = q[1];
842
+ }
843
+ } else if (q.length == 3) {
844
+ // check whether function or regex
845
+ if (typeof(q[1]) === FUNC_TYPE && !(q[1].exec && q[1].test)) {
846
+ // call function (usually string mapper)
847
+ result[q[0]] = match ? q[1].call(this, match, q[2]) : undefined;
848
+ } else {
849
+ // sanitize match using given regex
850
+ result[q[0]] = match ? match.replace(q[1], q[2]) : undefined;
851
+ }
852
+ } else if (q.length == 4) {
853
+ result[q[0]] = match ? q[3].call(this, match.replace(q[1], q[2])) : undefined;
854
+ }
855
+ } else {
856
+ result[q] = match ? match : undefined;
857
+ }
858
+ }
859
+ break;
860
+ }
861
+ }
862
+
863
+ if(!!matches) break; // break the loop immediately if match found
864
+ }
865
+ return result;
866
+ },
867
+
868
+ str : function (str, map) {
869
+
870
+ for (var i in map) {
871
+ // check if array
872
+ if (typeof(map[i]) === OBJ_TYPE && map[i].length > 0) {
873
+ for (var j = 0; j < map[i].length; j++) {
874
+ if (util.has(map[i][j], str)) {
875
+ return (i === UNKNOWN) ? undefined : i;
876
+ }
877
+ }
878
+ } else if (util.has(map[i], str)) {
879
+ return (i === UNKNOWN) ? undefined : i;
880
+ }
881
+ }
882
+ return str;
883
+ }
884
+ };
885
+
886
+
887
+ ///////////////
888
+ // String map
889
+ //////////////
890
+
891
+
892
+ var maps = {
893
+
894
+ browser : {
895
+ oldsafari : {
896
+ major : {
897
+ '1' : ['/8', '/1', '/3'],
898
+ '2' : '/4',
899
+ '?' : '/'
900
+ },
901
+ version : {
902
+ '1.0' : '/8',
903
+ '1.2' : '/1',
904
+ '1.3' : '/3',
905
+ '2.0' : '/412',
906
+ '2.0.2' : '/416',
907
+ '2.0.3' : '/417',
908
+ '2.0.4' : '/419',
909
+ '?' : '/'
910
+ }
911
+ }
912
+ },
913
+
914
+ device : {
915
+ sprint : {
916
+ model : {
917
+ 'Evo Shift 4G' : '7373KT'
918
+ },
919
+ vendor : {
920
+ 'HTC' : 'APA',
921
+ 'Sprint' : 'Sprint'
922
+ }
923
+ }
924
+ },
925
+
926
+ os : {
927
+ windows : {
928
+ version : {
929
+ 'ME' : '4.90',
930
+ 'NT 3.11' : 'NT3.51',
931
+ 'NT 4.0' : 'NT4.0',
932
+ '2000' : 'NT 5.0',
933
+ 'XP' : ['NT 5.1', 'NT 5.2'],
934
+ 'Vista' : 'NT 6.0',
935
+ '7' : 'NT 6.1',
936
+ '8' : 'NT 6.2',
937
+ '8.1' : 'NT 6.3',
938
+ 'RT' : 'ARM'
939
+ }
940
+ }
941
+ }
942
+ };
943
+
944
+
945
+ //////////////
946
+ // Regex map
947
+ /////////////
948
+
949
+
950
+ var regexes = {
951
+
952
+ browser : [[
953
+
954
+ // Presto based
955
+ /(opera\smini)\/((\d+)?[\w\.-]+)/i, // Opera Mini
956
+ /(opera\s[mobiletab]+).+version\/((\d+)?[\w\.-]+)/i, // Opera Mobi/Tablet
957
+ /(opera).+version\/((\d+)?[\w\.]+)/i, // Opera > 9.80
958
+ /(opera)[\/\s]+((\d+)?[\w\.]+)/i // Opera < 9.80
959
+
960
+ ], [NAME, VERSION, MAJOR], [
961
+
962
+ /\s(opr)\/((\d+)?[\w\.]+)/i // Opera Webkit
963
+ ], [[NAME, 'Opera'], VERSION, MAJOR], [
964
+
965
+ // Mixed
966
+ /(kindle)\/((\d+)?[\w\.]+)/i, // Kindle
967
+ /(lunascape|maxthon|netfront|jasmine|blazer)[\/\s]?((\d+)?[\w\.]+)*/i,
968
+ // Lunascape/Maxthon/Netfront/Jasmine/Blazer
969
+
970
+ // Trident based
971
+ /(avant\s|iemobile|slim|baidu)(?:browser)?[\/\s]?((\d+)?[\w\.]*)/i,
972
+ // Avant/IEMobile/SlimBrowser/Baidu
973
+ /(?:ms|\()(ie)\s((\d+)?[\w\.]+)/i, // Internet Explorer
974
+
975
+ // Webkit/KHTML based
976
+ /(rekonq)((?:\/)[\w\.]+)*/i, // Rekonq
977
+ /(chromium|flock|rockmelt|midori|epiphany|silk|skyfire|ovibrowser|bolt|iron)\/((\d+)?[\w\.-]+)/i
978
+ // Chromium/Flock/RockMelt/Midori/Epiphany/Silk/Skyfire/Bolt/Iron
979
+ ], [NAME, VERSION, MAJOR], [
980
+
981
+ /(trident).+rv[:\s]((\d+)?[\w\.]+).+like\sgecko/i // IE11
982
+ ], [[NAME, 'IE'], VERSION, MAJOR], [
983
+
984
+ /(yabrowser)\/((\d+)?[\w\.]+)/i // Yandex
985
+ ], [[NAME, 'Yandex'], VERSION, MAJOR], [
986
+
987
+ /(comodo_dragon)\/((\d+)?[\w\.]+)/i // Comodo Dragon
988
+ ], [[NAME, /_/g, ' '], VERSION, MAJOR], [
989
+
990
+ /(chrome|omniweb|arora|[tizenoka]{5}\s?browser)\/v?((\d+)?[\w\.]+)/i
991
+ // Chrome/OmniWeb/Arora/Tizen/Nokia
992
+ ], [NAME, VERSION, MAJOR], [
993
+
994
+ /(dolfin)\/((\d+)?[\w\.]+)/i // Dolphin
995
+ ], [[NAME, 'Dolphin'], VERSION, MAJOR], [
996
+
997
+ /((?:android.+)crmo|crios)\/((\d+)?[\w\.]+)/i // Chrome for Android/iOS
998
+ ], [[NAME, 'Chrome'], VERSION, MAJOR], [
999
+
1000
+ /((?:android.+))version\/((\d+)?[\w\.]+)\smobile\ssafari/i // Android Browser
1001
+ ], [[NAME, 'Android Browser'], VERSION, MAJOR], [
1002
+
1003
+ /version\/((\d+)?[\w\.]+).+?mobile\/\w+\s(safari)/i // Mobile Safari
1004
+ ], [VERSION, MAJOR, [NAME, 'Mobile Safari']], [
1005
+
1006
+ /version\/((\d+)?[\w\.]+).+?(mobile\s?safari|safari)/i // Safari & Safari Mobile
1007
+ ], [VERSION, MAJOR, NAME], [
1008
+
1009
+ /webkit.+?(mobile\s?safari|safari)((\/[\w\.]+))/i // Safari < 3.0
1010
+ ], [NAME, [MAJOR, mapper.str, maps.browser.oldsafari.major], [VERSION, mapper.str, maps.browser.oldsafari.version]], [
1011
+
1012
+ /(konqueror)\/((\d+)?[\w\.]+)/i, // Konqueror
1013
+ /(webkit|khtml)\/((\d+)?[\w\.]+)/i
1014
+ ], [NAME, VERSION, MAJOR], [
1015
+
1016
+ // Gecko based
1017
+ /(navigator|netscape)\/((\d+)?[\w\.-]+)/i // Netscape
1018
+ ], [[NAME, 'Netscape'], VERSION, MAJOR], [
1019
+ /(swiftfox)/i, // Swiftfox
1020
+ /(icedragon|iceweasel|camino|chimera|fennec|maemo\sbrowser|minimo|conkeror)[\/\s]?((\d+)?[\w\.\+]+)/i,
1021
+ // IceDragon/Iceweasel/Camino/Chimera/Fennec/Maemo/Minimo/Conkeror
1022
+ /(firefox|seamonkey|k-meleon|icecat|iceape|firebird|phoenix)\/((\d+)?[\w\.-]+)/i,
1023
+ // Firefox/SeaMonkey/K-Meleon/IceCat/IceApe/Firebird/Phoenix
1024
+ /(mozilla)\/((\d+)?[\w\.]+).+rv\:.+gecko\/\d+/i, // Mozilla
1025
+
1026
+ // Other
1027
+ /(uc\s?browser|polaris|lynx|dillo|icab|doris|amaya|w3m|netsurf|qqbrowser)[\/\s]?((\d+)?[\w\.]+)/i,
1028
+ // UCBrowser/Polaris/Lynx/Dillo/iCab/Doris/Amaya/w3m/NetSurf/QQBrowser
1029
+ /(links)\s\(((\d+)?[\w\.]+)/i, // Links
1030
+ /(gobrowser)\/?((\d+)?[\w\.]+)*/i, // GoBrowser
1031
+ /(ice\s?browser)\/v?((\d+)?[\w\._]+)/i, // ICE Browser
1032
+ /(mosaic)[\/\s]((\d+)?[\w\.]+)/i // Mosaic
1033
+ ], [NAME, VERSION, MAJOR]
1034
+ ],
1035
+
1036
+ engine : [[
1037
+
1038
+ /(presto)\/([\w\.]+)/i, // Presto
1039
+ /(webkit|trident|netfront|netsurf|amaya|lynx|w3m)\/([\w\.]+)/i, // WebKit/Trident/NetFront/NetSurf/Amaya/Lynx/w3m
1040
+ /(khtml|tasman|links)[\/\s]\(?([\w\.]+)/i, // KHTML/Tasman/Links
1041
+ /(icab)[\/\s]([23]\.[\d\.]+)/i // iCab
1042
+ ], [NAME, VERSION], [
1043
+
1044
+ /rv\:([\w\.]+).*(gecko)/i // Gecko
1045
+ ], [VERSION, NAME]
1046
+ ],
1047
+
1048
+ os : [[
1049
+
1050
+ // Windows based
1051
+ /(windows)\snt\s6\.2;\s(arm)/i, // Windows RT
1052
+ /(windows\sphone(?:\sos)*|windows\smobile|windows)[\s\/]?([ntce\d\.\s]+\w)/i
1053
+ ], [NAME, [VERSION, mapper.str, maps.os.windows.version]], [
1054
+ /(win(?=3|9|n)|win\s9x\s)([nt\d\.]+)/i
1055
+ ], [[NAME, 'Windows'], [VERSION, mapper.str, maps.os.windows.version]], [
1056
+
1057
+ // Mobile/Embedded OS
1058
+ /\((bb)(10);/i // BlackBerry 10
1059
+ ], [[NAME, 'BlackBerry'], VERSION], [
1060
+ /(blackberry)\w*\/?([\w\.]+)*/i, // Blackberry
1061
+ /(tizen)\/([\w\.]+)/i, // Tizen
1062
+ /(android|webos|palm\os|qnx|bada|rim\stablet\sos|meego)[\/\s-]?([\w\.]+)*/i
1063
+ // Android/WebOS/Palm/QNX/Bada/RIM/MeeGo
1064
+ ], [NAME, VERSION], [
1065
+ /(symbian\s?os|symbos|s60(?=;))[\/\s-]?([\w\.]+)*/i // Symbian
1066
+ ], [[NAME, 'Symbian'], VERSION],[
1067
+ /mozilla.+\(mobile;.+gecko.+firefox/i // Firefox OS
1068
+ ], [[NAME, 'Firefox OS'], VERSION], [
1069
+
1070
+ // Console
1071
+ /(nintendo|playstation)\s([wids3portablevu]+)/i, // Nintendo/Playstation
1072
+
1073
+ // GNU/Linux based
1074
+ /(mint)[\/\s\(]?(\w+)*/i, // Mint
1075
+ /(joli|[kxln]?ubuntu|debian|[open]*suse|gentoo|arch|slackware|fedora|mandriva|centos|pclinuxos|redhat|zenwalk)[\/\s-]?([\w\.-]+)*/i,
1076
+ // Joli/Ubuntu/Debian/SUSE/Gentoo/Arch/Slackware
1077
+ // Fedora/Mandriva/CentOS/PCLinuxOS/RedHat/Zenwalk
1078
+ /(hurd|linux)\s?([\w\.]+)*/i, // Hurd/Linux
1079
+ /(gnu)\s?([\w\.]+)*/i // GNU
1080
+ ], [NAME, VERSION], [
1081
+
1082
+ /(cros)\s[\w]+\s([\w\.]+\w)/i // Chromium OS
1083
+ ], [[NAME, 'Chromium OS'], VERSION],[
1084
+
1085
+ // Solaris
1086
+ /(sunos)\s?([\w\.]+\d)*/i // Solaris
1087
+ ], [[NAME, 'Solaris'], VERSION], [
1088
+
1089
+ // BSD based
1090
+ /\s([frentopc-]{0,4}bsd|dragonfly)\s?([\w\.]+)*/i // FreeBSD/NetBSD/OpenBSD/PC-BSD/DragonFly
1091
+ ], [NAME, VERSION],[
1092
+
1093
+ /(ip[honead]+)(?:.*os\s*([\w]+)*\slike\smac|;\sopera)/i // iOS
1094
+ ], [[NAME, 'iOS'], [VERSION, /_/g, '.']], [
1095
+
1096
+ /(mac\sos\sx)\s?([\w\s\.]+\w)*/i // Mac OS
1097
+ ], [NAME, [VERSION, /_/g, '.']], [
1098
+
1099
+ // Other
1100
+ /(haiku)\s(\w+)/i, // Haiku
1101
+ /(aix)\s((\d)(?=\.|\)|\s)[\w\.]*)*/i, // AIX
1102
+ /(macintosh|mac(?=_powerpc)|plan\s9|minix|beos|os\/2|amigaos|morphos|risc\sos)/i,
1103
+ // Plan9/Minix/BeOS/OS2/AmigaOS/MorphOS/RISCOS
1104
+ /(unix)\s?([\w\.]+)*/i // UNIX
1105
+ ], [NAME, VERSION]
1106
+ ]
1107
+ };
1108
+
1109
+
1110
+ /////////////////
1111
+ // Constructor
1112
+ ////////////////
1113
+
1114
+
1115
+ var UAParser = function (uastring) {
1116
+
1117
+ var ua = uastring || ((window && window.navigator && window.navigator.userAgent) ? window.navigator.userAgent : EMPTY);
1118
+
1119
+ this.getBrowser = function () {
1120
+ return mapper.rgx.apply(this, regexes.browser);
1121
+ };
1122
+ this.getEngine = function () {
1123
+ return mapper.rgx.apply(this, regexes.engine);
1124
+ };
1125
+ this.getOS = function () {
1126
+ return mapper.rgx.apply(this, regexes.os);
1127
+ };
1128
+ this.getResult = function() {
1129
+ return {
1130
+ ua : this.getUA(),
1131
+ browser : this.getBrowser(),
1132
+ engine : this.getEngine(),
1133
+ os : this.getOS()
1134
+ };
1135
+ };
1136
+ this.getUA = function () {
1137
+ return ua;
1138
+ };
1139
+ this.setUA = function (uastring) {
1140
+ ua = uastring;
1141
+ return this;
1142
+ };
1143
+ this.setUA(ua);
1144
+ };
1145
+
1146
+ return new UAParser().getResult();
1147
+ })();
1148
+
1149
+
1150
+ function version_compare(v1, v2, operator) {
1151
+ // From: http://phpjs.org/functions
1152
+ // + original by: Philippe Jausions (http://pear.php.net/user/jausions)
1153
+ // + original by: Aidan Lister (http://aidanlister.com/)
1154
+ // + reimplemented by: Kankrelune (http://www.webfaktory.info/)
1155
+ // + improved by: Brett Zamir (http://brett-zamir.me)
1156
+ // + improved by: Scott Baker
1157
+ // + improved by: Theriault
1158
+ // * example 1: version_compare('8.2.5rc', '8.2.5a');
1159
+ // * returns 1: 1
1160
+ // * example 2: version_compare('8.2.50', '8.2.52', '<');
1161
+ // * returns 2: true
1162
+ // * example 3: version_compare('5.3.0-dev', '5.3.0');
1163
+ // * returns 3: -1
1164
+ // * example 4: version_compare('4.1.0.52','4.01.0.51');
1165
+ // * returns 4: 1
1166
+
1167
+ // Important: compare must be initialized at 0.
1168
+ var i = 0,
1169
+ x = 0,
1170
+ compare = 0,
1171
+ // vm maps textual PHP versions to negatives so they're less than 0.
1172
+ // PHP currently defines these as CASE-SENSITIVE. It is important to
1173
+ // leave these as negatives so that they can come before numerical versions
1174
+ // and as if no letters were there to begin with.
1175
+ // (1alpha is < 1 and < 1.1 but > 1dev1)
1176
+ // If a non-numerical value can't be mapped to this table, it receives
1177
+ // -7 as its value.
1178
+ vm = {
1179
+ 'dev': -6,
1180
+ 'alpha': -5,
1181
+ 'a': -5,
1182
+ 'beta': -4,
1183
+ 'b': -4,
1184
+ 'RC': -3,
1185
+ 'rc': -3,
1186
+ '#': -2,
1187
+ 'p': 1,
1188
+ 'pl': 1
1189
+ },
1190
+ // This function will be called to prepare each version argument.
1191
+ // It replaces every _, -, and + with a dot.
1192
+ // It surrounds any nonsequence of numbers/dots with dots.
1193
+ // It replaces sequences of dots with a single dot.
1194
+ // version_compare('4..0', '4.0') == 0
1195
+ // Important: A string of 0 length needs to be converted into a value
1196
+ // even less than an unexisting value in vm (-7), hence [-8].
1197
+ // It's also important to not strip spaces because of this.
1198
+ // version_compare('', ' ') == 1
1199
+ prepVersion = function (v) {
1200
+ v = ('' + v).replace(/[_\-+]/g, '.');
1201
+ v = v.replace(/([^.\d]+)/g, '.$1.').replace(/\.{2,}/g, '.');
1202
+ return (!v.length ? [-8] : v.split('.'));
1203
+ },
1204
+ // This converts a version component to a number.
1205
+ // Empty component becomes 0.
1206
+ // Non-numerical component becomes a negative number.
1207
+ // Numerical component becomes itself as an integer.
1208
+ numVersion = function (v) {
1209
+ return !v ? 0 : (isNaN(v) ? vm[v] || -7 : parseInt(v, 10));
1210
+ };
1211
+
1212
+ v1 = prepVersion(v1);
1213
+ v2 = prepVersion(v2);
1214
+ x = Math.max(v1.length, v2.length);
1215
+ for (i = 0; i < x; i++) {
1216
+ if (v1[i] == v2[i]) {
1217
+ continue;
1218
+ }
1219
+ v1[i] = numVersion(v1[i]);
1220
+ v2[i] = numVersion(v2[i]);
1221
+ if (v1[i] < v2[i]) {
1222
+ compare = -1;
1223
+ break;
1224
+ } else if (v1[i] > v2[i]) {
1225
+ compare = 1;
1226
+ break;
1227
+ }
1228
+ }
1229
+ if (!operator) {
1230
+ return compare;
1231
+ }
1232
+
1233
+ // Important: operator is CASE-SENSITIVE.
1234
+ // "No operator" seems to be treated as "<."
1235
+ // Any other values seem to make the function return null.
1236
+ switch (operator) {
1237
+ case '>':
1238
+ case 'gt':
1239
+ return (compare > 0);
1240
+ case '>=':
1241
+ case 'ge':
1242
+ return (compare >= 0);
1243
+ case '<=':
1244
+ case 'le':
1245
+ return (compare <= 0);
1246
+ case '==':
1247
+ case '=':
1248
+ case 'eq':
1249
+ return (compare === 0);
1250
+ case '<>':
1251
+ case '!=':
1252
+ case 'ne':
1253
+ return (compare !== 0);
1254
+ case '':
1255
+ case '<':
1256
+ case 'lt':
1257
+ return (compare < 0);
1258
+ default:
1259
+ return null;
1260
+ }
819
1261
  }
820
1262
 
1263
+
821
1264
  var can = (function() {
822
1265
  var caps = {
823
1266
  define_property: (function() {
@@ -851,7 +1294,7 @@ define("moxie/core/utils/Env", [
851
1294
  try {
852
1295
  if (Basic.inArray(responseType, ['', 'text', 'document']) !== -1) {
853
1296
  return true;
854
- } else if (window.XMLHttpRequest){
1297
+ } else if (window.XMLHttpRequest) {
855
1298
  var xhr = new XMLHttpRequest();
856
1299
  xhr.open('get', '/'); // otherwise Gecko throws an exception
857
1300
  if ('responseType' in xhr) {
@@ -903,16 +1346,26 @@ define("moxie/core/utils/Env", [
903
1346
  };
904
1347
  }());
905
1348
 
1349
+
906
1350
  var Env = {
907
1351
  can: can,
908
- browser: getStr(browser),
909
- version: getVer(navigator.userAgent) || getVer(navigator.appVersion),
910
- OS: getStr(os),
1352
+
1353
+ browser: UAParser.browser.name,
1354
+ version: parseFloat(UAParser.browser.major),
1355
+ os: UAParser.os.name, // everybody intuitively types it in a lowercase for some reason
1356
+ osVersion: UAParser.os.version,
1357
+
1358
+ verComp: version_compare,
1359
+
911
1360
  swf_url: "../flash/Moxie.swf",
912
1361
  xap_url: "../silverlight/Moxie.xap",
913
1362
  global_event_dispatcher: "moxie.core.EventTarget.instance.dispatchEvent"
914
1363
  };
915
1364
 
1365
+ // for backward compatibility
1366
+ // @deprecated Use `Env.os` instead
1367
+ Env.OS = Env.os;
1368
+
916
1369
  return Env;
917
1370
  });
918
1371
 
@@ -942,7 +1395,6 @@ define('moxie/core/utils/Dom', ['moxie/core/utils/Env'], function(Env) {
942
1395
  if (typeof id !== 'string') {
943
1396
  return id;
944
1397
  }
945
-
946
1398
  return document.getElementById(id);
947
1399
  };
948
1400
 
@@ -955,14 +1407,11 @@ define('moxie/core/utils/Dom', ['moxie/core/utils/Env'], function(Env) {
955
1407
  @param {String} name Class name
956
1408
  */
957
1409
  var hasClass = function(obj, name) {
958
- var regExp;
959
-
960
- if (obj.className === '') {
1410
+ if (!obj.className) {
961
1411
  return false;
962
1412
  }
963
1413
 
964
- regExp = new RegExp("(^|\\s+)"+name+"(\\s+|$)");
965
-
1414
+ var regExp = new RegExp("(^|\\s+)"+name+"(\\s+|$)");
966
1415
  return regExp.test(obj.className);
967
1416
  };
968
1417
 
@@ -976,7 +1425,7 @@ define('moxie/core/utils/Dom', ['moxie/core/utils/Env'], function(Env) {
976
1425
  */
977
1426
  var addClass = function(obj, name) {
978
1427
  if (!hasClass(obj, name)) {
979
- obj.className = obj.className === '' ? name : obj.className.replace(/\s+$/, '') + ' ' + name;
1428
+ obj.className = !obj.className ? name : obj.className.replace(/\s+$/, '') + ' ' + name;
980
1429
  }
981
1430
  };
982
1431
 
@@ -989,11 +1438,12 @@ define('moxie/core/utils/Dom', ['moxie/core/utils/Env'], function(Env) {
989
1438
  @param {String} name Class name
990
1439
  */
991
1440
  var removeClass = function(obj, name) {
992
- var regExp = new RegExp("(^|\\s+)"+name+"(\\s+|$)");
993
-
994
- obj.className = obj.className.replace(regExp, function($0, $1, $2) {
995
- return $1 === ' ' && $2 === ' ' ? ' ' : '';
996
- });
1441
+ if (obj.className) {
1442
+ var regExp = new RegExp("(^|\\s+)"+name+"(\\s+|$)");
1443
+ obj.className = obj.className.replace(regExp, function($0, $1, $2) {
1444
+ return $1 === ' ' && $2 === ' ' ? ' ' : '';
1445
+ });
1446
+ }
997
1447
  };
998
1448
 
999
1449
  /**
@@ -1408,7 +1858,7 @@ define('moxie/core/EventTarget', [
1408
1858
  @return {Boolean} true by default and false if any handler returned false
1409
1859
  */
1410
1860
  dispatchEvent: function(type) {
1411
- var uid, list, args, tmpEvt, evt = {};
1861
+ var uid, list, args, tmpEvt, evt = {}, result = true, undef;
1412
1862
 
1413
1863
  if (Basic.typeOf(type) !== 'string') {
1414
1864
  // we can't use original object directly (because of Silverlight)
@@ -1417,7 +1867,7 @@ define('moxie/core/EventTarget', [
1417
1867
  if (Basic.typeOf(tmpEvt.type) === 'string') {
1418
1868
  type = tmpEvt.type;
1419
1869
 
1420
- if (tmpEvt.total && tmpEvt.loaded) { // progress event
1870
+ if (tmpEvt.total !== undef && tmpEvt.loaded !== undef) { // progress event
1421
1871
  evt.total = tmpEvt.total;
1422
1872
  evt.loaded = tmpEvt.loaded;
1423
1873
  }
@@ -1471,10 +1921,12 @@ define('moxie/core/EventTarget', [
1471
1921
  }
1472
1922
  });
1473
1923
  if (queue.length) {
1474
- Basic.inSeries(queue);
1924
+ Basic.inSeries(queue, function(err) {
1925
+ result = !err;
1926
+ });
1475
1927
  }
1476
1928
  }
1477
- return true;
1929
+ return result;
1478
1930
  },
1479
1931
 
1480
1932
  /**
@@ -1514,7 +1966,7 @@ define('moxie/core/EventTarget', [
1514
1966
  @protected
1515
1967
  */
1516
1968
  trigger: function() {
1517
- this.dispatchEvent.apply(this, arguments);
1969
+ return this.dispatchEvent.apply(this, arguments);
1518
1970
  },
1519
1971
 
1520
1972
 
@@ -1759,9 +2211,9 @@ define('moxie/runtime/Runtime', [
1759
2211
  @param {String} type Sanitized name of the runtime
1760
2212
  @param {Object} [caps] Set of capabilities that differentiate specified runtime
1761
2213
  @param {Object} [modeCaps] Set of capabilities that do require specific operational mode
1762
- @param {String} [defaultMode='browser'] Default operational mode to choose if no required capabilities were requested
2214
+ @param {String} [preferredMode='browser'] Preferred operational mode to choose if no required capabilities were requested
1763
2215
  */
1764
- function Runtime(options, type, caps, modeCaps, defaultMode) {
2216
+ function Runtime(options, type, caps, modeCaps, preferredMode) {
1765
2217
  /**
1766
2218
  Dispatched when runtime is initialized and ready.
1767
2219
  Results in RuntimeInit on a connected component.
@@ -1779,67 +2231,10 @@ define('moxie/runtime/Runtime', [
1779
2231
  var self = this
1780
2232
  , _shim
1781
2233
  , _uid = Basic.guid(type + '_')
2234
+ , defaultMode = preferredMode || 'browser'
1782
2235
  ;
1783
2236
 
1784
-
1785
- /**
1786
- Runtime (not native one) may operate in browser or client mode.
1787
-
1788
- @method _setMode
1789
- @private
1790
- @param {Object} [modeCaps] Set of capabilities that do require specific operational mode
1791
- @param {Object} [defaultMode] The mode to switch to if modeCaps or requiredCaps are empty
1792
- */
1793
- function _setMode(modeCaps, defaultMode) {
1794
- var mode = null
1795
- , rc = options && options.required_caps
1796
- ;
1797
-
1798
- defaultMode = defaultMode || 'browser';
1799
-
1800
- // mode can be effectively set only once
1801
- if (this.mode !== null) {
1802
- return this.mode;
1803
- }
1804
-
1805
- if (rc && !Basic.isEmptyObj(modeCaps)) {
1806
- // loop over required caps and check if they do require the same mode
1807
- Basic.each(rc, function(value, cap) {
1808
- if (modeCaps.hasOwnProperty(cap)) {
1809
- var capMode = modeCaps[cap](value);
1810
-
1811
- // make sure we always have an array
1812
- if (typeof(capMode) === 'string') {
1813
- capMode = [capMode];
1814
- }
1815
-
1816
- if (!mode) {
1817
- mode = capMode;
1818
- } else if (!(mode = Basic.arrayIntersect(mode, capMode))) {
1819
- // if cap requires conflicting mode - runtime cannot fulfill required caps
1820
- return (mode = false);
1821
- }
1822
- }
1823
- });
1824
-
1825
- if (mode) {
1826
- this.mode = Basic.inArray(defaultMode, mode) !== -1 ? defaultMode : mode[0];
1827
- } else if (mode === false) {
1828
- this.mode = false;
1829
- }
1830
- }
1831
-
1832
- // if mode still not defined
1833
- if (this.mode === null) {
1834
- this.mode = defaultMode;
1835
- }
1836
-
1837
- // once we got the mode, test against all caps
1838
- if (this.mode && rc && !this.can(rc)) {
1839
- this.mode = false;
1840
- }
1841
- }
1842
-
2237
+ options = options || {};
1843
2238
 
1844
2239
  // register runtime in private hash
1845
2240
  runtimes[_uid] = this;
@@ -1903,7 +2298,12 @@ define('moxie/runtime/Runtime', [
1903
2298
  // e.g. runtime.can('use_http_method', 'put')
1904
2299
  use_http_method: true
1905
2300
  }, caps);
1906
-
2301
+
2302
+
2303
+ // default to the mode that is compatible with preferred caps
2304
+ if (options.preferred_caps) {
2305
+ defaultMode = Runtime.getMode(modeCaps, options.preferred_caps, defaultMode);
2306
+ }
1907
2307
 
1908
2308
  // small extension factory here (is meant to be extended with actual extensions constructors)
1909
2309
  _shim = (function() {
@@ -1974,7 +2374,7 @@ define('moxie/runtime/Runtime', [
1974
2374
  @private
1975
2375
  @type {String|Boolean} current mode or false, if none possible
1976
2376
  */
1977
- mode: null,
2377
+ mode: Runtime.getMode(modeCaps, (options.required_caps), defaultMode),
1978
2378
 
1979
2379
  /**
1980
2380
  id of the DOM container for the runtime (if available)
@@ -2135,7 +2535,10 @@ define('moxie/runtime/Runtime', [
2135
2535
  }
2136
2536
  });
2137
2537
 
2138
- _setMode.call(this, modeCaps, defaultMode);
2538
+ // once we got the mode, test against all caps
2539
+ if (this.mode && options.required_caps && !this.can(options.required_caps)) {
2540
+ this.mode = false;
2541
+ }
2139
2542
  }
2140
2543
 
2141
2544
 
@@ -2205,6 +2608,7 @@ define('moxie/runtime/Runtime', [
2205
2608
  return {
2206
2609
  uid: runtime.uid,
2207
2610
  type: runtime.type,
2611
+ mode: runtime.mode,
2208
2612
  can: function() {
2209
2613
  return runtime.can.apply(runtime, arguments);
2210
2614
  }
@@ -2282,6 +2686,53 @@ define('moxie/runtime/Runtime', [
2282
2686
  };
2283
2687
 
2284
2688
 
2689
+ /**
2690
+ Figure out an operational mode for the specified set of capabilities.
2691
+
2692
+ @method getMode
2693
+ @static
2694
+ @param {Object} modeCaps Set of capabilities that depend on particular runtime mode
2695
+ @param {Object} [requiredCaps] Supplied set of capabilities to find operational mode for
2696
+ @param {String|Boolean} [defaultMode='browser'] Default mode to use
2697
+ @return {String|Boolean} Compatible operational mode
2698
+ */
2699
+ Runtime.getMode = function(modeCaps, requiredCaps, defaultMode) {
2700
+ var mode = null;
2701
+
2702
+ if (Basic.typeOf(defaultMode) === 'undefined') { // only if not specified
2703
+ defaultMode = 'browser';
2704
+ }
2705
+
2706
+ if (requiredCaps && !Basic.isEmptyObj(modeCaps)) {
2707
+ // loop over required caps and check if they do require the same mode
2708
+ Basic.each(requiredCaps, function(value, cap) {
2709
+ if (modeCaps.hasOwnProperty(cap)) {
2710
+ var capMode = modeCaps[cap](value);
2711
+
2712
+ // make sure we always have an array
2713
+ if (typeof(capMode) === 'string') {
2714
+ capMode = [capMode];
2715
+ }
2716
+
2717
+ if (!mode) {
2718
+ mode = capMode;
2719
+ } else if (!(mode = Basic.arrayIntersect(mode, capMode))) {
2720
+ // if cap requires conflicting mode - runtime cannot fulfill required caps
2721
+ return (mode = false);
2722
+ }
2723
+ }
2724
+ });
2725
+
2726
+ if (mode) {
2727
+ return Basic.inArray(defaultMode, mode) !== -1 ? defaultMode : mode[0];
2728
+ } else if (mode === false) {
2729
+ return false;
2730
+ }
2731
+ }
2732
+ return defaultMode;
2733
+ };
2734
+
2735
+
2285
2736
  /**
2286
2737
  Capability check that always returns true
2287
2738
 
@@ -2927,6 +3378,15 @@ define('moxie/file/FileInput', [
2927
3378
  @type {String}
2928
3379
  */
2929
3380
  ruid: null,
3381
+
3382
+ /**
3383
+ Unique id of the runtime container. Useful to get hold of it for various manipulations.
3384
+
3385
+ @property shimid
3386
+ @protected
3387
+ @type {String}
3388
+ */
3389
+ shimid: null,
2930
3390
 
2931
3391
  /**
2932
3392
  Array of selected mOxie.File objects
@@ -2947,6 +3407,7 @@ define('moxie/file/FileInput', [
2947
3407
 
2948
3408
  self.bind('RuntimeInit', function(e, runtime) {
2949
3409
  self.ruid = runtime.uid;
3410
+ self.shimid = runtime.shimid;
2950
3411
 
2951
3412
  self.bind("Ready", function() {
2952
3413
  self.trigger("Refresh");
@@ -3593,10 +4054,10 @@ define('moxie/core/utils/Url', [], function() {
3593
4054
  @method parseUrl
3594
4055
  @for Utils
3595
4056
  @static
3596
- @param {String} str Url to parse (defaults to empty string if undefined)
4057
+ @param {String} url Url to parse (defaults to empty string if undefined)
3597
4058
  @return {Object} Hash containing extracted uri components
3598
4059
  */
3599
- var parseUrl = function(str) {
4060
+ var parseUrl = function(url, currentUrl) {
3600
4061
  var key = ['source', 'scheme', 'authority', 'userInfo', 'user', 'pass', 'host', 'port', 'relative', 'path', 'directory', 'file', 'query', 'fragment']
3601
4062
  , i = key.length
3602
4063
  , ports = {
@@ -3605,7 +4066,7 @@ define('moxie/core/utils/Url', [], function() {
3605
4066
  }
3606
4067
  , uri = {}
3607
4068
  , regex = /^(?:([^:\/?#]+):)?(?:\/\/()(?:(?:()(?:([^:@]*):?([^:@]*))?@)?([^:\/?#]*)(?::(\d*))?))?()(?:(()(?:(?:[^?#\/]*\/)*)()(?:[^?#]*))(?:\\?([^#]*))?(?:#(.*))?)/
3608
- , m = regex.exec(str || '') // default to empty string if undefined
4069
+ , m = regex.exec(url || '')
3609
4070
  ;
3610
4071
 
3611
4072
  while (i--) {
@@ -3614,34 +4075,43 @@ define('moxie/core/utils/Url', [], function() {
3614
4075
  }
3615
4076
  }
3616
4077
 
3617
- if (/^[^\/]/.test(uri.path) && !uri.scheme) { // when url is relative, we need to figure out the path ourselves
3618
- var path = document.location.pathname;
3619
- // if path ends with a filename, strip it
3620
- if (!/(\/|\/[^\.]+)$/.test(path)) {
3621
- path = path.replace(/[^\/]+$/, '');
4078
+ // when url is relative, we set the origin and the path ourselves
4079
+ if (!uri.scheme) {
4080
+ // come up with defaults
4081
+ if (!currentUrl || typeof(currentUrl) === 'string') {
4082
+ currentUrl = parseUrl(currentUrl || document.location.href);
4083
+ }
4084
+
4085
+ uri.scheme = currentUrl.scheme;
4086
+ uri.host = currentUrl.host;
4087
+ uri.port = currentUrl.port;
4088
+
4089
+ var path = '';
4090
+ // for urls without trailing slash we need to figure out the path
4091
+ if (/^[^\/]/.test(uri.path)) {
4092
+ path = currentUrl.path;
4093
+ // if path ends with a filename, strip it
4094
+ if (!/(\/|\/[^\.]+)$/.test(path)) {
4095
+ path = path.replace(/\/[^\/]+$/, '/');
4096
+ } else {
4097
+ path += '/';
4098
+ }
3622
4099
  }
3623
- uri.host = document.location.hostname;
3624
4100
  uri.path = path + (uri.path || ''); // site may reside at domain.com or domain.com/subdir
3625
4101
  }
3626
4102
 
3627
- if (!uri.scheme) {
3628
- uri.scheme = document.location.protocol.replace(/:$/, '');
3629
- }
3630
-
3631
- if (!uri.host) {
3632
- uri.host = document.location.hostname;
3633
- }
3634
-
3635
4103
  if (!uri.port) {
3636
- uri.port = document.location.port || ports[uri.scheme] || 80;
4104
+ uri.port = ports[uri.scheme] || 80;
3637
4105
  }
4106
+
3638
4107
  uri.port = parseInt(uri.port, 10);
3639
4108
 
3640
4109
  if (!uri.path) {
3641
4110
  uri.path = "/";
3642
4111
  }
3643
-
4112
+
3644
4113
  delete uri.source;
4114
+
3645
4115
  return uri;
3646
4116
  };
3647
4117
 
@@ -3787,7 +4257,7 @@ define("moxie/xhr/FormData", [
3787
4257
  @constructor
3788
4258
  */
3789
4259
  function FormData() {
3790
- var _blobField, _fields = {}, _name = "";
4260
+ var _blob, _fields = [];
3791
4261
 
3792
4262
  Basic.extend(this, {
3793
4263
  /**
@@ -3800,29 +4270,29 @@ define("moxie/xhr/FormData", [
3800
4270
  append: function(name, value) {
3801
4271
  var self = this, valueType = Basic.typeOf(value);
3802
4272
 
4273
+ // according to specs value might be either Blob or String
3803
4274
  if (value instanceof Blob) {
3804
- if (_blobField) {
3805
- delete _fields[_blobField];
3806
- }
3807
- _blobField = name;
3808
- _fields[name] = [value]; // unfortunately we can only send single Blob in one FormData
4275
+ _blob = {
4276
+ name: name,
4277
+ value: value // unfortunately we can only send single Blob in one FormData
4278
+ };
3809
4279
  } else if ('array' === valueType) {
3810
4280
  name += '[]';
3811
4281
 
3812
4282
  Basic.each(value, function(value) {
3813
- self.append.call(self, name, value);
4283
+ self.append(name, value);
3814
4284
  });
3815
4285
  } else if ('object' === valueType) {
3816
4286
  Basic.each(value, function(value, key) {
3817
- self.append.call(self, name + '[' + key + ']', value);
4287
+ self.append(name + '[' + key + ']', value);
3818
4288
  });
4289
+ } else if ('null' === valueType || 'undefined' === valueType || 'number' === valueType && isNaN(value)) {
4290
+ self.append(name, "false");
3819
4291
  } else {
3820
- value = value.toString(); // according to specs value might be either Blob or String
3821
-
3822
- if (!_fields[name]) {
3823
- _fields[name] = [];
3824
- }
3825
- _fields[name].push(value);
4292
+ _fields.push({
4293
+ name: name,
4294
+ value: value.toString()
4295
+ });
3826
4296
  }
3827
4297
  },
3828
4298
 
@@ -3833,7 +4303,7 @@ define("moxie/xhr/FormData", [
3833
4303
  @return {Boolean}
3834
4304
  */
3835
4305
  hasBlob: function() {
3836
- return !!_blobField;
4306
+ return !!this.getBlob();
3837
4307
  },
3838
4308
 
3839
4309
  /**
@@ -3843,7 +4313,7 @@ define("moxie/xhr/FormData", [
3843
4313
  @return {Object} Either Blob if found or null
3844
4314
  */
3845
4315
  getBlob: function() {
3846
- return _fields[_blobField] && _fields[_blobField][0] || null;
4316
+ return _blob && _blob.value || null;
3847
4317
  },
3848
4318
 
3849
4319
  /**
@@ -3853,7 +4323,7 @@ define("moxie/xhr/FormData", [
3853
4323
  @return {String} Either Blob field name or null
3854
4324
  */
3855
4325
  getBlobName: function() {
3856
- return _blobField || null;
4326
+ return _blob && _blob.name || null;
3857
4327
  },
3858
4328
 
3859
4329
  /**
@@ -3863,17 +4333,18 @@ define("moxie/xhr/FormData", [
3863
4333
  @param {Function} cb Callback to call for each field
3864
4334
  */
3865
4335
  each: function(cb) {
3866
- Basic.each(_fields, function(value, name) {
3867
- Basic.each(value, function(value) {
3868
- cb(value, name);
3869
- });
4336
+ Basic.each(_fields, function(field) {
4337
+ cb(field.value, field.name);
3870
4338
  });
4339
+
4340
+ if (_blob) {
4341
+ cb(_blob.value, _blob.name);
4342
+ }
3871
4343
  },
3872
4344
 
3873
4345
  destroy: function() {
3874
- _blobField = null;
3875
- _name = "";
3876
- _fields = {};
4346
+ _blob = null;
4347
+ _fields = [];
3877
4348
  }
3878
4349
  });
3879
4350
  }
@@ -4452,9 +4923,9 @@ define("moxie/xhr/XMLHttpRequest", [
4452
4923
  // 8.2
4453
4924
  // this.dispatchEvent('loadstart'); // will be dispatched either by native or runtime xhr
4454
4925
  // 8.3
4455
- if (!_upload_complete_flag) {
4926
+ //if (!_upload_complete_flag) {
4456
4927
  // this.upload.dispatchEvent('loadstart'); // will be dispatched either by native or runtime xhr
4457
- }
4928
+ //}
4458
4929
  }
4459
4930
  // 8.5 - Return the send() method call, but continue running the steps in this algorithm.
4460
4931
  _doXHR.call(this, data);
@@ -4968,329 +5439,6 @@ define("moxie/runtime/Transporter", [
4968
5439
  return Transporter;
4969
5440
  });
4970
5441
 
4971
- // Included from: src/javascript/core/JSON.js
4972
-
4973
- /**
4974
- * JSON.js
4975
- *
4976
- * Copyright 2013, Moxiecode Systems AB
4977
- * Released under GPL License.
4978
- *
4979
- * License: http://www.plupload.com/license
4980
- * Contributing: http://www.plupload.com/contributing
4981
- */
4982
-
4983
- /*jshint smarttabs:true */
4984
-
4985
- define("moxie/core/JSON", [], function() {
4986
- /**
4987
- Parse string into the JSON object in a safe way
4988
- @credits Douglas Crockford: https://github.com/douglascrockford/JSON-js/blob/master/json_parse.js
4989
-
4990
- @method parse
4991
- @static
4992
- @protected
4993
- @param {Object} obj Object to add property to
4994
- @param {String} prop Property name
4995
- @param {Object} desc Set of key-value pairs defining descriptor for the property
4996
- */
4997
- return !!window.JSON && JSON.parse || (function() {
4998
- "use strict";
4999
-
5000
- // This is a function that can parse a JSON text, producing a JavaScript
5001
- // data structure. It is a simple, recursive descent parser. It does not use
5002
- // eval or regular expressions, so it can be used as a model for implementing
5003
- // a JSON parser in other languages.
5004
-
5005
- // We are defining the function inside of another function to avoid
5006
- // creating global variables.
5007
-
5008
- var at, // The index of the current character
5009
- ch, // The current character
5010
- escapee = {
5011
- '"': '"',
5012
- '\\': '\\',
5013
- '/': '/',
5014
- b: '\b',
5015
- f: '\f',
5016
- n: '\n',
5017
- r: '\r',
5018
- t: '\t'
5019
- },
5020
- text,
5021
-
5022
- error = function (m) {
5023
-
5024
- // Call error when something is wrong.
5025
-
5026
- throw {
5027
- name: 'SyntaxError',
5028
- message: m,
5029
- at: at,
5030
- text: text
5031
- };
5032
- },
5033
-
5034
- next = function (c) {
5035
-
5036
- // If a c parameter is provided, verify that it matches the current character.
5037
-
5038
- if (c && c !== ch) {
5039
- error("Expected '" + c + "' instead of '" + ch + "'");
5040
- }
5041
-
5042
- // Get the next character. When there are no more characters,
5043
- // return the empty string.
5044
-
5045
- ch = text.charAt(at);
5046
- at += 1;
5047
- return ch;
5048
- },
5049
-
5050
- number = function () {
5051
-
5052
- // Parse a number value.
5053
-
5054
- var number,
5055
- string = '';
5056
-
5057
- if (ch === '-') {
5058
- string = '-';
5059
- next('-');
5060
- }
5061
- while (ch >= '0' && ch <= '9') {
5062
- string += ch;
5063
- next();
5064
- }
5065
- if (ch === '.') {
5066
- string += '.';
5067
- while (next() && ch >= '0' && ch <= '9') {
5068
- string += ch;
5069
- }
5070
- }
5071
- if (ch === 'e' || ch === 'E') {
5072
- string += ch;
5073
- next();
5074
- if (ch === '-' || ch === '+') {
5075
- string += ch;
5076
- next();
5077
- }
5078
- while (ch >= '0' && ch <= '9') {
5079
- string += ch;
5080
- next();
5081
- }
5082
- }
5083
- number = +string;
5084
- if (!isFinite(number)) {
5085
- error("Bad number");
5086
- } else {
5087
- return number;
5088
- }
5089
- },
5090
-
5091
- string = function () {
5092
-
5093
- // Parse a string value.
5094
-
5095
- var hex,
5096
- i,
5097
- string = '',
5098
- uffff;
5099
-
5100
- // When parsing for string values, we must look for " and \ characters.
5101
-
5102
- if (ch === '"') {
5103
- while (next()) {
5104
- if (ch === '"') {
5105
- next();
5106
- return string;
5107
- } else if (ch === '\\') {
5108
- next();
5109
- if (ch === 'u') {
5110
- uffff = 0;
5111
- for (i = 0; i < 4; i += 1) {
5112
- hex = parseInt(next(), 16);
5113
- if (!isFinite(hex)) {
5114
- break;
5115
- }
5116
- uffff = uffff * 16 + hex;
5117
- }
5118
- string += String.fromCharCode(uffff);
5119
- } else if (typeof escapee[ch] === 'string') {
5120
- string += escapee[ch];
5121
- } else {
5122
- break;
5123
- }
5124
- } else {
5125
- string += ch;
5126
- }
5127
- }
5128
- }
5129
- error("Bad string");
5130
- },
5131
-
5132
- white = function () {
5133
-
5134
- // Skip whitespace.
5135
-
5136
- while (ch && ch <= ' ') {
5137
- next();
5138
- }
5139
- },
5140
-
5141
- word = function () {
5142
-
5143
- // true, false, or null.
5144
-
5145
- switch (ch) {
5146
- case 't':
5147
- next('t');
5148
- next('r');
5149
- next('u');
5150
- next('e');
5151
- return true;
5152
- case 'f':
5153
- next('f');
5154
- next('a');
5155
- next('l');
5156
- next('s');
5157
- next('e');
5158
- return false;
5159
- case 'n':
5160
- next('n');
5161
- next('u');
5162
- next('l');
5163
- next('l');
5164
- return null;
5165
- }
5166
- error("Unexpected '" + ch + "'");
5167
- },
5168
-
5169
- value, // Place holder for the value function.
5170
-
5171
- array = function () {
5172
-
5173
- // Parse an array value.
5174
-
5175
- var array = [];
5176
-
5177
- if (ch === '[') {
5178
- next('[');
5179
- white();
5180
- if (ch === ']') {
5181
- next(']');
5182
- return array; // empty array
5183
- }
5184
- while (ch) {
5185
- array.push(value());
5186
- white();
5187
- if (ch === ']') {
5188
- next(']');
5189
- return array;
5190
- }
5191
- next(',');
5192
- white();
5193
- }
5194
- }
5195
- error("Bad array");
5196
- },
5197
-
5198
- object = function () {
5199
-
5200
- // Parse an object value.
5201
-
5202
- var key,
5203
- object = {};
5204
-
5205
- if (ch === '{') {
5206
- next('{');
5207
- white();
5208
- if (ch === '}') {
5209
- next('}');
5210
- return object; // empty object
5211
- }
5212
- while (ch) {
5213
- key = string();
5214
- white();
5215
- next(':');
5216
- if (Object.hasOwnProperty.call(object, key)) {
5217
- error('Duplicate key "' + key + '"');
5218
- }
5219
- object[key] = value();
5220
- white();
5221
- if (ch === '}') {
5222
- next('}');
5223
- return object;
5224
- }
5225
- next(',');
5226
- white();
5227
- }
5228
- }
5229
- error("Bad object");
5230
- };
5231
-
5232
- value = function () {
5233
-
5234
- // Parse a JSON value. It could be an object, an array, a string, a number,
5235
- // or a word.
5236
-
5237
- white();
5238
- switch (ch) {
5239
- case '{':
5240
- return object();
5241
- case '[':
5242
- return array();
5243
- case '"':
5244
- return string();
5245
- case '-':
5246
- return number();
5247
- default:
5248
- return ch >= '0' && ch <= '9' ? number() : word();
5249
- }
5250
- };
5251
-
5252
- // Return the json_parse function. It will have access to all of the above
5253
- // functions and variables.
5254
-
5255
- return function (source, reviver) {
5256
- var result;
5257
-
5258
- text = source;
5259
- at = 0;
5260
- ch = ' ';
5261
- result = value();
5262
- white();
5263
- if (ch) {
5264
- error("Syntax error");
5265
- }
5266
-
5267
- // If there is a reviver function, we recursively walk the new structure,
5268
- // passing each name/value pair to the reviver function for possible
5269
- // transformation, starting with a temporary root object that holds the result
5270
- // in an empty key. If there is not a reviver function, we simply return the
5271
- // result.
5272
-
5273
- return typeof reviver === 'function' ? (function walk(holder, key) {
5274
- var k, v, value = holder[key];
5275
- if (value && typeof value === 'object') {
5276
- for (k in value) {
5277
- if (Object.prototype.hasOwnProperty.call(value, k)) {
5278
- v = walk(value, k);
5279
- if (v !== undefined) {
5280
- value[k] = v;
5281
- } else {
5282
- delete value[k];
5283
- }
5284
- }
5285
- }
5286
- }
5287
- return reviver.call(holder, key, value);
5288
- }({'': result}, '')) : result;
5289
- };
5290
- }());
5291
-
5292
- });
5293
-
5294
5442
  // Included from: src/javascript/image/Image.js
5295
5443
 
5296
5444
  /**
@@ -5316,9 +5464,8 @@ define("moxie/image/Image", [
5316
5464
  "moxie/core/EventTarget",
5317
5465
  "moxie/file/Blob",
5318
5466
  "moxie/file/File",
5319
- "moxie/core/utils/Encode",
5320
- "moxie/core/JSON"
5321
- ], function(Basic, Dom, x, FileReaderSync, XMLHttpRequest, Runtime, RuntimeClient, Transporter, Env, EventTarget, Blob, File, Encode, parseJSON) {
5467
+ "moxie/core/utils/Encode"
5468
+ ], function(Basic, Dom, x, FileReaderSync, XMLHttpRequest, Runtime, RuntimeClient, Transporter, Env, EventTarget, Blob, File, Encode) {
5322
5469
  /**
5323
5470
  Image preloading and manipulation utility. Additionally it provides access to image meta info (Exif, GPS) and raw binary data.
5324
5471
 
@@ -5745,28 +5892,18 @@ define("moxie/image/Image", [
5745
5892
  info = this.getRuntime().exec.call(this, 'Image', 'getInfo');
5746
5893
  }
5747
5894
 
5748
- if (info) {
5749
- if (Basic.typeOf(info.meta) === 'string') { // might be a JSON string
5750
- try {
5751
- this.meta = parseJSON(info.meta);
5752
- } catch(ex) {}
5753
- } else {
5754
- this.meta = info.meta;
5755
- }
5756
- }
5757
-
5758
- Basic.extend(this, { // info object might be non-enumerable (as returned from SilverLight for example)
5759
- size: parseInt(info.size, 10),
5760
- width: parseInt(info.width, 10),
5761
- height: parseInt(info.height, 10),
5762
- type: info.type
5763
- });
5895
+ this.size = info.size;
5896
+ this.width = info.width;
5897
+ this.height = info.height;
5898
+ this.type = info.type;
5899
+ this.meta = info.meta;
5764
5900
 
5765
5901
  // update file name, only if empty
5766
5902
  if (this.name === '') {
5767
5903
  this.name = info.name;
5768
5904
  }
5769
5905
  }
5906
+
5770
5907
 
5771
5908
  function _load(src) {
5772
5909
  var srcType = Basic.typeOf(src);
@@ -5948,11 +6085,10 @@ define("moxie/runtime/html5/Runtime", [
5948
6085
  }()),
5949
6086
  return_response_headers: True,
5950
6087
  return_response_type: function(responseType) {
5951
- if (responseType === 'json') {
5952
- return true; // we can fake this one even if it's not supported
5953
- } else {
5954
- return Env.can('return_response_type', responseType);
5955
- }
6088
+ if (responseType === 'json' && !!window.JSON) { // we can fake this one even if it's not supported
6089
+ return true;
6090
+ }
6091
+ return Env.can('return_response_type', responseType);
5956
6092
  },
5957
6093
  return_status_code: True,
5958
6094
  report_upload_progress: Test(window.XMLHttpRequest && new XMLHttpRequest().upload),
@@ -5966,7 +6102,10 @@ define("moxie/runtime/html5/Runtime", [
5966
6102
  return I.can('select_file') && Env.browser === 'Chrome' && Env.version >= 21;
5967
6103
  },
5968
6104
  select_multiple: function() {
5969
- return I.can('select_file') && !(Env.browser === 'Safari' && Env.OS === 'Windows');
6105
+ // it is buggy on Safari Windows and iOS
6106
+ return I.can('select_file') &&
6107
+ !(Env.browser === 'Safari' && Env.os === 'Windows') &&
6108
+ !(Env.os === 'iOS' && Env.verComp(Env.osVersion, "7.0.4", '<'));
5970
6109
  },
5971
6110
  send_binary_string: Test(window.XMLHttpRequest && (new XMLHttpRequest().sendAsBinary || (window.Uint8Array && window.ArrayBuffer))),
5972
6111
  send_custom_headers: Test(window.XMLHttpRequest),
@@ -6383,7 +6522,10 @@ define("moxie/runtime/html5/file/FileInput", [
6383
6522
  },
6384
6523
 
6385
6524
  destroy: function() {
6386
- var I = this.getRuntime(), shimContainer = I.getShimContainer();
6525
+ var I = this.getRuntime()
6526
+ , shim = I.getShim()
6527
+ , shimContainer = I.getShimContainer()
6528
+ ;
6387
6529
 
6388
6530
  Events.removeAllEvents(shimContainer, this.uid);
6389
6531
  Events.removeAllEvents(_options && Dom.get(_options.container), this.uid);
@@ -6392,7 +6534,10 @@ define("moxie/runtime/html5/file/FileInput", [
6392
6534
  if (shimContainer) {
6393
6535
  shimContainer.innerHTML = '';
6394
6536
  }
6395
- _files = _options = null;
6537
+
6538
+ shim.removeInstance(this.uid);
6539
+
6540
+ _files = _options = shimContainer = shim = null;
6396
6541
  }
6397
6542
  });
6398
6543
  }
@@ -6449,11 +6594,7 @@ define("moxie/runtime/html5/file/FileDrop", [
6449
6594
 
6450
6595
  // Chrome 21+ accepts folders via Drag'n'Drop
6451
6596
  if (e.dataTransfer.items && e.dataTransfer.items[0].webkitGetAsEntry) {
6452
- var entries = [];
6453
- Basic.each(e.dataTransfer.items, function(item) {
6454
- entries.push(item.webkitGetAsEntry());
6455
- });
6456
- _readEntries(entries, function() {
6597
+ _readItems(e.dataTransfer.items, function() {
6457
6598
  comp.trigger("drop");
6458
6599
  });
6459
6600
  } else {
@@ -6505,6 +6646,32 @@ define("moxie/runtime/html5/file/FileDrop", [
6505
6646
  }
6506
6647
 
6507
6648
 
6649
+ function _readItems(items, cb) {
6650
+ var entries = [];
6651
+ Basic.each(items, function(item) {
6652
+ var entry = item.webkitGetAsEntry();
6653
+ // Address #998 (https://code.google.com/p/chromium/issues/detail?id=332579)
6654
+ if (entry) {
6655
+ // file() fails on OSX when the filename contains a special character (e.g. umlaut): see #61
6656
+ if (entry.isFile) {
6657
+ var file = item.getAsFile();
6658
+ if (_isAcceptable(file)) {
6659
+ _files.push(file);
6660
+ }
6661
+ } else {
6662
+ entries.push(entry);
6663
+ }
6664
+ }
6665
+ });
6666
+
6667
+ if (entries.length) {
6668
+ _readEntries(entries, cb);
6669
+ } else {
6670
+ cb();
6671
+ }
6672
+ }
6673
+
6674
+
6508
6675
  function _readEntries(entries, cb) {
6509
6676
  var queue = [];
6510
6677
  Basic.each(entries, function(entry) {
@@ -6667,12 +6834,12 @@ define("moxie/runtime/html5/xhr/XMLHttpRequest", [
6667
6834
  "moxie/file/Blob",
6668
6835
  "moxie/xhr/FormData",
6669
6836
  "moxie/core/Exceptions",
6670
- "moxie/core/utils/Env",
6671
- "moxie/core/JSON"
6672
- ], function(extensions, Basic, Mime, Url, File, Blob, FormData, x, Env, parseJSON) {
6837
+ "moxie/core/utils/Env"
6838
+ ], function(extensions, Basic, Mime, Url, File, Blob, FormData, x, Env) {
6673
6839
 
6674
6840
  function XMLHttpRequest() {
6675
- var _xhr
6841
+ var self = this
6842
+ , _xhr
6676
6843
  , _filename
6677
6844
  ;
6678
6845
 
@@ -6881,7 +7048,7 @@ define("moxie/runtime/html5/xhr/XMLHttpRequest", [
6881
7048
 
6882
7049
  case 'json':
6883
7050
  if (!Env.can('return_response_type', 'json')) {
6884
- return _xhr.status === 200 ? parseJSON(_xhr.responseText) : null;
7051
+ return _xhr.status === 200 && !!window.JSON ? JSON.parse(_xhr.responseText) : null;
6885
7052
  }
6886
7053
  return _xhr.response;
6887
7054
 
@@ -6997,7 +7164,7 @@ define("moxie/runtime/html5/xhr/XMLHttpRequest", [
6997
7164
  // Build RFC2388 blob
6998
7165
  multipart += dashdash + boundary + crlf +
6999
7166
  'Content-Disposition: form-data; name="' + name + '"; filename="' + unescape(encodeURIComponent(value.name || 'blob')) + '"' + crlf +
7000
- 'Content-Type: ' + value.type + crlf + crlf +
7167
+ 'Content-Type: ' + (value.type || 'application/octet-stream') + crlf + crlf +
7001
7168
  value.getSource() + crlf;
7002
7169
  } else {
7003
7170
  multipart += dashdash + boundary + crlf +
@@ -8236,12 +8403,12 @@ define("moxie/runtime/html5/image/Image", [
8236
8403
  "moxie/core/utils/Basic",
8237
8404
  "moxie/core/Exceptions",
8238
8405
  "moxie/core/utils/Encode",
8239
- "moxie/file/Blob",
8406
+ "moxie/file/File",
8240
8407
  "moxie/runtime/html5/image/ImageInfo",
8241
8408
  "moxie/runtime/html5/image/MegaPixel",
8242
8409
  "moxie/core/utils/Mime",
8243
8410
  "moxie/core/utils/Env"
8244
- ], function(extensions, Basic, x, Encode, Blob, ImageInfo, MegaPixel, Mime, Env) {
8411
+ ], function(extensions, Basic, x, Encode, File, ImageInfo, MegaPixel, Mime, Env) {
8245
8412
 
8246
8413
  function HTML5Image() {
8247
8414
  var me = this
@@ -8279,7 +8446,7 @@ define("moxie/runtime/html5/image/Image", [
8279
8446
  loadFromImage: function(img, exact) {
8280
8447
  this.meta = img.meta;
8281
8448
 
8282
- _blob = new Blob(null, {
8449
+ _blob = new File(null, {
8283
8450
  name: img.name,
8284
8451
  size: img.size,
8285
8452
  type: img.type
@@ -8323,7 +8490,8 @@ define("moxie/runtime/html5/image/Image", [
8323
8490
  // if different mime type requested prepare image for conversion
8324
8491
  _downsize.call(this, this.width, this.height, false);
8325
8492
  }
8326
- return new Blob(null, {
8493
+ return new File(null, {
8494
+ name: _blob.name || '',
8327
8495
  type: type,
8328
8496
  data: me.getAsBinaryString.call(this, type, quality)
8329
8497
  });
@@ -8466,18 +8634,27 @@ define("moxie/runtime/html5/image/Image", [
8466
8634
  }
8467
8635
 
8468
8636
  function _downsize(width, height, crop, preserveHeaders) {
8469
- var self = this, ctx, scale, mathFn, x, y, img, imgWidth, imgHeight, orientation;
8637
+ var self = this
8638
+ , scale
8639
+ , mathFn
8640
+ , x = 0
8641
+ , y = 0
8642
+ , img
8643
+ , destWidth
8644
+ , destHeight
8645
+ , orientation
8646
+ ;
8470
8647
 
8471
- _preserveHeaders = preserveHeaders; // we will need to check this on export
8648
+ _preserveHeaders = preserveHeaders; // we will need to check this on export (see getAsBinaryString())
8472
8649
 
8473
8650
  // take into account orientation tag
8474
8651
  orientation = (this.meta && this.meta.tiff && this.meta.tiff.Orientation) || 1;
8475
8652
 
8476
8653
  if (Basic.inArray(orientation, [5,6,7,8]) !== -1) { // values that require 90 degree rotation
8477
8654
  // swap dimensions
8478
- var mem = width;
8655
+ var tmp = width;
8479
8656
  width = height;
8480
- height = mem;
8657
+ height = tmp;
8481
8658
  }
8482
8659
 
8483
8660
  img = _getImg();
@@ -8492,34 +8669,40 @@ define("moxie/runtime/html5/image/Image", [
8492
8669
  return;
8493
8670
  }
8494
8671
 
8495
- imgWidth = Math.round(img.width * scale);
8496
- imgHeight = Math.round(img.height * scale);
8497
-
8498
8672
  // prepare canvas if necessary
8499
8673
  if (!_canvas) {
8500
8674
  _canvas = document.createElement("canvas");
8501
8675
  }
8502
8676
 
8503
- ctx = _canvas.getContext('2d');
8677
+ // calculate dimensions of proportionally resized image
8678
+ destWidth = Math.round(img.width * scale);
8679
+ destHeight = Math.round(img.height * scale);
8680
+
8504
8681
 
8505
8682
  // scale image and canvas
8506
8683
  if (crop) {
8507
8684
  _canvas.width = width;
8508
8685
  _canvas.height = height;
8686
+
8687
+ // if dimensions of the resulting image still larger than canvas, center it
8688
+ if (destWidth > width) {
8689
+ x = Math.round((destWidth - width) / 2);
8690
+ }
8691
+
8692
+ if (destHeight > height) {
8693
+ y = Math.round((destHeight - height) / 2);
8694
+ }
8509
8695
  } else {
8510
- _canvas.width = imgWidth;
8511
- _canvas.height = imgHeight;
8696
+ _canvas.width = destWidth;
8697
+ _canvas.height = destHeight;
8512
8698
  }
8513
8699
 
8514
- // if dimensions of the resulting image still larger than canvas, center it
8515
- x = imgWidth > _canvas.width ? Math.round((imgWidth - _canvas.width) / 2) : 0;
8516
- y = imgHeight > _canvas.height ? Math.round((imgHeight - _canvas.height) / 2) : 0;
8517
-
8700
+ // rotate if required, according to orientation tag
8518
8701
  if (!_preserveHeaders) {
8519
8702
  _rotateToOrientaion(_canvas.width, _canvas.height, orientation);
8520
8703
  }
8521
8704
 
8522
- _drawToCanvas.call(this, img, _canvas, -x, -y, imgWidth, imgHeight);
8705
+ _drawToCanvas.call(this, img, _canvas, -x, -y, destWidth, destHeight);
8523
8706
 
8524
8707
  this.width = _canvas.width;
8525
8708
  this.height = _canvas.height;
@@ -8706,7 +8889,10 @@ define("moxie/runtime/flash/Runtime", [
8706
8889
  resize_image: Runtime.capTrue,
8707
8890
  return_response_headers: false,
8708
8891
  return_response_type: function(responseType) {
8709
- return !Basic.arrayDiff(responseType, ['', 'text', 'json', 'document']) || I.mode === 'browser';
8892
+ if (responseType === 'json' && !!window.JSON) {
8893
+ return true;
8894
+ }
8895
+ return !Basic.arrayDiff(responseType, ['', 'text', 'document']) || I.mode === 'browser';
8710
8896
  },
8711
8897
  return_status_code: function(code) {
8712
8898
  return I.mode === 'browser' || !Basic.arrayDiff(code, [200, 404]);
@@ -8769,7 +8955,7 @@ define("moxie/runtime/flash/Runtime", [
8769
8955
  }, 'client');
8770
8956
 
8771
8957
 
8772
- // minimal requirement Flash Player 10
8958
+ // minimal requirement for Flash Player version
8773
8959
  if (getShimVersion() < 10) {
8774
8960
  this.mode = false; // with falsy mode, runtime won't operable, no matter what the mode was before
8775
8961
  }
@@ -9073,9 +9259,8 @@ define("moxie/runtime/flash/xhr/XMLHttpRequest", [
9073
9259
  "moxie/file/File",
9074
9260
  "moxie/file/FileReaderSync",
9075
9261
  "moxie/xhr/FormData",
9076
- "moxie/runtime/Transporter",
9077
- "moxie/core/JSON"
9078
- ], function(extensions, Basic, Blob, File, FileReaderSync, FormData, Transporter, parseJSON) {
9262
+ "moxie/runtime/Transporter"
9263
+ ], function(extensions, Basic, Blob, File, FileReaderSync, FormData, Transporter) {
9079
9264
 
9080
9265
  var XMLHttpRequest = {
9081
9266
 
@@ -9165,24 +9350,20 @@ define("moxie/runtime/flash/xhr/XMLHttpRequest", [
9165
9350
 
9166
9351
  if ('blob' === responseType) {
9167
9352
  return blob;
9168
- } else if (!!~Basic.inArray(responseType, ["", "text"])) {
9169
- frs = new FileReaderSync();
9170
- return frs.readAsText(blob);
9171
- } else if ('arraybuffer' === responseType) {
9172
-
9173
- // do something
9353
+ }
9174
9354
 
9175
- } else if ('json' === responseType) {
9355
+ try {
9176
9356
  frs = new FileReaderSync();
9177
-
9178
- try {
9179
- return parseJSON(frs.readAsText(blob));
9180
- } catch (ex) {
9181
- return null;
9357
+
9358
+ if (!!~Basic.inArray(responseType, ["", "text"])) {
9359
+ return frs.readAsText(blob);
9360
+ } else if ('json' === responseType && !!window.JSON) {
9361
+ return JSON.parse(frs.readAsText(blob));
9182
9362
  }
9363
+ } finally {
9364
+ blob.destroy();
9183
9365
  }
9184
9366
  }
9185
-
9186
9367
  return null;
9187
9368
  },
9188
9369
 
@@ -9195,9 +9376,9 @@ define("moxie/runtime/flash/xhr/XMLHttpRequest", [
9195
9376
  // this.dispatchEvent('progress');
9196
9377
  this.dispatchEvent('abort');
9197
9378
 
9198
- if (!upload_complete_flag) {
9379
+ //if (!upload_complete_flag) {
9199
9380
  // this.dispatchEvent('uploadprogress');
9200
- }
9381
+ //}
9201
9382
  }
9202
9383
  };
9203
9384
 
@@ -9424,7 +9605,13 @@ define("moxie/runtime/silverlight/Runtime", [
9424
9605
  return_response_headers: function(value) {
9425
9606
  return value && I.mode === 'client';
9426
9607
  },
9427
- return_response_type: Runtime.capTrue,
9608
+ return_response_type: function(responseType) {
9609
+ if (responseType !== 'json') {
9610
+ return true;
9611
+ } else {
9612
+ return !!window.JSON;
9613
+ }
9614
+ },
9428
9615
  return_status_code: function(code) {
9429
9616
  return I.mode === 'client' || !Basic.arrayDiff(code, [200, 404]);
9430
9617
  },
@@ -9758,7 +9945,51 @@ define("moxie/runtime/silverlight/image/Image", [
9758
9945
  "moxie/core/utils/Basic",
9759
9946
  "moxie/runtime/flash/image/Image"
9760
9947
  ], function(extensions, Basic, Image) {
9761
- return (extensions.Image = Basic.extend({}, Image));
9948
+ return (extensions.Image = Basic.extend({}, Image, {
9949
+
9950
+ getInfo: function() {
9951
+ var self = this.getRuntime()
9952
+ , grps = ['tiff', 'exif', 'gps']
9953
+ , info = { meta: {} }
9954
+ , rawInfo = self.shimExec.call(this, 'Image', 'getInfo')
9955
+ ;
9956
+
9957
+ if (rawInfo.meta) {
9958
+ Basic.each(grps, function(grp) {
9959
+ var meta = rawInfo.meta[grp]
9960
+ , tag
9961
+ , i
9962
+ , length
9963
+ , value
9964
+ ;
9965
+ if (meta && meta.keys) {
9966
+ info.meta[grp] = {};
9967
+ for (i = 0, length = meta.keys.length; i < length; i++) {
9968
+ tag = meta.keys[i];
9969
+ value = meta[tag];
9970
+ if (value) {
9971
+ // convert numbers
9972
+ if (/^(\d|[1-9]\d+)$/.test(value)) { // integer (make sure doesn't start with zero)
9973
+ value = parseInt(value, 10);
9974
+ } else if (/^\d*\.\d+$/.test(value)) { // double
9975
+ value = parseFloat(value);
9976
+ }
9977
+ info.meta[grp][tag] = value;
9978
+ }
9979
+ }
9980
+ }
9981
+ });
9982
+ }
9983
+
9984
+ info.width = parseInt(rawInfo.width, 10);
9985
+ info.height = parseInt(rawInfo.height, 10);
9986
+ info.size = parseInt(rawInfo.size, 10);
9987
+ info.type = rawInfo.type;
9988
+ info.name = rawInfo.name;
9989
+
9990
+ return info;
9991
+ }
9992
+ }));
9762
9993
  });
9763
9994
 
9764
9995
  // Included from: src/javascript/runtime/html4/Runtime.js
@@ -9811,7 +10042,10 @@ define("moxie/runtime/html4/Runtime", [
9811
10042
  report_upload_progress: false,
9812
10043
  return_response_headers: false,
9813
10044
  return_response_type: function(responseType) {
9814
- return !!~Basic.inArray(responseType, ['json', 'text', 'document', '']);
10045
+ if (responseType === 'json' && !!window.JSON) {
10046
+ return true;
10047
+ }
10048
+ return !!~Basic.inArray(responseType, ['text', 'document', '']);
9815
10049
  },
9816
10050
  return_status_code: function(code) {
9817
10051
  return !Basic.arrayDiff(code, [200, 404]);
@@ -9830,7 +10064,6 @@ define("moxie/runtime/html4/Runtime", [
9830
10064
  summon_file_dialog: Test(function() { // yeah... some dirty sniffing here...
9831
10065
  return (Env.browser === 'Firefox' && Env.version >= 4) ||
9832
10066
  (Env.browser === 'Opera' && Env.version >= 12) ||
9833
- (Env.browser === 'IE' && Env.version >= 10) ||
9834
10067
  !!~Basic.inArray(Env.browser, ['Chrome', 'Safari']);
9835
10068
  }()),
9836
10069
  upload_filesize: True,
@@ -9922,7 +10155,7 @@ define("moxie/runtime/html4/file/FileInput", [
9922
10155
  input = document.createElement('input');
9923
10156
  input.setAttribute('id', uid);
9924
10157
  input.setAttribute('type', 'file');
9925
- input.setAttribute('name', 'Filedata');
10158
+ input.setAttribute('name', _options.name || 'Filedata');
9926
10159
  input.setAttribute('accept', _mimes.join(','));
9927
10160
 
9928
10161
  Basic.extend(input.style, {
@@ -9969,9 +10202,11 @@ define("moxie/runtime/html4/file/FileInput", [
9969
10202
  addInput.call(comp);
9970
10203
 
9971
10204
  // after file is initialized as o.File, we need to update form and input ids
9972
- comp.bind('change', function() {
10205
+ comp.bind('change', function onChange() {
9973
10206
  var input = Dom.get(uid), form = Dom.get(uid + '_form'), file;
9974
10207
 
10208
+ comp.unbind('change', onChange);
10209
+
9975
10210
  if (comp.files.length && input && form) {
9976
10211
  file = comp.files[0];
9977
10212
 
@@ -10004,12 +10239,6 @@ define("moxie/runtime/html4/file/FileInput", [
10004
10239
  _uid = uid;
10005
10240
 
10006
10241
  shimContainer = currForm = browseButton = null;
10007
-
10008
- // trigger ready event asynchronously
10009
- comp.trigger({
10010
- type: 'ready',
10011
- async: true
10012
- });
10013
10242
  }
10014
10243
 
10015
10244
  Basic.extend(this, {
@@ -10065,6 +10294,12 @@ define("moxie/runtime/html4/file/FileInput", [
10065
10294
  addInput.call(this);
10066
10295
 
10067
10296
  shimContainer = null;
10297
+
10298
+ // trigger ready event asynchronously
10299
+ comp.trigger({
10300
+ type: 'ready',
10301
+ async: true
10302
+ });
10068
10303
  },
10069
10304
 
10070
10305
  getFiles: function() {
@@ -10080,7 +10315,10 @@ define("moxie/runtime/html4/file/FileInput", [
10080
10315
  },
10081
10316
 
10082
10317
  destroy: function() {
10083
- var I = this.getRuntime(), shimContainer = I.getShimContainer();
10318
+ var I = this.getRuntime()
10319
+ , shim = I.getShim()
10320
+ , shimContainer = I.getShimContainer()
10321
+ ;
10084
10322
 
10085
10323
  Events.removeAllEvents(shimContainer, this.uid);
10086
10324
  Events.removeAllEvents(_options && Dom.get(_options.container), this.uid);
@@ -10089,7 +10327,10 @@ define("moxie/runtime/html4/file/FileInput", [
10089
10327
  if (shimContainer) {
10090
10328
  shimContainer.innerHTML = '';
10091
10329
  }
10092
- _uid = _files = _mimes = _options = null;
10330
+
10331
+ shim.removeInstance(this.uid);
10332
+
10333
+ _uid = _files = _mimes = _options = shimContainer = shim = null;
10093
10334
  }
10094
10335
  });
10095
10336
  }
@@ -10144,9 +10385,8 @@ define("moxie/runtime/html4/xhr/XMLHttpRequest", [
10144
10385
  "moxie/core/Exceptions",
10145
10386
  "moxie/core/utils/Events",
10146
10387
  "moxie/file/Blob",
10147
- "moxie/xhr/FormData",
10148
- "moxie/core/JSON"
10149
- ], function(extensions, Basic, Dom, Url, x, Events, Blob, FormData, parseJSON) {
10388
+ "moxie/xhr/FormData"
10389
+ ], function(extensions, Basic, Dom, Url, x, Events, Blob, FormData) {
10150
10390
 
10151
10391
  function XMLHttpRequest() {
10152
10392
  var _status, _response, _iframe;
@@ -10228,7 +10468,7 @@ define("moxie/runtime/html4/xhr/XMLHttpRequest", [
10228
10468
  el = _iframe.contentWindow.document || _iframe.contentDocument || window.frames[_iframe.id].document;
10229
10469
 
10230
10470
  // try to detect some standard error pages
10231
- if (/^4\d{2}\s/.test(el.title) && el.getElementsByTagName('address').length) { // standard Apache style
10471
+ if (/^4(0[0-9]|1[0-7]|2[2346])\s/.test(el.title)) { // test if title starts with 4xx HTTP error
10232
10472
  _status = el.title.replace(/^(\d+).*$/, '$1');
10233
10473
  } else {
10234
10474
  _status = 200;
@@ -10306,7 +10546,12 @@ define("moxie/runtime/html4/xhr/XMLHttpRequest", [
10306
10546
  value : value
10307
10547
  });
10308
10548
 
10309
- form.appendChild(hidden);
10549
+ // make sure that input[type="file"], if it's there, comes last
10550
+ if (input) {
10551
+ form.insertBefore(hidden, input);
10552
+ } else {
10553
+ form.appendChild(hidden);
10554
+ }
10310
10555
  }
10311
10556
  });
10312
10557
  }
@@ -10326,9 +10571,9 @@ define("moxie/runtime/html4/xhr/XMLHttpRequest", [
10326
10571
  getResponse: function(responseType) {
10327
10572
  if ('json' === responseType) {
10328
10573
  // strip off <pre>..</pre> tags that might be enclosing the response
10329
- if (Basic.typeOf(_response) === 'string') {
10574
+ if (Basic.typeOf(_response) === 'string' && !!window.JSON) {
10330
10575
  try {
10331
- return parseJSON(_response.replace(/^\s*<pre[^>]*>/, '').replace(/<\/pre>\s*$/, ''));
10576
+ return JSON.parse(_response.replace(/^\s*<pre[^>]*>/, '').replace(/<\/pre>\s*$/, ''));
10332
10577
  } catch (ex) {
10333
10578
  return null;
10334
10579
  }
@@ -10386,7 +10631,7 @@ define("moxie/runtime/html4/image/Image", [
10386
10631
  return (extensions.Image = Image);
10387
10632
  });
10388
10633
 
10389
- 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/core/JSON","moxie/image/Image","moxie/core/utils/Events"]);
10634
+ 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"]);
10390
10635
  })(this);/**
10391
10636
  * o.js
10392
10637
  *