compass-jquery-plugin 0.3.2.pre.2 → 0.3.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (83) hide show
  1. data/LICENSE.md +20 -20
  2. data/README.md +7 -2
  3. data/VERSION.yml +2 -2
  4. data/lib/jquery/gridify/grid.rb +1 -1
  5. data/lib/jquery/gridify/grid_column.rb +1 -1
  6. data/lib/jquery/gridify/grid_finder.rb +16 -1
  7. data/lib/jquery/gridify/grid_view.rb +1 -1
  8. data/lib/jquery/jqgrid.rb +4 -4
  9. data/lib/jquery/jqtouch.rb +3 -3
  10. data/lib/jquery/jquery.rb +431 -431
  11. data/lib/jquery/jquery_json_response.rb +28 -0
  12. data/lib/jquery/secret_sauce.rb +8 -8
  13. data/lib/jquery/secret_sauce/controller/ui_dialog_controls.rb +13 -13
  14. data/lib/jquery/secret_sauce/controller/ui_grid_controls.rb +18 -18
  15. data/lib/jquery/secret_sauce/helpers/ui_dialog_helper.rb +5 -5
  16. data/lib/jquery/secret_sauce/model/find_for_grid.rb +41 -41
  17. data/templates/dynatree/jquery.dynatree.js +111 -110
  18. data/templates/dynatree/jquery.dynatree.min.js +75 -77
  19. data/templates/dynatree/jquery/dynatree/aero.scss +1 -3
  20. data/templates/dynatree/jquery/dynatree/aqua.scss +1 -3
  21. data/templates/dynatree/jquery/dynatree/crystal.scss +1 -3
  22. data/templates/dynatree/jquery/dynatree/xp.scss +1 -3
  23. data/templates/emulators/emulators/iphone.landscape.png +0 -0
  24. data/templates/emulators/emulators/iphone.landscape.scss +4 -4
  25. data/templates/emulators/emulators/palm.landscape.scss +6 -6
  26. data/templates/emulators/emulators/palm.pre.landscape.png +0 -0
  27. data/templates/ical/jquery.ical.js +3202 -3197
  28. data/templates/ical/jquery.ical.min.js +185 -184
  29. data/templates/ical/jquery/ical.scss +3 -3
  30. data/templates/jqgrid/i18n/jqgrid/locale-ar.js +126 -0
  31. data/templates/jqgrid/i18n/jqgrid/locale-ar.min.js +6 -0
  32. data/templates/jqgrid/i18n/jqgrid/locale-fi.js +45 -47
  33. data/templates/jqgrid/i18n/jqgrid/locale-fi.min.js +6 -6
  34. data/templates/jqgrid/jquery.jqGrid.js +2047 -2036
  35. data/templates/jqgrid/jquery.jqGrid.min.js +48 -48
  36. data/templates/jqgrid/manifest.rb +2 -0
  37. data/templates/jqtouch/jquery.jqtouch.js +122 -113
  38. data/templates/jqtouch/jquery.jqtouch.min.js +1 -1
  39. data/templates/jquery/config/initializers/jquery.rb +4 -2
  40. data/templates/jquery/i18n/jquery.ui/datepicker-ar-DZ.js +23 -0
  41. data/templates/jquery/i18n/jquery.ui/datepicker-ar-DZ.min.js +2 -0
  42. data/templates/jquery/i18n/jquery.ui/datepicker-en-AU.js +23 -0
  43. data/templates/jquery/i18n/jquery.ui/datepicker-en-AU.min.js +2 -0
  44. data/templates/jquery/i18n/jquery.ui/datepicker-en-NZ.js +23 -0
  45. data/templates/jquery/i18n/jquery.ui/datepicker-en-NZ.min.js +2 -0
  46. data/templates/jquery/i18n/jquery.ui/datepicker-ml.js +23 -0
  47. data/templates/jquery/i18n/jquery.ui/datepicker-ml.min.js +2 -0
  48. data/templates/jquery/jquery-ui.js +354 -316
  49. data/templates/jquery/jquery-ui.min.js +544 -544
  50. data/templates/jquery/jquery.cookie.js +3 -3
  51. data/templates/jquery/jquery.form.js +271 -140
  52. data/templates/jquery/jquery.form.min.js +19 -17
  53. data/templates/jquery/jquery.layout.js +2435 -2437
  54. data/templates/jquery/jquery.layout.min.js +4 -3
  55. data/templates/jquery/jquery.mousewheel.js +78 -0
  56. data/templates/jquery/jquery.mousewheel.min.js +2 -0
  57. data/templates/jquery/jquery.offline.js +212 -0
  58. data/templates/jquery/jquery.offline.min.js +4 -0
  59. data/templates/jquery/jquery.tmpl.js +15 -22
  60. data/templates/jquery/jquery.tmpl.min.js +12 -12
  61. data/templates/jquery/jquery.tmplPlus.js +1 -0
  62. data/templates/jquery/jquery/ui/_theme.scss +27 -27
  63. data/templates/jquery/json.js +7 -0
  64. data/templates/jquery/json.min.js +7 -0
  65. data/templates/jquery/manifest.rb +14 -2
  66. data/templates/mobile/glyphish/{Read me first - license.txt → License.txt} +0 -0
  67. data/templates/mobile/jquery.mobile.js +1583 -1408
  68. data/templates/mobile/jquery.mobile.min.js +5 -5
  69. data/templates/mobile/jquery/mobile/_base.scss +938 -1038
  70. data/templates/mobile/jquery/mobile/default.scss +25 -26
  71. data/templates/mobile/jquery/mobile/valencia.scss +0 -1
  72. data/templates/mobile/manifest.rb +1 -1
  73. data/templates/tools/config/initializers/tools.rb +2 -0
  74. data/templates/tools/flowplayer.js +24 -0
  75. data/templates/tools/flowplayer.min.js +30 -0
  76. data/templates/tools/jquery.tools.js +4 -3
  77. data/templates/tools/jquery.tools.min.js +1 -1
  78. data/templates/tools/manifest.rb +4 -0
  79. data/templates/tools/swfobject.js +777 -0
  80. data/templates/tools/swfobject.min.js +19 -0
  81. metadata +31 -15
  82. data/templates/jquery/jquery.metadata.js +0 -122
  83. data/templates/jquery/jquery.metadata.min.js +0 -2
@@ -1,7 +1,7 @@
1
1
  /*
2
- * jQuery UI CSS Framework 1.8.7
2
+ * jQuery UI CSS Framework 1.8.9
3
3
  *
4
- * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
4
+ * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
5
5
  * Dual licensed under the MIT or GPL Version 2 licenses.
6
6
  * http://jquery.org/license
7
7
  *
@@ -83,9 +83,9 @@
83
83
 
84
84
 
85
85
  /*
86
- * jQuery UI Accordion 1.8.7
86
+ * jQuery UI Accordion 1.8.9
87
87
  *
88
- * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
88
+ * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
89
89
  * Dual licensed under the MIT or GPL Version 2 licenses.
90
90
  * http://jquery.org/license
91
91
  *
@@ -137,9 +137,9 @@
137
137
 
138
138
 
139
139
  /*
140
- * jQuery UI Autocomplete 1.8.7
140
+ * jQuery UI Autocomplete 1.8.9
141
141
  *
142
- * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
142
+ * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
143
143
  * Dual licensed under the MIT or GPL Version 2 licenses.
144
144
  * http://jquery.org/license
145
145
  *
@@ -156,7 +156,7 @@
156
156
  /* without this, the menu expands to 100% in IE6 */
157
157
 
158
158
  /*
159
- * jQuery UI Menu 1.8.7
159
+ * jQuery UI Menu 1.8.9
160
160
  *
161
161
  * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
162
162
  * Dual licensed under the MIT or GPL Version 2 licenses.
@@ -196,9 +196,9 @@
196
196
 
197
197
 
198
198
  /*
199
- * jQuery UI Button 1.8.7
199
+ * jQuery UI Button 1.8.9
200
200
  *
201
- * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
201
+ * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
202
202
  * Dual licensed under the MIT or GPL Version 2 licenses.
203
203
  * http://jquery.org/license
204
204
  *
@@ -292,9 +292,9 @@ button.ui-button::-moz-focus-inner {
292
292
 
293
293
 
294
294
  /*
295
- * jQuery UI Datepicker 1.8.7
295
+ * jQuery UI Datepicker 1.8.9
296
296
  *
297
- * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
297
+ * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
298
298
  * Dual licensed under the MIT or GPL Version 2 licenses.
299
299
  * http://jquery.org/license
300
300
  *
@@ -491,9 +491,9 @@ button.ui-button::-moz-focus-inner {
491
491
 
492
492
 
493
493
  /*
494
- * jQuery UI Dialog 1.8.7
494
+ * jQuery UI Dialog 1.8.9
495
495
  *
496
- * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
496
+ * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
497
497
  * Dual licensed under the MIT or GPL Version 2 licenses.
498
498
  * http://jquery.org/license
499
499
  *
@@ -506,12 +506,12 @@ button.ui-button::-moz-focus-inner {
506
506
  overflow: hidden; }
507
507
 
508
508
  .ui-dialog .ui-dialog-titlebar {
509
- padding: .5em 1em .3em;
509
+ padding: .4em 1em;
510
510
  position: relative; }
511
511
 
512
512
  .ui-dialog .ui-dialog-title {
513
513
  float: left;
514
- margin: .1em 16px .2em 0; }
514
+ margin: .1em 16px .1em 0; }
515
515
 
516
516
  .ui-dialog .ui-dialog-titlebar-close {
517
517
  position: absolute;
@@ -627,9 +627,9 @@ button.ui-button::-moz-focus-inner {
627
627
 
628
628
 
629
629
  /*
630
- * jQuery UI Progressbar 1.8.7
630
+ * jQuery UI Progressbar 1.8.9
631
631
  *
632
- * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
632
+ * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
633
633
  * Dual licensed under the MIT or GPL Version 2 licenses.
634
634
  * http://jquery.org/license
635
635
  *
@@ -645,9 +645,9 @@ button.ui-button::-moz-focus-inner {
645
645
 
646
646
 
647
647
  /*
648
- * jQuery UI Resizable 1.8.7
648
+ * jQuery UI Resizable 1.8.9
649
649
  *
650
- * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
650
+ * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
651
651
  * Dual licensed under the MIT or GPL Version 2 licenses.
652
652
  * http://jquery.org/license
653
653
  *
@@ -723,9 +723,9 @@ button.ui-button::-moz-focus-inner {
723
723
 
724
724
 
725
725
  /*
726
- * jQuery UI Selectable 1.8.7
726
+ * jQuery UI Selectable 1.8.9
727
727
  *
728
- * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
728
+ * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
729
729
  * Dual licensed under the MIT or GPL Version 2 licenses.
730
730
  * http://jquery.org/license
731
731
  *
@@ -835,9 +835,9 @@ button.ui-button::-moz-focus-inner {
835
835
 
836
836
 
837
837
  /*
838
- * jQuery UI Slider 1.8.7
838
+ * jQuery UI Slider 1.8.9
839
839
  *
840
- * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
840
+ * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
841
841
  * Dual licensed under the MIT or GPL Version 2 licenses.
842
842
  * http://jquery.org/license
843
843
  *
@@ -900,9 +900,9 @@ button.ui-button::-moz-focus-inner {
900
900
 
901
901
 
902
902
  /*
903
- * jQuery UI Tabs 1.8.7
903
+ * jQuery UI Tabs 1.8.9
904
904
  *
905
- * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
905
+ * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
906
906
  * Dual licensed under the MIT or GPL Version 2 licenses.
907
907
  * http://jquery.org/license
908
908
  *
@@ -955,9 +955,9 @@ button.ui-button::-moz-focus-inner {
955
955
 
956
956
 
957
957
  /*
958
- * jQuery UI CSS Framework 1.8.7
958
+ * jQuery UI CSS Framework 1.8.9
959
959
  *
960
- * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
960
+ * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
961
961
  * Dual licensed under the MIT or GPL Version 2 licenses.
962
962
  * http://jquery.org/license
963
963
  *
@@ -0,0 +1,7 @@
1
+ if(!this.JSON)this.JSON={};
2
+ (function(){function k(a){return a<10?"0"+a:a}if(typeof Date.prototype.toJSON!=="function"){Date.prototype.toJSON=function(){return isFinite(this.valueOf())?this.getUTCFullYear()+"-"+k(this.getUTCMonth()+1)+"-"+k(this.getUTCDate())+"T"+k(this.getUTCHours())+":"+k(this.getUTCMinutes())+":"+k(this.getUTCSeconds())+"Z":null};String.prototype.toJSON=Number.prototype.toJSON=Boolean.prototype.toJSON=function(){return this.valueOf()}}var n=/[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,o=
3
+ /[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,f,l,q={"\u0008":"\\b","\t":"\\t","\n":"\\n","\u000c":"\\f","\r":"\\r",'"':'\\"',"\\":"\\\\"},i;function p(a){o.lastIndex=0;return o.test(a)?'"'+a.replace(o,function(c){var d=q[c];return typeof d==="string"?d:"\\u"+("0000"+c.charCodeAt(0).toString(16)).slice(-4)})+'"':'"'+a+'"'}function m(a,c){var d,g,j=f,e,b=c[a];if(b&&typeof b==="object"&&typeof b.toJSON==="function")b=b.toJSON(a);
4
+ if(typeof i==="function")b=i.call(c,a,b);switch(typeof b){case "string":return p(b);case "number":return isFinite(b)?String(b):"null";case "boolean":case "null":return String(b);case "object":if(!b)return"null";f+=l;e=[];if(Object.prototype.toString.apply(b)==="[object Array]"){g=b.length;for(a=0;a<g;a+=1)e[a]=m(a,b)||"null";c=e.length===0?"[]":f?"[\n"+f+e.join(",\n"+f)+"\n"+j+"]":"["+e.join(",")+"]";f=j;return c}if(i&&typeof i==="object"){g=i.length;for(a=0;a<g;a+=1){d=i[a];if(typeof d==="string")if(c=
5
+ m(d,b))e.push(p(d)+(f?": ":":")+c)}}else for(d in b)if(Object.hasOwnProperty.call(b,d))if(c=m(d,b))e.push(p(d)+(f?": ":":")+c);c=e.length===0?"{}":f?"{\n"+f+e.join(",\n"+f)+"\n"+j+"}":"{"+e.join(",")+"}";f=j;return c}}if(typeof JSON.stringify!=="function")JSON.stringify=function(a,c,d){var g;l=f="";if(typeof d==="number")for(g=0;g<d;g+=1)l+=" ";else if(typeof d==="string")l=d;if((i=c)&&typeof c!=="function"&&(typeof c!=="object"||typeof c.length!=="number"))throw new Error("JSON.stringify");return m("",
6
+ {"":a})};if(typeof JSON.parse!=="function")JSON.parse=function(a,c){function d(g,j){var e,b,h=g[j];if(h&&typeof h==="object")for(e in h)if(Object.hasOwnProperty.call(h,e)){b=d(h,e);if(b!==undefined)h[e]=b;else delete h[e]}return c.call(g,j,h)}a=String(a);n.lastIndex=0;if(n.test(a))a=a.replace(n,function(g){return"\\u"+("0000"+g.charCodeAt(0).toString(16)).slice(-4)});if(/^[\],:{}\s]*$/.test(a.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,"@").replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,
7
+ "]").replace(/(?:^|:|,)(?:\s*\[)+/g,""))){a=eval("("+a+")");return typeof c==="function"?d({"":a},""):a}throw new SyntaxError("JSON.parse");}})();
@@ -0,0 +1,7 @@
1
+ if(!this.JSON)this.JSON={};
2
+ (function(){function k(a){return a<10?"0"+a:a}function n(a){o.lastIndex=0;return o.test(a)?'"'+a.replace(o,function(c){var d=q[c];return typeof d==="string"?d:"\\u"+("0000"+c.charCodeAt(0).toString(16)).slice(-4)})+'"':'"'+a+'"'}function l(a,c){var d,f,i=g,e,b=c[a];if(b&&typeof b==="object"&&typeof b.toJSON==="function")b=b.toJSON(a);if(typeof j==="function")b=j.call(c,a,b);switch(typeof b){case "string":return n(b);case "number":return isFinite(b)?String(b):"null";case "boolean":case "null":return String(b);case "object":if(!b)return"null";
3
+ g+=m;e=[];if(Object.prototype.toString.apply(b)==="[object Array]"){f=b.length;for(a=0;a<f;a+=1)e[a]=l(a,b)||"null";c=e.length===0?"[]":g?"[\n"+g+e.join(",\n"+g)+"\n"+i+"]":"["+e.join(",")+"]";g=i;return c}if(j&&typeof j==="object"){f=j.length;for(a=0;a<f;a+=1){d=j[a];if(typeof d==="string")if(c=l(d,b))e.push(n(d)+(g?": ":":")+c)}}else for(d in b)if(Object.hasOwnProperty.call(b,d))if(c=l(d,b))e.push(n(d)+(g?": ":":")+c);c=e.length===0?"{}":g?"{\n"+g+e.join(",\n"+g)+"\n"+i+"}":"{"+e.join(",")+"}";
4
+ g=i;return c}}if(typeof Date.prototype.toJSON!=="function"){Date.prototype.toJSON=function(){return isFinite(this.valueOf())?this.getUTCFullYear()+"-"+k(this.getUTCMonth()+1)+"-"+k(this.getUTCDate())+"T"+k(this.getUTCHours())+":"+k(this.getUTCMinutes())+":"+k(this.getUTCSeconds())+"Z":null};String.prototype.toJSON=Number.prototype.toJSON=Boolean.prototype.toJSON=function(){return this.valueOf()}}var p=/[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
5
+ o=/[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,g,m,q={"":"\\b","\t":"\\t","\n":"\\n"," ":"\\f","\r":"\\r",'"':'\\"',"\\":"\\\\"},j;if(typeof JSON.stringify!=="function")JSON.stringify=function(a,c,d){var f;m=g="";if(typeof d==="number")for(f=0;f<d;f+=1)m+=" ";else if(typeof d==="string")m=d;if((j=c)&&typeof c!=="function"&&(typeof c!=="object"||typeof c.length!=="number"))throw Error("JSON.stringify");return l("",{"":a})};
6
+ if(typeof JSON.parse!=="function")JSON.parse=function(a,c){function d(f,i){var e,b,h=f[i];if(h&&typeof h==="object")for(e in h)if(Object.hasOwnProperty.call(h,e)){b=d(h,e);if(b!==undefined)h[e]=b;else delete h[e]}return c.call(f,i,h)}a=String(a);p.lastIndex=0;if(p.test(a))a=a.replace(p,function(f){return"\\u"+("0000"+f.charCodeAt(0).toString(16)).slice(-4)});if(/^[\],:{}\s]*$/.test(a.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,"@").replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,
7
+ "]").replace(/(?:^|:|,)(?:\s*\[)+/g,""))){a=eval("("+a+")");return typeof c==="function"?d({"":a},""):a}throw new SyntaxError("JSON.parse");}})();
@@ -28,8 +28,10 @@ javascript 'jquery.hotkeys.js'
28
28
  javascript 'jquery.hotkeys.min.js'
29
29
  javascript 'jquery.layout.js'
30
30
  javascript 'jquery.layout.min.js'
31
- javascript 'jquery.metadata.js'
32
- javascript 'jquery.metadata.min.js'
31
+ javascript 'jquery.mousewheel.js'
32
+ javascript 'jquery.mousewheel.min.js'
33
+ javascript 'jquery.offline.js'
34
+ javascript 'jquery.offline.min.js'
33
35
  javascript 'jquery.pngFix.js'
34
36
  javascript 'jquery.pngFix.min.js'
35
37
  javascript 'jquery.themeswitchertool.js'
@@ -38,6 +40,8 @@ javascript 'jquery.tmpl.js'
38
40
  javascript 'jquery.tmpl.min.js'
39
41
  javascript 'jquery.tmplPlus.js'
40
42
  javascript 'jquery.tmplPlus.min.js'
43
+ javascript 'json.js'
44
+ javascript 'json.min.js'
41
45
  image 'jquery/ui/contextMenu/cut.png'
42
46
  image 'jquery/ui/contextMenu/door.png'
43
47
  image 'jquery/ui/contextMenu/page_white_copy.png'
@@ -79,6 +83,8 @@ javascript 'jquery-ui.js'
79
83
  javascript 'jquery-ui.min.js'
80
84
  javascript 'i18n/jquery.ui/datepicker-af.js'
81
85
  javascript 'i18n/jquery.ui/datepicker-af.min.js'
86
+ javascript 'i18n/jquery.ui/datepicker-ar-DZ.js'
87
+ javascript 'i18n/jquery.ui/datepicker-ar-DZ.min.js'
82
88
  javascript 'i18n/jquery.ui/datepicker-ar.js'
83
89
  javascript 'i18n/jquery.ui/datepicker-ar.min.js'
84
90
  javascript 'i18n/jquery.ui/datepicker-az.js'
@@ -97,8 +103,12 @@ javascript 'i18n/jquery.ui/datepicker-de.js'
97
103
  javascript 'i18n/jquery.ui/datepicker-de.min.js'
98
104
  javascript 'i18n/jquery.ui/datepicker-el.js'
99
105
  javascript 'i18n/jquery.ui/datepicker-el.min.js'
106
+ javascript 'i18n/jquery.ui/datepicker-en-AU.js'
107
+ javascript 'i18n/jquery.ui/datepicker-en-AU.min.js'
100
108
  javascript 'i18n/jquery.ui/datepicker-en-GB.js'
101
109
  javascript 'i18n/jquery.ui/datepicker-en-GB.min.js'
110
+ javascript 'i18n/jquery.ui/datepicker-en-NZ.js'
111
+ javascript 'i18n/jquery.ui/datepicker-en-NZ.min.js'
102
112
  javascript 'i18n/jquery.ui/datepicker-eo.js'
103
113
  javascript 'i18n/jquery.ui/datepicker-eo.min.js'
104
114
  javascript 'i18n/jquery.ui/datepicker-es.js'
@@ -143,6 +153,8 @@ javascript 'i18n/jquery.ui/datepicker-lt.js'
143
153
  javascript 'i18n/jquery.ui/datepicker-lt.min.js'
144
154
  javascript 'i18n/jquery.ui/datepicker-lv.js'
145
155
  javascript 'i18n/jquery.ui/datepicker-lv.min.js'
156
+ javascript 'i18n/jquery.ui/datepicker-ml.js'
157
+ javascript 'i18n/jquery.ui/datepicker-ml.min.js'
146
158
  javascript 'i18n/jquery.ui/datepicker-ms.js'
147
159
  javascript 'i18n/jquery.ui/datepicker-ms.min.js'
148
160
  javascript 'i18n/jquery.ui/datepicker-nl.js'
@@ -1,7 +1,7 @@
1
1
  /*!
2
- * jQuery UI Widget @VERSION
2
+ * jQuery UI Widget 1.8.9
3
3
  *
4
- * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
4
+ * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
5
5
  * Dual licensed under the MIT or GPL Version 2 licenses.
6
6
  * http://jquery.org/license
7
7
  *
@@ -96,15 +96,19 @@ $.widget.bridge = function( name, object ) {
96
96
 
97
97
  if ( isMethodCall ) {
98
98
  this.each(function() {
99
- var instance = $.data( this, name );
100
- if ( !instance ) {
101
- throw "cannot call methods on " + name + " prior to initialization; " +
102
- "attempted to call method '" + options + "'";
103
- }
104
- if ( !$.isFunction( instance[options] ) ) {
105
- throw "no such method '" + options + "' for " + name + " widget instance";
106
- }
107
- var methodValue = instance[ options ].apply( instance, args );
99
+ var instance = $.data( this, name ),
100
+ methodValue = instance && $.isFunction( instance[options] ) ?
101
+ instance[ options ].apply( instance, args ) :
102
+ instance;
103
+ // TODO: add this back in 1.9 and use $.error() (see #5972)
104
+ // if ( !instance ) {
105
+ // throw "cannot call methods on " + name + " prior to initialization; " +
106
+ // "attempted to call method '" + options + "'";
107
+ // }
108
+ // if ( !$.isFunction( instance[options] ) ) {
109
+ // throw "no such method '" + options + "' for " + name + " widget instance";
110
+ // }
111
+ // var methodValue = instance[ options ].apply( instance, args );
108
112
  if ( methodValue !== instance && methodValue !== undefined ) {
109
113
  returnValue = methodValue;
110
114
  return false;
@@ -158,11 +162,7 @@ $.Widget.prototype = {
158
162
  this._init();
159
163
  },
160
164
  _getCreateOptions: function() {
161
- var options = {};
162
- if ( $.metadata ) {
163
- options = $.metadata.get( element )[ this.widgetName ];
164
- }
165
- return options;
165
+ return $.metadata && $.metadata.get( this.element[0] )[ this.widgetName ];
166
166
  },
167
167
  _create: function() {},
168
168
  _init: function() {},
@@ -319,9 +319,17 @@ $.mobile.media = (function() {
319
319
 
320
320
  return function( query ) {
321
321
  if ( !( query in cache ) ) {
322
- var styleBlock = $( "<style type='text/css'>" +
323
- "@media " + query + "{#jquery-mediatest{position:absolute;}}" +
324
- "</style>" );
322
+ var styleBlock = document.createElement('style'),
323
+ cssrule = "@media " + query + " { #jquery-mediatest { position:absolute; } }";
324
+ //must set type for IE!
325
+ styleBlock.type = "text/css";
326
+ if (styleBlock.styleSheet){
327
+ styleBlock.styleSheet.cssText = cssrule;
328
+ }
329
+ else {
330
+ styleBlock.appendChild(document.createTextNode(cssrule));
331
+ }
332
+
325
333
  $html.prepend( fakeBody ).prepend( styleBlock );
326
334
  cache[ query ] = testDiv.css( "position" ) === "absolute";
327
335
  fakeBody.add( styleBlock ).remove();
@@ -388,11 +396,26 @@ $(document).bind("mobileinit.htmlclass", function(){
388
396
  //add orientation class to HTML element on flip/resize.
389
397
  if(event.orientation){
390
398
  $html.removeClass( "portrait landscape" ).addClass( event.orientation );
399
+ //Set the min-height to the size of the fullscreen. This is to fix issue #455
400
+ if( event.orientation === 'portrait' ) {
401
+ $( '.ui-page' ).css( 'minHeight', ( screen.availHeight >= screen.availWidth ) ? screen.availHeight : screen.availWidth);
402
+ } else {
403
+ $( '.ui-page' ).css( 'minHeight', ( screen.availHeight <= screen.availWidth ) ? screen.availHeight : screen.availWidth);
404
+ }
405
+
406
+ $.mobile.silentScroll();
391
407
  }
392
408
  //add classes to HTML element for min/max breakpoints
393
409
  detectResolutionBreakpoints();
394
410
  });
411
+ });
395
412
 
413
+ /* Manually trigger an orientationchange event when the dom ready event fires.
414
+ This will ensure that any viewport meta tag that may have been injected
415
+ has taken effect already, allowing us to properly calculate the width of the
416
+ document.
417
+ */
418
+ $(function(){
396
419
  //trigger event manually
397
420
  $window.trigger( "orientationchange.htmlclass" );
398
421
  });
@@ -429,11 +452,21 @@ function propExists( prop ){
429
452
  //test for dynamic-updating base tag support (allows us to avoid href,src attr rewriting)
430
453
  function baseTagTest(){
431
454
  var fauxBase = location.protocol + '//' + location.host + location.pathname + "ui-dir/",
432
- base = $("<base>", {"href": fauxBase}).appendTo("head"),
433
- link = $( "<a href='testurl'></a>" ).prependTo( fakeBody ),
455
+ base = $("head base"),
456
+ fauxEle = null,
457
+ href = '';
458
+ if (!base.length) {
459
+ base = fauxEle = $("<base>", {"href": fauxBase}).appendTo("head");
460
+ }
461
+ else {
462
+ href = base.attr("href");
463
+ }
464
+ var link = $( "<a href='testurl'></a>" ).prependTo( fakeBody ),
434
465
  rebase = link[0].href;
435
- base[0].href = location.pathname;
436
- base.remove();
466
+ base[0].href = href ? href : location.pathname;
467
+ if (fauxEle) {
468
+ fauxEle.remove();
469
+ }
437
470
  return rebase.indexOf(fauxBase) === 0;
438
471
  };
439
472
 
@@ -521,20 +554,37 @@ $.event.special.tap = {
521
554
  $this = $( thisObject );
522
555
 
523
556
  $this
524
- .bind( touchStartEvent, function( event ) {
525
- if ( event.which && event.which !== 1 ) {
526
- return;
557
+ .bind( "mousedown touchstart", function( event ) {
558
+ if ( event.which && event.which !== 1 ||
559
+ //check if event fired once already by a device that fires both mousedown and touchstart (while supporting both events)
560
+ $this.data( "prevEvent") && $this.data( "prevEvent") !== event.type ) {
561
+ return false;
527
562
  }
528
563
 
564
+ //save event type so only this type is let through for a temp duration,
565
+ //allowing quick repetitive taps but not duplicative events
566
+ $this.data( "prevEvent", event.type );
567
+ setTimeout(function(){
568
+ $this.removeData( "prevEvent" );
569
+ }, 800);
570
+
529
571
  var moved = false,
530
572
  touching = true,
531
- origPos = [ event.pageX, event.pageY ],
573
+ origTarget = event.target,
574
+ origEvent = event.originalEvent,
575
+ origPos = event.type == "touchstart" ? [origEvent.touches[0].pageX, origEvent.touches[0].pageY] : [ event.pageX, event.pageY ],
532
576
  originalType,
533
577
  timer;
578
+
534
579
 
535
- function moveHandler() {
536
- if ((Math.abs(origPos[0] - event.pageX) > 10) ||
537
- (Math.abs(origPos[1] - event.pageY) > 10)) {
580
+ function moveHandler( event ) {
581
+ if( event.type == "scroll" ){
582
+ moved = true;
583
+ return;
584
+ }
585
+ var newPageXY = event.type == "touchmove" ? event.originalEvent.touches[0] : event;
586
+ if ((Math.abs(origPos[0] - newPageXY.pageX) > 10) ||
587
+ (Math.abs(origPos[1] - newPageXY.pageY) > 10)) {
538
588
  moved = true;
539
589
  }
540
590
  }
@@ -548,14 +598,21 @@ $.event.special.tap = {
548
598
  }
549
599
  }, 750 );
550
600
 
601
+ //scroll now cancels tap
602
+ $(window).one("scroll", moveHandler);
603
+
551
604
  $this
552
- .one( touchMoveEvent, moveHandler)
553
- .one( touchStopEvent, function( event ) {
554
- $this.unbind( touchMoveEvent, moveHandler );
605
+ .bind( "mousemove touchmove", moveHandler )
606
+ .one( "mouseup touchend", function( event ) {
607
+ $this.unbind( "mousemove touchmove", moveHandler );
608
+ $(window).unbind("scroll", moveHandler);
555
609
  clearTimeout( timer );
556
610
  touching = false;
557
611
 
558
- if ( !moved ) {
612
+ /* ONLY trigger a 'tap' event if the start target is
613
+ * the same as the stop target.
614
+ */
615
+ if ( !moved && ( origTarget == event.target ) ) {
559
616
  originalType = event.type;
560
617
  event.type = "tap";
561
618
  $.event.handle.call( thisObject, event );
@@ -1096,6 +1153,217 @@ $.each({
1096
1153
  })(jQuery,this);
1097
1154
 
1098
1155
 
1156
+ /*
1157
+ * jQuery Mobile Framework : "page" plugin
1158
+ * Copyright (c) jQuery Project
1159
+ * Dual licensed under the MIT or GPL Version 2 licenses.
1160
+ * http://jquery.org/license
1161
+ */
1162
+ (function($, undefined ) {
1163
+
1164
+ $.widget( "mobile.page", $.mobile.widget, {
1165
+ options: {
1166
+ backBtnText: "Back",
1167
+ addBackBtn: true,
1168
+ degradeInputs: {
1169
+ color: false,
1170
+ date: false,
1171
+ datetime: false,
1172
+ "datetime-local": false,
1173
+ email: false,
1174
+ month: false,
1175
+ number: false,
1176
+ range: "number",
1177
+ search: true,
1178
+ tel: false,
1179
+ time: false,
1180
+ url: false,
1181
+ week: false
1182
+ },
1183
+ keepNative: null
1184
+ },
1185
+
1186
+ _create: function() {
1187
+ var $elem = this.element,
1188
+ o = this.options;
1189
+
1190
+ this.keepNative = "[data-role='none'], [data-role='nojs']" + (o.keepNative ? ", " + o.keepNative : "");
1191
+
1192
+ if ( this._trigger( "beforeCreate" ) === false ) {
1193
+ return;
1194
+ }
1195
+
1196
+ if( $( "html" ).hasClass( 'portrait' ) ) {
1197
+ $elem.css( 'minHeight', ( screen.availHeight >= screen.availWidth ) ? screen.availHeight : screen.availWidth);
1198
+ } else {
1199
+ $elem.css( 'minHeight', ( screen.availHeight <= screen.availWidth ) ? screen.availHeight : screen.availWidth);
1200
+ }
1201
+
1202
+ //some of the form elements currently rely on the presence of ui-page and ui-content
1203
+ // classes so we'll handle page and content roles outside of the main role processing
1204
+ // loop below.
1205
+ $elem.find( "[data-role='page'], [data-role='content']" ).andSelf().each(function() {
1206
+ $(this).addClass( "ui-" + $(this).data( "role" ) );
1207
+ });
1208
+
1209
+ $elem.find( "[data-role='nojs']" ).addClass( "ui-nojs" );
1210
+
1211
+ // pre-find data els
1212
+ var $dataEls = $elem.find( "[data-role]" ).andSelf().each(function() {
1213
+ var $this = $( this ),
1214
+ role = $this.data( "role" ),
1215
+ theme = $this.data( "theme" );
1216
+
1217
+ //apply theming and markup modifications to page,header,content,footer
1218
+ if ( role === "header" || role === "footer" ) {
1219
+ $this.addClass( "ui-bar-" + (theme || $this.parent('[data-role=page]').data( "theme" ) || "a") );
1220
+
1221
+ // add ARIA role
1222
+ $this.attr( "role", role === "header" ? "banner" : "contentinfo" );
1223
+
1224
+ //right,left buttons
1225
+ var $headeranchors = $this.children( "a" ),
1226
+ leftbtn = $headeranchors.hasClass( "ui-btn-left" ),
1227
+ rightbtn = $headeranchors.hasClass( "ui-btn-right" );
1228
+
1229
+ if ( !leftbtn ) {
1230
+ leftbtn = $headeranchors.eq( 0 ).not( ".ui-btn-right" ).addClass( "ui-btn-left" ).length;
1231
+ }
1232
+
1233
+ if ( !rightbtn ) {
1234
+ rightbtn = $headeranchors.eq( 1 ).addClass( "ui-btn-right" ).length;
1235
+ }
1236
+
1237
+ // auto-add back btn on pages beyond first view
1238
+ if ( o.addBackBtn && role === "header" &&
1239
+ $.mobile.urlHistory.stack.length > 0 &&
1240
+ !leftbtn && $this.data( "backbtn" ) !== false ) {
1241
+
1242
+ $( "<a href='#' class='ui-btn-left' data-rel='back' data-icon='arrow-l'>"+ o.backBtnText +"</a>" ).prependTo( $this );
1243
+ }
1244
+
1245
+ //page title
1246
+ $this.children( "h1, h2, h3, h4, h5, h6" )
1247
+ .addClass( "ui-title" )
1248
+ //regardless of h element number in src, it becomes h1 for the enhanced page
1249
+ .attr({ "tabindex": "0", "role": "heading", "aria-level": "1" });
1250
+
1251
+ } else if ( role === "content" ) {
1252
+ if ( theme ) {
1253
+ $this.addClass( "ui-body-" + theme );
1254
+ }
1255
+
1256
+ // add ARIA role
1257
+ $this.attr( "role", "main" );
1258
+
1259
+ } else if ( role === "page" ) {
1260
+ $this.addClass( "ui-body-" + (theme || "c") );
1261
+ }
1262
+
1263
+ switch(role) {
1264
+ case "header":
1265
+ case "footer":
1266
+ case "page":
1267
+ case "content":
1268
+ $this.addClass( "ui-" + role );
1269
+ break;
1270
+ case "collapsible":
1271
+ case "fieldcontain":
1272
+ case "navbar":
1273
+ case "listview":
1274
+ case "dialog":
1275
+ $this[ role ]();
1276
+ break;
1277
+ }
1278
+ });
1279
+
1280
+ //enhance form controls
1281
+ this._enhanceControls();
1282
+
1283
+ //links in bars, or those with data-role become buttons
1284
+ $elem.find( "[data-role='button'], .ui-bar > a, .ui-header > a, .ui-footer > a" )
1285
+ .not( ".ui-btn" )
1286
+ .not(this.keepNative)
1287
+ .buttonMarkup();
1288
+
1289
+ $elem
1290
+ .find("[data-role='controlgroup']")
1291
+ .controlgroup();
1292
+
1293
+ //links within content areas
1294
+ $elem.find( "a:not(.ui-btn):not(.ui-link-inherit)" )
1295
+ .not(this.keepNative)
1296
+ .addClass( "ui-link" );
1297
+
1298
+ //fix toolbars
1299
+ $elem.fixHeaderFooter();
1300
+ },
1301
+
1302
+ _enhanceControls: function() {
1303
+ var o = this.options;
1304
+
1305
+ // degrade inputs to avoid poorly implemented native functionality
1306
+ this.element.find( "input" ).not(this.keepNative).each(function() {
1307
+ var type = this.getAttribute( "type" ),
1308
+ optType = o.degradeInputs[ type ] || "text";
1309
+
1310
+ if ( o.degradeInputs[ type ] ) {
1311
+ $( this ).replaceWith(
1312
+ $( "<div>" ).html( $(this).clone() ).html()
1313
+ .replace( /type="([a-zA-Z]+)"/, "type="+ optType +" data-type='$1'" ) );
1314
+ }
1315
+ });
1316
+
1317
+ // We re-find form elements since the degredation code above
1318
+ // may have injected new elements. We cache the non-native control
1319
+ // query to reduce the number of times we search through the entire page.
1320
+
1321
+ var allControls = this.element.find("input, textarea, select, button"),
1322
+ nonNativeControls = allControls.not(this.keepNative);
1323
+
1324
+ // XXX: Temporary workaround for issue 785. Turn off autocorrect and
1325
+ // autocomplete since the popup they use can't be dismissed by
1326
+ // the user. Note that we test for the presence of the feature
1327
+ // by looking for the autocorrect property on the input element.
1328
+
1329
+ var textInputs = allControls.filter( "input[type=text]" );
1330
+ if (textInputs.length && typeof textInputs[0].autocorrect !== "undefined") {
1331
+ textInputs.each(function(){
1332
+ // Set the attribute instead of the property just in case there
1333
+ // is code that attempts to make modifications via HTML.
1334
+ this.setAttribute("autocorrect", "off");
1335
+ this.setAttribute("autocomplete", "off");
1336
+ });
1337
+ }
1338
+
1339
+ // enchance form controls
1340
+ nonNativeControls
1341
+ .filter( "[type='radio'], [type='checkbox']" )
1342
+ .checkboxradio();
1343
+
1344
+ nonNativeControls
1345
+ .filter( "button, [type='button'], [type='submit'], [type='reset'], [type='image']" )
1346
+ .button();
1347
+
1348
+ nonNativeControls
1349
+ .filter( "input, textarea" )
1350
+ .not( "[type='radio'], [type='checkbox'], [type='button'], [type='submit'], [type='reset'], [type='image'], [type='hidden']" )
1351
+ .textinput();
1352
+
1353
+ nonNativeControls
1354
+ .filter( "input, select" )
1355
+ .filter( "[data-role='slider'], [data-type='range']" )
1356
+ .slider();
1357
+
1358
+ nonNativeControls
1359
+ .filter( "select:not([data-role='slider'])" )
1360
+ .selectmenu();
1361
+ }
1362
+ });
1363
+
1364
+ })( jQuery );
1365
+
1366
+
1099
1367
  /*!
1100
1368
  * jQuery Mobile v@VERSION
1101
1369
  * http://jquerymobile.com/
@@ -1125,9 +1393,14 @@ $.each({
1125
1393
  //class used for "active" button state, from CSS framework
1126
1394
  activeBtnClass: 'ui-btn-active',
1127
1395
 
1396
+ //automatically handle clicks and form submissions through Ajax, when same-domain
1397
+ ajaxEnabled: true,
1398
+
1399
+ // TODO: deprecated - remove at 1.0
1128
1400
  //automatically handle link clicks through Ajax, when possible
1129
1401
  ajaxLinksEnabled: true,
1130
1402
 
1403
+ // TODO: deprecated - remove at 1.0
1131
1404
  //automatically handle form submissions through Ajax, when possible
1132
1405
  ajaxFormsEnabled: true,
1133
1406
 
@@ -1141,6 +1414,8 @@ $.each({
1141
1414
  //configure meta viewport tag's content attr:
1142
1415
  metaViewportContent: "width=device-width, minimum-scale=1, maximum-scale=1",
1143
1416
 
1417
+ nativeSelectMenus: false,
1418
+
1144
1419
  //support conditions that must be met in order to proceed
1145
1420
  gradeA: function(){
1146
1421
  return $.support.mediaquery;
@@ -1184,11 +1459,11 @@ $.each({
1184
1459
  });
1185
1460
 
1186
1461
 
1187
- //trigger mobileinit event - useful hook for configuring $.mobile settings before they're used
1462
+ //trigger mobileinit event - useful hook for configuring $.mobile settings before they're used
1188
1463
  $( window.document ).trigger('mobileinit');
1189
1464
 
1190
1465
 
1191
- //support conditions
1466
+ //support conditions
1192
1467
  //if device support condition(s) aren't met, leave things as they are -> a basic, usable experience,
1193
1468
  //otherwise, proceed with the enhancements
1194
1469
  if ( !$.mobile.gradeA() ) {
@@ -1196,7 +1471,7 @@ $.each({
1196
1471
  }
1197
1472
 
1198
1473
 
1199
- //define vars for interal use
1474
+ //define vars for interal use
1200
1475
  var $window = $(window),
1201
1476
  $html = $('html'),
1202
1477
  $head = $('head'),
@@ -1211,15 +1486,15 @@ $.each({
1211
1486
  : undefined;
1212
1487
 
1213
1488
 
1214
- //add mobile, initial load "rendering" classes to docEl
1489
+ //add mobile, initial load "rendering" classes to docEl
1215
1490
  $html.addClass('ui-mobile ui-mobile-rendering');
1216
1491
 
1217
1492
 
1218
- //define & prepend meta viewport tag, if content is defined
1493
+ //define & prepend meta viewport tag, if content is defined
1219
1494
  $.mobile.metaViewportContent ? $("<meta>", { name: "viewport", content: $.mobile.metaViewportContent}).prependTo( $head ) : undefined;
1220
1495
 
1221
1496
 
1222
- //expose some core utilities
1497
+ //expose some core utilities
1223
1498
  $.extend($.mobile, {
1224
1499
 
1225
1500
  // turn on/off page loading message.
@@ -1228,7 +1503,9 @@ $.each({
1228
1503
  $html.removeClass( "ui-loading" );
1229
1504
  } else {
1230
1505
  if( $.mobile.loadingMessage ){
1231
- $loader.appendTo($.mobile.pageContainer).css({top: $(window).scrollTop() + 75});
1506
+ var activeLink = $( "." + $.mobile.activeBtnClass ).eq(0),
1507
+ yPos = activeLink.length ? activeLink.offset().top : $(window).scrollTop() + 75;
1508
+ $loader.appendTo($.mobile.pageContainer).css({top: yPos});
1232
1509
  }
1233
1510
  $html.addClass( "ui-loading" );
1234
1511
  }
@@ -1236,10 +1513,12 @@ $.each({
1236
1513
 
1237
1514
  //scroll page vertically: scroll to 0 to hide iOS address bar, or pass a Y value
1238
1515
  silentScroll: function( ypos ) {
1516
+ ypos = ypos || 0;
1239
1517
  // prevent scrollstart and scrollstop events
1240
1518
  $.event.special.scrollstart.enabled = false;
1241
1519
  setTimeout(function() {
1242
- window.scrollTo( 0, ypos || 0 );
1520
+ window.scrollTo( 0, ypos );
1521
+ $(document).trigger("silentscroll", { x: 0, y: ypos });
1243
1522
  },20);
1244
1523
  setTimeout(function() {
1245
1524
  $.event.special.scrollstart.enabled = true;
@@ -1248,13 +1527,13 @@ $.each({
1248
1527
  });
1249
1528
 
1250
1529
 
1251
- //dom-ready inits
1530
+ //dom-ready inits
1252
1531
  $(function(){
1253
1532
 
1254
1533
  //find present pages
1255
1534
  var $pages = $("[data-role='page']");
1256
1535
 
1257
- $pages.each(function(){
1536
+ $("[data-role='page'], [data-role='dialog']").each(function(){
1258
1537
  $(this).attr('data-url', $(this).attr('id'));
1259
1538
  });
1260
1539
 
@@ -1278,7 +1557,7 @@ $.each({
1278
1557
  });
1279
1558
 
1280
1559
 
1281
- //window load event
1560
+ //window load event
1282
1561
  //hide iOS browser chrome on load
1283
1562
  $window.load( $.mobile.silentScroll );
1284
1563
 
@@ -1306,24 +1585,17 @@ $.each({
1306
1585
  if( newPath == undefined ){
1307
1586
  newPath = location.hash;
1308
1587
  }
1309
- newPath = newPath.replace(/#/,'').split('/');
1310
- if(newPath.length){
1311
- var lastSegment = newPath[newPath.length-1];
1312
- if( lastSegment.indexOf('.') > -1 || lastSegment == ''){
1313
- newPath.pop();
1314
- }
1315
- }
1316
- return newPath.join('/') + (newPath.length ? '/' : '');
1588
+ return path.stripHash( newPath ).replace(/[^\/]*\.[^\/*]+$/, '');
1317
1589
  },
1318
1590
 
1319
1591
  //return the substring of a filepath before the sub-page key, for making a server request
1320
1592
  getFilePath: function( path ){
1321
1593
  var splitkey = '&' + $.mobile.subPageUrlKey;
1322
- return path && path.indexOf( splitkey ) > -1 ? path.split( splitkey )[0] : path;
1594
+ return path && path.split( splitkey )[0].split( dialogHashKey )[0];
1323
1595
  },
1324
-
1325
- set: function( path, disableListening){
1326
- if(disableListening) { hashListener = false; }
1596
+
1597
+ //set location hash to path
1598
+ set: function( path ){
1327
1599
  location.hash = path;
1328
1600
  },
1329
1601
 
@@ -1332,48 +1604,147 @@ $.each({
1332
1604
 
1333
1605
  setOrigin: function(){
1334
1606
  path.origin = path.get( location.protocol + '//' + location.host + location.pathname );
1607
+ },
1608
+
1609
+ //prefix a relative url with the current path
1610
+ makeAbsolute: function( url ){
1611
+ return path.get() + url;
1612
+ },
1613
+
1614
+ //return a url path with the window's location protocol/hostname removed
1615
+ clean: function( url ){
1616
+ return url.replace( location.protocol + "//" + location.host, "");
1617
+ },
1618
+
1619
+ //just return the url without an initial #
1620
+ stripHash: function( url ){
1621
+ return url.replace( /^#/, "" );
1622
+ },
1623
+
1624
+ //check whether a url is referencing the same domain, or an external domain or different protocol
1625
+ //could be mailto, etc
1626
+ isExternal: function( url ){
1627
+ return path.hasProtocol( path.clean( url ) );
1628
+ },
1629
+
1630
+ hasProtocol: function( url ){
1631
+ return /^(:?\w+:)/.test( url );
1632
+ },
1633
+
1634
+ //check if the url is relative
1635
+ isRelative: function( url ){
1636
+ return /^[^\/|#]/.test( url ) && !path.hasProtocol( url );
1335
1637
  }
1336
1638
  },
1337
1639
 
1640
+ //will be defined when a link is clicked and given an active class
1641
+ $activeClickedLink = null,
1642
+
1643
+ //urlHistory is purely here to make guesses at whether the back or forward button was clicked
1644
+ //and provide an appropriate transition
1645
+ urlHistory = {
1646
+ //array of pages that are visited during a single page load. each has a url and optional transition
1647
+ stack: [],
1648
+
1649
+ //maintain an index number for the active page in the stack
1650
+ activeIndex: 0,
1651
+
1652
+ //get active
1653
+ getActive: function(){
1654
+ return urlHistory.stack[ urlHistory.activeIndex ];
1655
+ },
1656
+
1657
+ getPrev: function(){
1658
+ return urlHistory.stack[ urlHistory.activeIndex - 1 ];
1659
+ },
1660
+
1661
+ getNext: function(){
1662
+ return urlHistory.stack[ urlHistory.activeIndex + 1 ];
1663
+ },
1664
+
1665
+ // addNew is used whenever a new page is added
1666
+ addNew: function( url, transition ){
1667
+ //if there's forward history, wipe it
1668
+ if( urlHistory.getNext() ){
1669
+ urlHistory.clearForward();
1670
+ }
1671
+
1672
+ urlHistory.stack.push( {url : url, transition: transition } );
1673
+
1674
+ urlHistory.activeIndex = urlHistory.stack.length - 1;
1675
+ },
1676
+
1677
+ //wipe urls ahead of active index
1678
+ clearForward: function(){
1679
+ urlHistory.stack = urlHistory.stack.slice( 0, urlHistory.activeIndex + 1 );
1680
+ },
1681
+
1682
+ //enable/disable hashchange event listener
1683
+ //toggled internally when location.hash is updated to match the url of a successful page load
1684
+ listeningEnabled: true
1685
+ },
1686
+
1687
+ //define first selector to receive focus when a page is shown
1688
+ focusable = "[tabindex],a,button:visible,select:visible,input",
1689
+
1690
+ //contains role for next page, if defined on clicked link via data-rel
1691
+ nextPageRole = null,
1692
+
1693
+ //nonsense hash change key for dialogs, so they create a history entry
1694
+ dialogHashKey = "&ui-state=dialog";
1695
+
1696
+ //existing base tag?
1697
+ var $base = $head.children("base"),
1698
+ hostURL = location.protocol + '//' + location.host,
1699
+ docLocation = path.get( hostURL + location.pathname ),
1700
+ docBase = docLocation;
1701
+
1702
+ if ($base.length){
1703
+ var href = $base.attr("href");
1704
+ if (href){
1705
+ if (href.search(/^[^:/]+:\/\/[^/]+\/?/) == -1){
1706
+ //the href is not absolute, we need to turn it into one
1707
+ //so that we can turn paths stored in our location hash into
1708
+ //relative paths.
1709
+ if (href.charAt(0) == '/'){
1710
+ //site relative url
1711
+ docBase = hostURL + href;
1712
+ }
1713
+ else {
1714
+ //the href is a document relative url
1715
+ docBase = docLocation + href;
1716
+ //XXX: we need some code here to calculate the final path
1717
+ // just in case the docBase contains up-level (../) references.
1718
+ }
1719
+ }
1720
+ else {
1721
+ //the href is an absolute url
1722
+ docBase = href;
1723
+ }
1724
+ }
1725
+ //make sure docBase ends with a slash
1726
+ docBase = docBase + (docBase.charAt(docBase.length - 1) == '/' ? ' ' : '/');
1727
+ }
1728
+
1338
1729
  //base element management, defined depending on dynamic base tag support
1339
1730
  base = $.support.dynamicBaseTag ? {
1340
1731
 
1341
1732
  //define base element, for use in routing asset urls that are referenced in Ajax-requested markup
1342
- element: $("<base>", { href: path.origin }).prependTo( $head ),
1733
+ element: ($base.length ? $base : $("<base>", { href: docBase }).prependTo( $head )),
1343
1734
 
1344
1735
  //set the generated BASE element's href attribute to a new page's base path
1345
1736
  set: function( href ){
1346
- base.element.attr('href', path.origin + path.get( href ));
1737
+ base.element.attr('href', docBase + path.get( href ));
1347
1738
  },
1348
1739
 
1349
1740
  //set the generated BASE element's href attribute to a new page's base path
1350
1741
  reset: function(){
1351
- base.element.attr('href', path.origin );
1742
+ base.element.attr('href', docBase );
1352
1743
  }
1353
1744
 
1354
- } : undefined,
1355
-
1745
+ } : undefined;
1356
1746
 
1357
- //will be defined when a link is clicked and given an active class
1358
- $activeClickedLink = null,
1359
1747
 
1360
- //array of pages that are visited during a single page load
1361
- //length will grow as pages are visited, and shrink as "back" link/button is clicked
1362
- //each item has a url (string matches ID), and transition (saved for reuse when "back" link/button is clicked)
1363
- urlStack = [ {
1364
- url: location.hash.replace( /^#/, "" ),
1365
- transition: undefined
1366
- } ],
1367
-
1368
- //define first selector to receive focus when a page is shown
1369
- focusable = "[tabindex],a,button:visible,select:visible,input",
1370
-
1371
- //contains role for next page, if defined on clicked link via data-rel
1372
- nextPageRole = null,
1373
-
1374
- //enable/disable hashchange event listener
1375
- //toggled internally when location.hash is updated to match the url of a successful page load
1376
- hashListener = true;
1377
1748
 
1378
1749
  //set location pathname from intial directory request
1379
1750
  path.setOrigin();
@@ -1402,7 +1773,6 @@ $.each({
1402
1773
  $activeClickedLink = null;
1403
1774
  };
1404
1775
 
1405
-
1406
1776
  //animation complete callback
1407
1777
  $.fn.animationComplete = function( callback ){
1408
1778
  if($.support.cssTransitions){
@@ -1418,37 +1788,87 @@ $.each({
1418
1788
  /* exposed $.mobile methods */
1419
1789
 
1420
1790
  //update location.hash, with or without triggering hashchange event
1791
+ //TODO - deprecate this one at 1.0
1421
1792
  $.mobile.updateHash = path.set;
1793
+
1794
+ //expose path object on $.mobile
1795
+ $.mobile.path = path;
1796
+
1797
+ //expose base object on $.mobile
1798
+ $.mobile.base = base;
1422
1799
 
1423
1800
  //url stack, useful when plugins need to be aware of previous pages viewed
1424
- $.mobile.urlStack = urlStack;
1801
+ //TODO: deprecate this one at 1.0
1802
+ $.mobile.urlstack = urlHistory.stack;
1803
+
1804
+ //history stack
1805
+ $.mobile.urlHistory = urlHistory;
1425
1806
 
1426
1807
  // changepage function
1427
- $.mobile.changePage = function( to, transition, back, changeHash){
1428
-
1808
+ // TODO : consider moving args to an object hash
1809
+ $.mobile.changePage = function( to, transition, reverse, changeHash, fromHashChange ){
1429
1810
  //from is always the currently viewed page
1430
1811
  var toIsArray = $.type(to) === "array",
1812
+ toIsObject = $.type(to) === "object",
1431
1813
  from = toIsArray ? to[0] : $.mobile.activePage,
1432
1814
  to = toIsArray ? to[1] : to,
1433
- url = fileUrl = $.type(to) === "string" ? to.replace( /^#/, "" ) : null,
1815
+ url = fileUrl = $.type(to) === "string" ? path.stripHash( to ) : "",
1434
1816
  data = undefined,
1435
1817
  type = 'get',
1436
1818
  isFormRequest = false,
1437
1819
  duplicateCachedPage = null,
1438
- back = (back !== undefined) ? back : ( urlStack.length > 1 && urlStack[ urlStack.length - 2 ].url === url );
1439
-
1440
- //If we are trying to transition to the same page that we are currently on ignore the request.
1441
- if(urlStack.length > 1 && url === urlStack[urlStack.length -1].url && !toIsArray ) {
1820
+ currPage = urlHistory.getActive(),
1821
+ back = false,
1822
+ forward = false;
1823
+
1824
+
1825
+ // If we are trying to transition to the same page that we are currently on ignore the request.
1826
+ // an illegal same page request is defined by the current page being the same as the url, as long as there's history
1827
+ // and to is not an array or object (those are allowed to be "same")
1828
+ if( currPage && urlHistory.stack.length > 1 && currPage.url === url && !toIsArray && !toIsObject ) {
1442
1829
  return;
1830
+ }
1831
+
1832
+ // if the changePage was sent from a hashChange event
1833
+ // guess if it came from the history menu
1834
+ if( fromHashChange ){
1835
+
1836
+ // check if url is in history and if it's ahead or behind current page
1837
+ $.each( urlHistory.stack, function( i ){
1838
+ //if the url is in the stack, it's a forward or a back
1839
+ if( this.url == url ){
1840
+ urlIndex = i;
1841
+ //define back and forward by whether url is older or newer than current page
1842
+ back = i < urlHistory.activeIndex;
1843
+ //forward set to opposite of back
1844
+ forward = !back;
1845
+ //reset activeIndex to this one
1846
+ urlHistory.activeIndex = i;
1847
+ }
1848
+ });
1849
+
1850
+ //if it's a back, use reverse animation
1851
+ if( back ){
1852
+ reverse = true;
1853
+ transition = transition || currPage.transition;
1854
+ }
1855
+ else if ( forward ){
1856
+ transition = transition || urlHistory.getActive().transition;
1857
+ }
1443
1858
  }
1859
+
1444
1860
 
1445
- if( $.type(to) === "object" && to.url ){
1861
+ if( toIsObject && to.url ){
1446
1862
  url = to.url,
1447
1863
  data = to.data,
1448
1864
  type = to.type,
1449
1865
  isFormRequest = true;
1450
1866
  //make get requests bookmarkable
1451
1867
  if( data && type == 'get' ){
1868
+ if($.type( data ) == "object" ){
1869
+ data = $.param(data);
1870
+ }
1871
+
1452
1872
  url += "?" + data;
1453
1873
  data = undefined;
1454
1874
  }
@@ -1466,32 +1886,19 @@ $.each({
1466
1886
  }
1467
1887
  }
1468
1888
 
1469
- // if the new href is the same as the previous one
1470
- if ( back ) {
1471
- var pop = urlStack.pop();
1472
-
1473
- // prefer the explicitly set transition
1474
- if( pop && !transition ){
1475
- transition = pop.transition;
1476
- }
1477
-
1478
- // ensure a transition has been set where pop is undefined
1479
- defaultTransition();
1480
- } else {
1481
- // If no transition has been passed
1482
- defaultTransition();
1483
-
1484
- // push the url and transition onto the stack
1485
- urlStack.push({ url: url, transition: transition });
1486
- }
1487
-
1488
1889
  //function for transitioning between two existing pages
1489
1890
  function transitionPages() {
1891
+ $.mobile.silentScroll();
1490
1892
 
1491
1893
  //get current scroll distance
1492
1894
  var currScroll = $window.scrollTop(),
1493
1895
  perspectiveTransitions = ["flip"],
1494
1896
  pageContainerClasses = [];
1897
+
1898
+ //support deep-links to generated sub-pages
1899
+ if( url.indexOf( "&" + $.mobile.subPageUrlKey ) > -1 ){
1900
+ to = $( "[data-url='" + url + "']" );
1901
+ }
1495
1902
 
1496
1903
  //set as data for returning to that spot
1497
1904
  from.data('lastScroll', currScroll);
@@ -1501,28 +1908,36 @@ $.each({
1501
1908
  to.data("page")._trigger("beforeshow", {prevPage: from});
1502
1909
 
1503
1910
  function loadComplete(){
1504
- $.mobile.pageLoading( true );
1505
-
1506
- reFocus( to );
1507
1911
 
1508
1912
  if( changeHash !== false && url ){
1509
- path.set(url, (back !== true));
1913
+ if( !back ){
1914
+ urlHistory.listeningEnabled = false;
1915
+ }
1916
+ path.set( url );
1917
+ urlHistory.listeningEnabled = true;
1510
1918
  }
1511
- removeActiveLinkClass();
1512
-
1513
- //if there's a duplicateCachedPage, remove it from the DOM now that it's hidden
1514
- if( duplicateCachedPage != null ){
1515
- duplicateCachedPage.remove();
1919
+
1920
+ //add page to history stack if it's not back or forward
1921
+ if( !back && !forward ){
1922
+ urlHistory.addNew( url, transition );
1516
1923
  }
1924
+
1925
+ removeActiveLinkClass();
1517
1926
 
1518
- //jump to top or prev scroll, if set
1519
- $.mobile.silentScroll( to.data( 'lastScroll' ) );
1927
+ //jump to top or prev scroll, sometimes on iOS the page has not rendered yet. I could only get by this with a setTimeout, but would like to avoid that.
1928
+ $.mobile.silentScroll( to.data( 'lastScroll' ) );
1929
+ reFocus( to );
1520
1930
 
1521
1931
  //trigger show/hide events, allow preventing focus change through return false
1522
1932
  from.data("page")._trigger("hide", null, {nextPage: to});
1523
1933
  if( to.data("page")._trigger("show", null, {prevPage: from}) !== false ){
1524
1934
  $.mobile.activePage = to;
1525
1935
  }
1936
+
1937
+ //if there's a duplicateCachedPage, remove it from the DOM now that it's hidden
1938
+ if (duplicateCachedPage != null) {
1939
+ duplicateCachedPage.remove();
1940
+ }
1526
1941
  };
1527
1942
 
1528
1943
  function addContainerClass(className){
@@ -1537,18 +1952,25 @@ $.each({
1537
1952
 
1538
1953
  pageContainerClasses = [];
1539
1954
  };
1955
+
1956
+
1540
1957
 
1541
1958
  if(transition && (transition !== 'none')){
1542
- if( perspectiveTransitions.indexOf(transition) >= 0 ){
1959
+ $.mobile.pageLoading( true );
1960
+ if( $.inArray(transition, perspectiveTransitions) >= 0 ){
1543
1961
  addContainerClass('ui-mobile-viewport-perspective');
1544
1962
  }
1545
1963
 
1546
1964
  addContainerClass('ui-mobile-viewport-transitioning');
1547
1965
 
1548
- // animate in / out
1549
- from.addClass( transition + " out " + ( back ? "reverse" : "" ) );
1966
+ /* animate in / out
1967
+ * This is in a setTimeout because we were often seeing pages in not animate across but rather go straight to
1968
+ * the 'to' page. The loadComplete would still fire, so the browser thought it was applying the animation. From
1969
+ * what I could tell this was a problem with the classes not being applied yet.
1970
+ */
1971
+ setTimeout(function() { from.addClass( transition + " out " + ( reverse ? "reverse" : "" ) );
1550
1972
  to.addClass( $.mobile.activePageClass + " " + transition +
1551
- " in " + ( back ? "reverse" : "" ) );
1973
+ " in " + ( reverse ? "reverse" : "" ) ); } , 0);
1552
1974
 
1553
1975
  // callback - remove classes, etc
1554
1976
  to.animationComplete(function() {
@@ -1559,6 +1981,7 @@ $.each({
1559
1981
  });
1560
1982
  }
1561
1983
  else{
1984
+ $.mobile.pageLoading( true );
1562
1985
  from.removeClass( $.mobile.activePageClass );
1563
1986
  to.addClass( $.mobile.activePageClass );
1564
1987
  loadComplete();
@@ -1570,7 +1993,7 @@ $.each({
1570
1993
 
1571
1994
  //set next page role, if defined
1572
1995
  if ( nextPageRole || to.data('role') == 'dialog' ) {
1573
- changeHash = false;
1996
+ url = urlHistory.getActive().url + dialogHashKey;
1574
1997
  if(nextPageRole){
1575
1998
  to.attr( "data-role", nextPageRole );
1576
1999
  nextPageRole = null;
@@ -1594,6 +2017,9 @@ $.each({
1594
2017
  fileUrl = toIDfileurl;
1595
2018
  }
1596
2019
  }
2020
+
2021
+ // ensure a transition has been set where pop is undefined
2022
+ defaultTransition();
1597
2023
 
1598
2024
  // find the "to" page, either locally existing in the dom or by creating it through ajax
1599
2025
  if ( to.length && !isFormRequest ) {
@@ -1616,8 +2042,23 @@ $.each({
1616
2042
  type: type,
1617
2043
  data: data,
1618
2044
  success: function( html ) {
1619
- if(base){ base.set(fileUrl); }
2045
+
2046
+ //pre-parse html to check for a data-url,
2047
+ //use it as the new fileUrl, base path, etc
2048
+ var redirectLoc = / data-url="(.*)"/.test( html ) && RegExp.$1;
1620
2049
 
2050
+ if( redirectLoc ){
2051
+ if(base){
2052
+ base.set( redirectLoc );
2053
+ }
2054
+ url = fileUrl = path.makeAbsolute( path.getFilePath( redirectLoc ) );
2055
+ }
2056
+ else {
2057
+ if(base){
2058
+ base.set(fileUrl);
2059
+ }
2060
+ }
2061
+
1621
2062
  var all = $("<div></div>");
1622
2063
  //workaround to allow scripts to execute when included in page divs
1623
2064
  all.get(0).innerHTML = html;
@@ -1638,7 +2079,8 @@ $.each({
1638
2079
  }
1639
2080
  });
1640
2081
  }
1641
-
2082
+
2083
+ //append to page and enhance
1642
2084
  to
1643
2085
  .attr( "data-url", fileUrl )
1644
2086
  .appendTo( $.mobile.pageContainer );
@@ -1667,20 +2109,22 @@ $.each({
1667
2109
  /* Event Bindings - hashchange, submit, and click */
1668
2110
 
1669
2111
  //bind to form submit events, handle with Ajax
1670
- $('form').live('submit', function(event){
1671
- if( !$.mobile.ajaxFormsEnabled ){ return; }
2112
+ $( "form[data-ajax!='false']" ).live('submit', function(event){
2113
+ if( !$.mobile.ajaxEnabled ||
2114
+ //TODO: deprecated - remove at 1.0
2115
+ !$.mobile.ajaxFormsEnabled ){ return; }
1672
2116
 
1673
2117
  var type = $(this).attr("method"),
1674
- url = $(this).attr( "action" ).replace( location.protocol + "//" + location.host, "");
2118
+ url = path.clean( $(this).attr( "action" ) );
1675
2119
 
1676
2120
  //external submits use regular HTTP
1677
- if( /^(:?\w+:)/.test( url ) ){
2121
+ if( path.isExternal( url ) ){
1678
2122
  return;
1679
2123
  }
1680
2124
 
1681
2125
  //if it's a relative href, prefix href with base url
1682
- if( url.indexOf('/') && url.indexOf('#') !== 0 ){
1683
- url = path.get() + url;
2126
+ if( path.isRelative( url ) ){
2127
+ url = path.makeAbsolute( url );
1684
2128
  }
1685
2129
 
1686
2130
  $.mobile.changePage({
@@ -1698,50 +2142,63 @@ $.each({
1698
2142
 
1699
2143
  //click routing - direct to HTTP or Ajax, accordingly
1700
2144
  $( "a" ).live( "click", function(event) {
1701
-
1702
- if( !$.mobile.ajaxLinksEnabled ){ return; }
2145
+
1703
2146
  var $this = $(this),
1704
2147
  //get href, remove same-domain protocol and host
1705
- href = $this.attr( "href" ).replace( location.protocol + "//" + location.host, ""),
1706
- //if target attr is specified, it's external, and we mimic _blank... for now
1707
- target = $this.is( "[target]" ),
1708
- //if it still starts with a protocol, it's external, or could be :mailto, etc
1709
- external = target || /^(:?\w+:)/.test( href ) || $this.is( "[rel=external]" );
2148
+ url = path.clean( $this.attr( "href" ) ),
2149
+
2150
+ //check if it's external
2151
+ isExternal = path.isExternal( url ) || $this.is( "[rel='external']" ),
2152
+
2153
+ //if target attr is specified we mimic _blank... for now
2154
+ hasTarget = $this.is( "[target]" );
2155
+
2156
+ //if there's a data-rel=back attr, go back in history
2157
+ if( $this.is( "[data-rel='back']" ) ){
2158
+ window.history.back();
2159
+ return false;
2160
+ }
1710
2161
 
1711
- if( href === '#' ){
2162
+ if( url === "#" ){
1712
2163
  //for links created purely for interaction - ignore
1713
2164
  return false;
1714
2165
  }
1715
2166
 
1716
2167
  $activeClickedLink = $this.closest( ".ui-btn" ).addClass( $.mobile.activeBtnClass );
1717
2168
 
1718
- if( external || !$.mobile.ajaxLinksEnabled ){
1719
- //remove active link class if external
2169
+ if( isExternal || hasTarget || !$.mobile.ajaxEnabled ||
2170
+ // TODO: deprecated - remove at 1.0
2171
+ !$.mobile.ajaxLinksEnabled ){
2172
+ //remove active link class if external (then it won't be there if you come back)
1720
2173
  removeActiveLinkClass(true);
1721
2174
 
1722
2175
  //deliberately redirect, in case click was triggered
1723
- if( target ){
1724
- window.open(href);
2176
+ if( hasTarget ){
2177
+ window.open( url );
1725
2178
  }
1726
2179
  else{
1727
- location.href = href;
2180
+ location.href = url;
1728
2181
  }
1729
2182
  }
1730
2183
  else {
1731
2184
  //use ajax
1732
2185
  var transition = $this.data( "transition" ),
1733
- back = $this.data( "back" );
1734
-
2186
+ direction = $this.data("direction"),
2187
+ reverse = direction && direction == "reverse" ||
2188
+ // deprecated - remove by 1.0
2189
+ $this.data( "back" );
2190
+
2191
+ //this may need to be more specific as we use data-rel more
1735
2192
  nextPageRole = $this.attr( "data-rel" );
1736
2193
 
1737
2194
  //if it's a relative href, prefix href with base url
1738
- if( href.indexOf('/') && href.indexOf('#') !== 0 ){
1739
- href = path.get() + href;
2195
+ if( path.isRelative( url ) ){
2196
+ url = path.makeAbsolute( url );
1740
2197
  }
1741
2198
 
1742
- href.replace(/^#/,'');
2199
+ url = path.stripHash( url );
1743
2200
 
1744
- $.mobile.changePage(href, transition, back);
2201
+ $.mobile.changePage( url, transition, reverse);
1745
2202
  }
1746
2203
  event.preventDefault();
1747
2204
  });
@@ -1750,29 +2207,35 @@ $.each({
1750
2207
 
1751
2208
  //hashchange event handler
1752
2209
  $window.bind( "hashchange", function(e, triggered) {
1753
- if( !hashListener ){
1754
- hashListener = true;
2210
+ if( !triggered && ( !urlHistory.listeningEnabled || !$.mobile.ajaxEnabled ||
2211
+ // TODO: deprecated - remove at 1.0
2212
+ // only links need to be checked here, as forms don't trigger a hashchange event (they just silently update the hash)
2213
+ !$.mobile.ajaxLinksEnabled ) ){
1755
2214
  return;
1756
2215
  }
2216
+
2217
+ var to = path.stripHash( location.hash ),
2218
+ transition = triggered ? false : undefined;
1757
2219
 
1758
- if( $(".ui-page-active").is("[data-role=" + $.mobile.nonHistorySelectors + "]") ){
2220
+ //make sure that hash changes that produce a dialog url do nothing
2221
+ if( urlHistory.stack.length > 1 &&
2222
+ to.indexOf( dialogHashKey ) > -1 &&
2223
+ !$.mobile.activePage.is( ".ui-dialog" ) ){
1759
2224
  return;
1760
- }
1761
-
1762
- var to = location.hash,
1763
- transition = triggered ? false : undefined;
2225
+ }
1764
2226
 
1765
2227
  //if to is defined, use it
1766
2228
  if ( to ){
1767
- $.mobile.changePage( to, transition, undefined, false);
2229
+ $.mobile.changePage( to, transition, undefined, false, true );
1768
2230
  }
1769
2231
  //there's no hash, the active page is not the start page, and it's not manually triggered hashchange
1770
2232
  //we probably backed out to the first page visited
1771
2233
  else if( $.mobile.activePage.length && $.mobile.startPage[0] !== $.mobile.activePage[0] && !triggered ) {
1772
- $.mobile.changePage( $.mobile.startPage, transition, true, false );
2234
+ $.mobile.changePage( $.mobile.startPage, transition, true, false, true );
1773
2235
  }
1774
2236
  //probably the first page - show it
1775
2237
  else{
2238
+ urlHistory.addNew( "" );
1776
2239
  $.mobile.startPage.trigger("pagebeforeshow", {prevPage: $('')});
1777
2240
  $.mobile.startPage.addClass( $.mobile.activePageClass );
1778
2241
  $.mobile.pageLoading( true );
@@ -1784,451 +2247,378 @@ $.each({
1784
2247
  });
1785
2248
  })( jQuery );
1786
2249
 
2250
+
1787
2251
  /*
1788
- * jQuery Mobile Framework : "page" plugin
2252
+ * jQuery Mobile Framework : plugin for making button-like links
1789
2253
  * Copyright (c) jQuery Project
1790
2254
  * Dual licensed under the MIT or GPL Version 2 licenses.
1791
2255
  * http://jquery.org/license
1792
2256
  */
1793
2257
  (function($, undefined ) {
1794
2258
 
1795
- $.widget( "mobile.page", $.mobile.widget, {
1796
- options: {
1797
- backBtnText: "Back",
1798
- addBackBtn: true,
1799
- degradeInputs: {
1800
- color: false,
1801
- date: false,
1802
- datetime: false,
1803
- "datetime-local": false,
1804
- email: false,
1805
- month: false,
1806
- number: false,
1807
- range: "number",
1808
- search: true,
1809
- tel: false,
1810
- time: false,
1811
- url: false,
1812
- week: false
1813
- },
1814
- keepNative: null
1815
- },
1816
-
1817
- _create: function() {
1818
- var $elem = this.element,
1819
- o = this.options;
2259
+ $.fn.buttonMarkup = function( options ){
2260
+ return this.each( function() {
2261
+ var el = $( this ),
2262
+ o = $.extend( {}, $.fn.buttonMarkup.defaults, el.data(), options),
1820
2263
 
1821
- this.keepNative = "[data-role='none'], [data-role='nojs']" + (o.keepNative ? ", " + o.keepNative : "");
2264
+ // Classes Defined
2265
+ buttonClass,
2266
+ innerClass = "ui-btn-inner",
2267
+ iconClass;
1822
2268
 
1823
- if ( this._trigger( "beforeCreate" ) === false ) {
1824
- return;
2269
+ if ( attachEvents ) {
2270
+ attachEvents();
1825
2271
  }
1826
2272
 
1827
- //some of the form elements currently rely on the presence of ui-page and ui-content
1828
- // classes so we'll handle page and content roles outside of the main role processing
1829
- // loop below.
1830
- $elem.find( "[data-role='page'], [data-role='content']" ).andSelf().each(function() {
1831
- $(this).addClass( "ui-" + $(this).data( "role" ) );
1832
- });
2273
+ // if not, try to find closest theme container
2274
+ if ( !o.theme ) {
2275
+ var themedParent = el.closest("[class*='ui-bar-'],[class*='ui-body-']");
2276
+ o.theme = themedParent.length ?
2277
+ /ui-(bar|body)-([a-z])/.exec( themedParent.attr("class") )[2] :
2278
+ "c";
2279
+ }
1833
2280
 
1834
- $elem.find( "[data-role='nojs']" ).addClass( "ui-nojs" );
2281
+ buttonClass = "ui-btn ui-btn-up-" + o.theme;
1835
2282
 
1836
- // pre-find data els
1837
- var $dataEls = $elem.find( "[data-role]" ).andSelf().each(function() {
1838
- var $this = $( this ),
1839
- role = $this.data( "role" ),
1840
- theme = $this.data( "theme" );
2283
+ if ( o.inline ) {
2284
+ buttonClass += " ui-btn-inline";
2285
+ }
1841
2286
 
1842
- //apply theming and markup modifications to page,header,content,footer
1843
- if ( role === "header" || role === "footer" ) {
1844
- $this.addClass( "ui-bar-" + (theme || $this.parent('[data-role=page]').data( "theme" ) || "a") );
2287
+ if ( o.icon ) {
2288
+ o.icon = "ui-icon-" + o.icon;
2289
+ o.iconpos = o.iconpos || "left";
1845
2290
 
1846
- // add ARIA role
1847
- $this.attr( "role", role === "header" ? "banner" : "contentinfo" );
2291
+ iconClass = "ui-icon " + o.icon;
1848
2292
 
1849
- //right,left buttons
1850
- var $headeranchors = $this.children( "a" ),
1851
- leftbtn = $headeranchors.hasClass( "ui-btn-left" ),
1852
- rightbtn = $headeranchors.hasClass( "ui-btn-right" );
2293
+ if ( o.shadow ) {
2294
+ iconClass += " ui-icon-shadow";
2295
+ }
2296
+ }
1853
2297
 
1854
- if ( !leftbtn ) {
1855
- leftbtn = $headeranchors.eq( 0 ).not( ".ui-btn-right" ).addClass( "ui-btn-left" ).length;
1856
- }
2298
+ if ( o.iconpos ) {
2299
+ buttonClass += " ui-btn-icon-" + o.iconpos;
1857
2300
 
1858
- if ( !rightbtn ) {
1859
- rightbtn = $headeranchors.eq( 1 ).addClass( "ui-btn-right" ).length;
1860
- }
2301
+ if ( o.iconpos == "notext" && !el.attr("title") ) {
2302
+ el.attr( "title", el.text() );
2303
+ }
2304
+ }
1861
2305
 
1862
- // auto-add back btn on pages beyond first view
1863
- if ( o.addBackBtn && role === "header" &&
1864
- ($.mobile.urlStack.length > 1 || $(".ui-page").length > 1) &&
1865
- !leftbtn && !$this.data( "noBackBtn" ) ) {
2306
+ if ( o.corners ) {
2307
+ buttonClass += " ui-btn-corner-all";
2308
+ innerClass += " ui-btn-corner-all";
2309
+ }
1866
2310
 
1867
- $( "<a href='#' class='ui-btn-left' data-icon='arrow-l'>"+ o.backBtnText +"</a>" )
1868
- .click(function() {
1869
- history.back();
1870
- return false;
1871
- })
1872
- .prependTo( $this );
1873
- }
2311
+ if ( o.shadow ) {
2312
+ buttonClass += " ui-shadow";
2313
+ }
1874
2314
 
1875
- //page title
1876
- $this.children( "h1, h2, h3, h4, h5, h6" )
1877
- .addClass( "ui-title" )
1878
- //regardless of h element number in src, it becomes h1 for the enhanced page
1879
- .attr({ "tabindex": "0", "role": "heading", "aria-level": "1" });
2315
+ el
2316
+ .attr( "data-theme", o.theme )
2317
+ .addClass( buttonClass );
1880
2318
 
1881
- } else if ( role === "content" ) {
1882
- if ( theme ) {
1883
- $this.addClass( "ui-body-" + theme );
1884
- }
2319
+ var wrap = ("<D class='" + innerClass + "'><D class='ui-btn-text'></D>" +
2320
+ ( o.icon ? "<span class='" + iconClass + "'></span>" : "" ) +
2321
+ "</D>").replace(/D/g, o.wrapperEls);
1885
2322
 
1886
- // add ARIA role
1887
- $this.attr( "role", "main" );
2323
+ el.wrapInner( wrap );
2324
+ });
2325
+ };
1888
2326
 
1889
- } else if ( role === "page" ) {
1890
- $this.addClass( "ui-body-" + (theme || "c") );
1891
- }
2327
+ $.fn.buttonMarkup.defaults = {
2328
+ corners: true,
2329
+ shadow: true,
2330
+ iconshadow: true,
2331
+ wrapperEls: "span"
2332
+ };
1892
2333
 
1893
- switch(role) {
1894
- case "header":
1895
- case "footer":
1896
- case "page":
1897
- case "content":
1898
- $this.addClass( "ui-" + role );
1899
- break;
1900
- case "collapsible":
1901
- case "fieldcontain":
1902
- case "navbar":
1903
- case "listview":
1904
- case "dialog":
1905
- $this[ role ]();
1906
- break;
1907
- }
1908
- });
1909
-
1910
- //enhance form controls
1911
- this._enhanceControls();
2334
+ var attachEvents = function() {
2335
+ $(".ui-btn:not(.ui-disabled)").live({
2336
+ mousedown: function() {
2337
+ var theme = $(this).attr( "data-theme" );
2338
+ $(this).removeClass( "ui-btn-up-" + theme ).addClass( "ui-btn-down-" + theme );
2339
+ },
2340
+ mouseup: function() {
2341
+ var theme = $(this).attr( "data-theme" );
2342
+ $(this).removeClass( "ui-btn-down-" + theme ).addClass( "ui-btn-up-" + theme );
2343
+ },
2344
+ "mouseover focus": function() {
2345
+ var theme = $(this).attr( "data-theme" );
2346
+ $(this).removeClass( "ui-btn-up-" + theme ).addClass( "ui-btn-hover-" + theme );
2347
+ },
2348
+ "mouseout blur": function() {
2349
+ var theme = $(this).attr( "data-theme" );
2350
+ $(this).removeClass( "ui-btn-hover-" + theme ).addClass( "ui-btn-up-" + theme );
2351
+ }
2352
+ });
1912
2353
 
1913
- //links in bars, or those with data-role become buttons
1914
- $elem.find( "[data-role='button'], .ui-bar > a, .ui-header > a, .ui-footer > a" )
1915
- .not( ".ui-btn" )
1916
- .not(this.keepNative)
1917
- .buttonMarkup();
2354
+ attachEvents = null;
2355
+ };
1918
2356
 
1919
- $elem
1920
- .find("[data-role='controlgroup']")
1921
- .controlgroup();
2357
+ })(jQuery);
1922
2358
 
1923
- //links within content areas
1924
- $elem.find( "a:not(.ui-btn):not(.ui-link-inherit)" )
1925
- .not(this.keepNative)
1926
- .addClass( "ui-link" );
1927
2359
 
1928
- //fix toolbars
1929
- $elem.fixHeaderFooter();
2360
+ /*
2361
+ * jQuery Mobile Framework : "collapsible" plugin
2362
+ * Copyright (c) jQuery Project
2363
+ * Dual licensed under the MIT or GPL Version 2 licenses.
2364
+ * http://jquery.org/license
2365
+ */
2366
+ (function($, undefined ) {
2367
+ $.widget( "mobile.collapsible", $.mobile.widget, {
2368
+ options: {
2369
+ expandCueText: ' click to expand contents',
2370
+ collapseCueText: ' click to collapse contents',
2371
+ collapsed: false,
2372
+ heading: '>:header,>legend',
2373
+ theme: null,
2374
+ iconTheme: 'd'
1930
2375
  },
2376
+ _create: function(){
1931
2377
 
1932
- _enhanceControls: function() {
1933
- var o = this.options;
1934
-
1935
- // degrade inputs to avoid poorly implemented native functionality
1936
- this.element.find( "input" ).not(this.keepNative).each(function() {
1937
- var type = this.getAttribute( "type" ),
1938
- optType = o.degradeInputs[ type ] || "text";
1939
-
1940
- if ( o.degradeInputs[ type ] ) {
1941
- $( this ).replaceWith(
1942
- $( "<div>" ).html( $(this).clone() ).html()
1943
- .replace( /type="([a-zA-Z]+)"/, "type="+ optType +" data-type='$1'" ) );
2378
+ var $el = this.element,
2379
+ o = this.options,
2380
+ collapsibleContain = $el.addClass('ui-collapsible-contain'),
2381
+ collapsibleHeading = $el.find(o.heading).eq(0),
2382
+ collapsibleContent = collapsibleContain.wrapInner('<div class="ui-collapsible-content"></div>').find('.ui-collapsible-content'),
2383
+ collapsibleParent = $el.closest('[data-role="collapsible-set"]').addClass('ui-collapsible-set');
2384
+
2385
+ //replace collapsibleHeading if it's a legend
2386
+ if(collapsibleHeading.is('legend')){
2387
+ collapsibleHeading = $('<div role="heading">'+ collapsibleHeading.html() +'</div>').insertBefore(collapsibleHeading);
2388
+ collapsibleHeading.next().remove();
2389
+ }
2390
+
2391
+ //drop heading in before content
2392
+ collapsibleHeading.insertBefore(collapsibleContent);
2393
+
2394
+ //modify markup & attributes
2395
+ collapsibleHeading.addClass('ui-collapsible-heading')
2396
+ .append('<span class="ui-collapsible-heading-status"></span>')
2397
+ .wrapInner('<a href="#" class="ui-collapsible-heading-toggle"></a>')
2398
+ .find('a:eq(0)')
2399
+ .buttonMarkup({
2400
+ shadow: !!!collapsibleParent.length,
2401
+ corners:false,
2402
+ iconPos: 'left',
2403
+ icon: 'plus',
2404
+ theme: o.theme
2405
+ })
2406
+ .find('.ui-icon')
2407
+ .removeAttr('class')
2408
+ .buttonMarkup({
2409
+ shadow: true,
2410
+ corners:true,
2411
+ iconPos: 'notext',
2412
+ icon: 'plus',
2413
+ theme: o.iconTheme
2414
+ });
2415
+
2416
+ if( !collapsibleParent.length ){
2417
+ collapsibleHeading
2418
+ .find('a:eq(0)')
2419
+ .addClass('ui-corner-all')
2420
+ .find('.ui-btn-inner')
2421
+ .addClass('ui-corner-all');
2422
+ }
2423
+ else {
2424
+ if( collapsibleContain.data('collapsible-last') ){
2425
+ collapsibleHeading
2426
+ .find('a:eq(0), .ui-btn-inner')
2427
+ .addClass('ui-corner-bottom');
2428
+ }
1944
2429
  }
2430
+
2431
+
2432
+ //events
2433
+ collapsibleContain
2434
+ .bind('collapse', function(event){
2435
+ if( !event.isDefaultPrevented() ){
2436
+ event.preventDefault();
2437
+ collapsibleHeading
2438
+ .addClass('ui-collapsible-heading-collapsed')
2439
+ .find('.ui-collapsible-heading-status').text(o.expandCueText);
2440
+
2441
+ collapsibleHeading.find('.ui-icon').removeClass('ui-icon-minus').addClass('ui-icon-plus');
2442
+ collapsibleContent.addClass('ui-collapsible-content-collapsed').attr('aria-hidden',true);
2443
+
2444
+ if( collapsibleContain.data('collapsible-last') ){
2445
+ collapsibleHeading
2446
+ .find('a:eq(0), .ui-btn-inner')
2447
+ .addClass('ui-corner-bottom');
2448
+ }
2449
+ }
2450
+
2451
+ })
2452
+ .bind('expand', function(event){
2453
+ if( !event.isDefaultPrevented() ){
2454
+ event.preventDefault();
2455
+ collapsibleHeading
2456
+ .removeClass('ui-collapsible-heading-collapsed')
2457
+ .find('.ui-collapsible-heading-status').text(o.collapseCueText);
2458
+
2459
+ collapsibleHeading.find('.ui-icon').removeClass('ui-icon-plus').addClass('ui-icon-minus');
2460
+ collapsibleContent.removeClass('ui-collapsible-content-collapsed').attr('aria-hidden',false);
2461
+
2462
+ if( collapsibleContain.data('collapsible-last') ){
2463
+ collapsibleHeading
2464
+ .find('a:eq(0), .ui-btn-inner')
2465
+ .removeClass('ui-corner-bottom');
2466
+ }
2467
+
2468
+ }
2469
+ })
2470
+ .trigger(o.collapsed ? 'collapse' : 'expand');
2471
+
2472
+
2473
+ //close others in a set
2474
+ if( collapsibleParent.length && !collapsibleParent.data("collapsiblebound") ){
2475
+ collapsibleParent
2476
+ .data("collapsiblebound", true)
2477
+ .bind("expand", function( event ){
2478
+ $(this).find( ".ui-collapsible-contain" )
2479
+ .not( $(event.target).closest( ".ui-collapsible-contain" ) )
2480
+ .not( "> .ui-collapsible-contain .ui-collapsible-contain" )
2481
+ .trigger( "collapse" );
2482
+ })
2483
+ var set = collapsibleParent.find('[data-role=collapsible]')
2484
+
2485
+ set.first()
2486
+ .find('a:eq(0)')
2487
+ .addClass('ui-corner-top')
2488
+ .find('.ui-btn-inner')
2489
+ .addClass('ui-corner-top');
2490
+
2491
+ set.last().data('collapsible-last', true)
2492
+ }
2493
+
2494
+ collapsibleHeading.bind( $.support.touch ? "touchstart" : "click", function(){
2495
+ if( collapsibleHeading.is('.ui-collapsible-heading-collapsed') ){
2496
+ collapsibleContain.trigger('expand');
2497
+ }
2498
+ else {
2499
+ collapsibleContain.trigger('collapse');
2500
+ }
2501
+ return false;
1945
2502
  });
1946
-
1947
- // enchance form controls
1948
- this.element
1949
- .find( "[type='radio'], [type='checkbox']" )
1950
- .not(this.keepNative)
1951
- .checkboxradio();
1952
-
1953
- this.element
1954
- .find( "button, [type='button'], [type='submit'], [type='reset'], [type='image']" )
1955
- .not(this.keepNative)
1956
- .button();
1957
-
1958
- this.element
1959
- .find( "input, textarea" )
1960
- .not( "[type='radio'], [type='checkbox'], button, [type='button'], [type='submit'], [type='reset'], [type='image']" )
1961
- .not(this.keepNative)
1962
- .textinput();
1963
-
1964
- this.element
1965
- .find( "input, select" )
1966
- .not(this.keepNative)
1967
- .filter( "[data-role='slider'], [data-type='range']" )
1968
- .slider();
1969
-
1970
- this.element
1971
- .find( "select:not([data-role='slider'])" )
1972
- .not(this.keepNative)
1973
- .selectmenu();
2503
+
1974
2504
  }
1975
2505
  });
1976
-
1977
2506
  })( jQuery );
1978
2507
 
1979
-
1980
2508
  /*
1981
- * jQuery UI Position @VERSION
1982
- *
1983
- * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
1984
- * Dual licensed under the MIT or GPL Version 2 licenses.
1985
- * http://jquery.org/license
1986
- *
1987
- * http://docs.jquery.com/UI/Position
1988
- */
1989
- (function( $, undefined ) {
1990
-
1991
- $.ui = $.ui || {};
1992
-
1993
- var horizontalPositions = /left|center|right/,
1994
- verticalPositions = /top|center|bottom/,
1995
- center = "center",
1996
- _position = $.fn.position,
1997
- _offset = $.fn.offset;
1998
-
1999
- $.fn.position = function( options ) {
2000
- if ( !options || !options.of ) {
2001
- return _position.apply( this, arguments );
2002
- }
2003
-
2004
- // make a copy, we don't want to modify arguments
2005
- options = $.extend( {}, options );
2006
-
2007
- var target = $( options.of ),
2008
- targetElem = target[0],
2009
- collision = ( options.collision || "flip" ).split( " " ),
2010
- offset = options.offset ? options.offset.split( " " ) : [ 0, 0 ],
2011
- targetWidth,
2012
- targetHeight,
2013
- basePosition;
2014
-
2015
- if ( targetElem.nodeType === 9 ) {
2016
- targetWidth = target.width();
2017
- targetHeight = target.height();
2018
- basePosition = { top: 0, left: 0 };
2019
- // TODO: use $.isWindow() in 1.9
2020
- } else if ( targetElem.setTimeout ) {
2021
- targetWidth = target.width();
2022
- targetHeight = target.height();
2023
- basePosition = { top: target.scrollTop(), left: target.scrollLeft() };
2024
- } else if ( targetElem.preventDefault ) {
2025
- // force left top to allow flipping
2026
- options.at = "left top";
2027
- targetWidth = targetHeight = 0;
2028
- basePosition = { top: options.of.pageY, left: options.of.pageX };
2029
- } else {
2030
- targetWidth = target.outerWidth();
2031
- targetHeight = target.outerHeight();
2032
- basePosition = target.offset();
2033
- }
2034
-
2035
- // force my and at to have valid horizontal and veritcal positions
2036
- // if a value is missing or invalid, it will be converted to center
2037
- $.each( [ "my", "at" ], function() {
2038
- var pos = ( options[this] || "" ).split( " " );
2039
- if ( pos.length === 1) {
2040
- pos = horizontalPositions.test( pos[0] ) ?
2041
- pos.concat( [center] ) :
2042
- verticalPositions.test( pos[0] ) ?
2043
- [ center ].concat( pos ) :
2044
- [ center, center ];
2045
- }
2046
- pos[ 0 ] = horizontalPositions.test( pos[0] ) ? pos[ 0 ] : center;
2047
- pos[ 1 ] = verticalPositions.test( pos[1] ) ? pos[ 1 ] : center;
2048
- options[ this ] = pos;
2049
- });
2050
-
2051
- // normalize collision option
2052
- if ( collision.length === 1 ) {
2053
- collision[ 1 ] = collision[ 0 ];
2054
- }
2055
-
2056
- // normalize offset option
2057
- offset[ 0 ] = parseInt( offset[0], 10 ) || 0;
2058
- if ( offset.length === 1 ) {
2059
- offset[ 1 ] = offset[ 0 ];
2060
- }
2061
- offset[ 1 ] = parseInt( offset[1], 10 ) || 0;
2062
-
2063
- if ( options.at[0] === "right" ) {
2064
- basePosition.left += targetWidth;
2065
- } else if (options.at[0] === center ) {
2066
- basePosition.left += targetWidth / 2;
2067
- }
2068
-
2069
- if ( options.at[1] === "bottom" ) {
2070
- basePosition.top += targetHeight;
2071
- } else if ( options.at[1] === center ) {
2072
- basePosition.top += targetHeight / 2;
2073
- }
2074
-
2075
- basePosition.left += offset[ 0 ];
2076
- basePosition.top += offset[ 1 ];
2077
-
2078
- return this.each(function() {
2079
- var elem = $( this ),
2080
- elemWidth = elem.outerWidth(),
2081
- elemHeight = elem.outerHeight(),
2082
- marginLeft = parseInt( $.curCSS( this, "marginLeft", true ) ) || 0,
2083
- marginTop = parseInt( $.curCSS( this, "marginTop", true ) ) || 0,
2084
- collisionWidth = elemWidth + marginLeft +
2085
- parseInt( $.curCSS( this, "marginRight", true ) ) || 0,
2086
- collisionHeight = elemHeight + marginTop +
2087
- parseInt( $.curCSS( this, "marginBottom", true ) ) || 0,
2088
- position = $.extend( {}, basePosition ),
2089
- collisionPosition;
2090
-
2091
- if ( options.my[0] === "right" ) {
2092
- position.left -= elemWidth;
2093
- } else if ( options.my[0] === center ) {
2094
- position.left -= elemWidth / 2;
2095
- }
2096
-
2097
- if ( options.my[1] === "bottom" ) {
2098
- position.top -= elemHeight;
2099
- } else if ( options.my[1] === center ) {
2100
- position.top -= elemHeight / 2;
2101
- }
2102
-
2103
- // prevent fractions (see #5280)
2104
- position.left = parseInt( position.left );
2105
- position.top = parseInt( position.top );
2106
-
2107
- collisionPosition = {
2108
- left: position.left - marginLeft,
2109
- top: position.top - marginTop
2110
- };
2111
-
2112
- $.each( [ "left", "top" ], function( i, dir ) {
2113
- if ( $.ui.position[ collision[i] ] ) {
2114
- $.ui.position[ collision[i] ][ dir ]( position, {
2115
- targetWidth: targetWidth,
2116
- targetHeight: targetHeight,
2117
- elemWidth: elemWidth,
2118
- elemHeight: elemHeight,
2119
- collisionPosition: collisionPosition,
2120
- collisionWidth: collisionWidth,
2121
- collisionHeight: collisionHeight,
2122
- offset: offset,
2123
- my: options.my,
2124
- at: options.at
2125
- });
2126
- }
2127
- });
2128
-
2129
- if ( $.fn.bgiframe ) {
2130
- elem.bgiframe();
2509
+ * jQuery Mobile Framework: "controlgroup" plugin - corner-rounding for groups of buttons, checks, radios, etc
2510
+ * Copyright (c) jQuery Project
2511
+ * Dual licensed under the MIT or GPL Version 2 licenses.
2512
+ * http://jquery.org/license
2513
+ */
2514
+ (function($, undefined ) {
2515
+ $.fn.controlgroup = function(options){
2516
+
2517
+ return this.each(function(){
2518
+ var o = $.extend({
2519
+ direction: $( this ).data( "type" ) || "vertical",
2520
+ shadow: false
2521
+ },options);
2522
+ var groupheading = $(this).find('>legend'),
2523
+ flCorners = o.direction == 'horizontal' ? ['ui-corner-left', 'ui-corner-right'] : ['ui-corner-top', 'ui-corner-bottom'],
2524
+ type = $(this).find('input:eq(0)').attr('type');
2525
+
2526
+ //replace legend with more stylable replacement div
2527
+ if( groupheading.length ){
2528
+ $(this).wrapInner('<div class="ui-controlgroup-controls"></div>');
2529
+ $('<div role="heading" class="ui-controlgroup-label">'+ groupheading.html() +'</div>').insertBefore( $(this).children(0) );
2530
+ groupheading.remove();
2131
2531
  }
2132
- elem.offset( $.extend( position, { using: options.using } ) );
2133
- });
2134
- };
2135
2532
 
2136
- $.ui.position = {
2137
- fit: {
2138
- left: function( position, data ) {
2139
- var win = $( window ),
2140
- over = data.collisionPosition.left + data.collisionWidth - win.width() - win.scrollLeft();
2141
- position.left = over > 0 ? position.left - over : Math.max( position.left - data.collisionPosition.left, position.left );
2142
- },
2143
- top: function( position, data ) {
2144
- var win = $( window ),
2145
- over = data.collisionPosition.top + data.collisionHeight - win.height() - win.scrollTop();
2146
- position.top = over > 0 ? position.top - over : Math.max( position.top - data.collisionPosition.top, position.top );
2533
+ $(this).addClass('ui-corner-all ui-controlgroup ui-controlgroup-'+o.direction);
2534
+
2535
+ function flipClasses(els){
2536
+ els
2537
+ .removeClass('ui-btn-corner-all ui-shadow')
2538
+ .eq(0).addClass(flCorners[0])
2539
+ .end()
2540
+ .filter(':last').addClass(flCorners[1]).addClass('ui-controlgroup-last');
2147
2541
  }
2148
- },
2149
-
2150
- flip: {
2151
- left: function( position, data ) {
2152
- if ( data.at[0] === center ) {
2153
- return;
2154
- }
2155
- var win = $( window ),
2156
- over = data.collisionPosition.left + data.collisionWidth - win.width() - win.scrollLeft(),
2157
- myOffset = data.my[ 0 ] === "left" ?
2158
- -data.elemWidth :
2159
- data.my[ 0 ] === "right" ?
2160
- data.elemWidth :
2161
- 0,
2162
- atOffset = data.at[ 0 ] === "left" ?
2163
- data.targetWidth :
2164
- -data.targetWidth,
2165
- offset = -2 * data.offset[ 0 ];
2166
- position.left += data.collisionPosition.left < 0 ?
2167
- myOffset + atOffset + offset :
2168
- over > 0 ?
2169
- myOffset + atOffset + offset :
2170
- 0;
2171
- },
2172
- top: function( position, data ) {
2173
- if ( data.at[1] === center ) {
2174
- return;
2175
- }
2176
- var win = $( window ),
2177
- over = data.collisionPosition.top + data.collisionHeight - win.height() - win.scrollTop(),
2178
- myOffset = data.my[ 1 ] === "top" ?
2179
- -data.elemHeight :
2180
- data.my[ 1 ] === "bottom" ?
2181
- data.elemHeight :
2182
- 0,
2183
- atOffset = data.at[ 1 ] === "top" ?
2184
- data.targetHeight :
2185
- -data.targetHeight,
2186
- offset = -2 * data.offset[ 1 ];
2187
- position.top += data.collisionPosition.top < 0 ?
2188
- myOffset + atOffset + offset :
2189
- over > 0 ?
2190
- myOffset + atOffset + offset :
2191
- 0;
2542
+ flipClasses($(this).find('.ui-btn'));
2543
+ flipClasses($(this).find('.ui-btn-inner'));
2544
+ if(o.shadow){
2545
+ $(this).addClass('ui-shadow');
2192
2546
  }
2193
- }
2547
+ });
2194
2548
  };
2549
+ })(jQuery);
2195
2550
 
2196
- // offset setter from jQuery 1.4
2197
- if ( !$.offset.setOffset ) {
2198
- $.offset.setOffset = function( elem, options ) {
2199
- // set position first, in-case top/left are set even on static elem
2200
- if ( /static/.test( $.curCSS( elem, "position" ) ) ) {
2201
- elem.style.position = "relative";
2202
- }
2203
- var curElem = $( elem ),
2204
- curOffset = curElem.offset(),
2205
- curTop = parseInt( $.curCSS( elem, "top", true ), 10 ) || 0,
2206
- curLeft = parseInt( $.curCSS( elem, "left", true ), 10) || 0,
2207
- props = {
2208
- top: (options.top - curOffset.top) + curTop,
2209
- left: (options.left - curOffset.left) + curLeft
2210
- };
2551
+ /*
2552
+ * jQuery Mobile Framework : "dialog" plugin.
2553
+ * Copyright (c) jQuery Project
2554
+ * Dual licensed under the MIT (MIT-LICENSE.txt) and GPL (GPL-LICENSE.txt) licenses.
2555
+ * Note: Code is in draft form and is subject to change
2556
+ */
2557
+ (function($, undefined ) {
2558
+ $.widget( "mobile.dialog", $.mobile.widget, {
2559
+ options: {},
2560
+ _create: function(){
2561
+ var self = this,
2562
+ $el = self.element;
2211
2563
 
2212
- if ( 'using' in options ) {
2213
- options.using.call( elem, props );
2214
- } else {
2215
- curElem.css( props );
2216
- }
2217
- };
2218
-
2219
- $.fn.offset = function( options ) {
2220
- var elem = this[ 0 ];
2221
- if ( !elem || !elem.ownerDocument ) { return null; }
2222
- if ( options ) {
2223
- return this.each(function() {
2224
- $.offset.setOffset( this, options );
2564
+ /* class the markup for dialog styling */
2565
+ this.element
2566
+ //add ARIA role
2567
+ .attr("role","dialog")
2568
+ .addClass('ui-page ui-dialog ui-body-a')
2569
+ .find('[data-role=header]')
2570
+ .addClass('ui-corner-top ui-overlay-shadow')
2571
+ .prepend( '<a href="#" data-icon="delete" data-rel="back" data-iconpos="notext">Close</a>' )
2572
+ .end()
2573
+ .find('.ui-content:not([class*="ui-body-"])')
2574
+ .addClass('ui-body-c')
2575
+ .end()
2576
+ .find('.ui-content,[data-role=footer]')
2577
+ .last()
2578
+ .addClass('ui-corner-bottom ui-overlay-shadow');
2579
+
2580
+ /* bind events
2581
+ - clicks and submits should use the closing transition that the dialog opened with
2582
+ unless a data-transition is specified on the link/form
2583
+ - if the click was on the close button, or the link has a data-rel="back" it'll go back in history naturally
2584
+ */
2585
+ this.element
2586
+ .bind( "click submit", function(e){
2587
+ var $targetel;
2588
+ if( e.type == "click" ){
2589
+ $targetel = $(e.target).closest("a");
2590
+ }
2591
+ else{
2592
+ $targetel = $(e.target).closest("form");
2593
+ }
2594
+
2595
+ if( $targetel.length && !$targetel.data("transition") ){
2596
+ $targetel
2597
+ .attr("data-transition", $.mobile.urlHistory.getActive().transition )
2598
+ .attr("data-direction", "reverse");
2599
+ }
2225
2600
  });
2226
- }
2227
- return _offset.call( this );
2228
- };
2229
- }
2230
2601
 
2231
- }( jQuery ));
2602
+ },
2603
+
2604
+ //close method goes back in history
2605
+ close: function(){
2606
+ window.history.back();
2607
+ }
2608
+ });
2609
+ })( jQuery );
2610
+
2611
+ /*
2612
+ * jQuery Mobile Framework : "fieldcontain" plugin - simple class additions to make form row separators
2613
+ * Copyright (c) jQuery Project
2614
+ * Dual licensed under the MIT or GPL Version 2 licenses.
2615
+ * http://jquery.org/license
2616
+ */
2617
+ (function($, undefined ) {
2618
+ $.fn.fieldcontain = function(options){
2619
+ return this.addClass('ui-field-contain ui-body ui-br');
2620
+ };
2621
+ })(jQuery);
2232
2622
 
2233
2623
  /*
2234
2624
  * jQuery Mobile Framework : "fixHeaderFooter" plugin - on-demand positioning for headers,footers
@@ -2238,18 +2628,23 @@ if ( !$.offset.setOffset ) {
2238
2628
  */
2239
2629
  (function($, undefined ) {
2240
2630
  $.fn.fixHeaderFooter = function(options){
2241
- if( !$.support.scrollTop ){ return $(this); }
2242
- return $(this).each(function(){
2243
- if( $(this).data('fullscreen') ){ $(this).addClass('ui-page-fullscreen'); }
2244
- $(this).find('.ui-header[data-position="fixed"]').addClass('ui-header-fixed ui-fixed-inline fade'); //should be slidedown
2245
- $(this).find('.ui-footer[data-position="fixed"]').addClass('ui-footer-fixed ui-fixed-inline fade'); //should be slideup
2631
+ if( !$.support.scrollTop ){ return this; }
2632
+
2633
+ return this.each(function(){
2634
+ var $this = $(this);
2635
+
2636
+ if( $this.data('fullscreen') ){ $this.addClass('ui-page-fullscreen'); }
2637
+ $this.find('.ui-header[data-position="fixed"]').addClass('ui-header-fixed ui-fixed-inline fade'); //should be slidedown
2638
+ $this.find('.ui-footer[data-position="fixed"]').addClass('ui-footer-fixed ui-fixed-inline fade'); //should be slideup
2246
2639
  });
2247
- };
2640
+ };
2248
2641
 
2249
2642
  //single controller for all showing,hiding,toggling
2250
2643
  $.fixedToolbars = (function(){
2251
2644
  if( !$.support.scrollTop ){ return; }
2252
2645
  var currentstate = 'inline',
2646
+ autoHideMode = false,
2647
+ showDelay = 100,
2253
2648
  delayTimer,
2254
2649
  ignoreTargets = 'a,input,textarea,select,button,label,.ui-header-fixed,.ui-footer-fixed',
2255
2650
  toolbarSelector = '.ui-header-fixed:first, .ui-footer-fixed:not(.ui-footer-duplicate):last',
@@ -2261,6 +2656,24 @@ $.fixedToolbars = (function(){
2261
2656
  scrollTriggered = false,
2262
2657
  touchToggleEnabled = true;
2263
2658
 
2659
+ function showEventCallback(event)
2660
+ {
2661
+ // An event that affects the dimensions of the visual viewport has
2662
+ // been triggered. If the header and/or footer for the current page are in overlay
2663
+ // mode, we want to hide them, and then fire off a timer to show them at a later
2664
+ // point. Events like a resize can be triggered continuously during a scroll, on
2665
+ // some platforms, so the timer is used to delay the actual positioning until the
2666
+ // flood of events have subsided.
2667
+ //
2668
+ // If we are in autoHideMode, we don't do anything because we know the scroll
2669
+ // callbacks for the plugin will fire off a show when the scrolling has stopped.
2670
+ if (!autoHideMode && currentstate == 'overlay') {
2671
+ if (!delayTimer)
2672
+ $.fixedToolbars.hide(true);
2673
+ $.fixedToolbars.startShowTimer();
2674
+ }
2675
+ }
2676
+
2264
2677
  $(function() {
2265
2678
  $(document)
2266
2679
  .bind(touchStartEvent,function(event){
@@ -2269,14 +2682,6 @@ $.fixedToolbars = (function(){
2269
2682
  stateBefore = currentstate;
2270
2683
  }
2271
2684
  })
2272
- .bind('scrollstart',function(event){
2273
- if( $(event.target).closest(ignoreTargets).length ){ return; } //because it could be a touchmove...
2274
- scrollTriggered = true;
2275
- if(stateBefore == null){ stateBefore = currentstate; }
2276
- if (stateBefore == 'overlay') {
2277
- $.fixedToolbars.hide(true);
2278
- }
2279
- })
2280
2685
  .bind(touchStopEvent,function(event){
2281
2686
  if( touchToggleEnabled ) {
2282
2687
  if( $(event.target).closest(ignoreTargets).length ){ return; }
@@ -2286,21 +2691,44 @@ $.fixedToolbars = (function(){
2286
2691
  }
2287
2692
  }
2288
2693
  })
2694
+ .bind('scrollstart',function(event){
2695
+ if( $(event.target).closest(ignoreTargets).length ){ return; } //because it could be a touchmove...
2696
+ scrollTriggered = true;
2697
+ if(stateBefore == null){ stateBefore = currentstate; }
2698
+
2699
+ // We only enter autoHideMode if the headers/footers are in
2700
+ // an overlay state or the show timer was started. If the
2701
+ // show timer is set, clear it so the headers/footers don't
2702
+ // show up until after we're done scrolling.
2703
+ var isOverlayState = stateBefore == 'overlay';
2704
+ autoHideMode = isOverlayState || !!delayTimer;
2705
+ if (autoHideMode){
2706
+ $.fixedToolbars.clearShowTimer();
2707
+ if (isOverlayState) {
2708
+ $.fixedToolbars.hide(true);
2709
+ }
2710
+ }
2711
+ })
2289
2712
  .bind('scrollstop',function(event){
2290
2713
  if( $(event.target).closest(ignoreTargets).length ){ return; }
2291
2714
  scrollTriggered = false;
2292
- if (stateBefore == 'overlay') {
2293
- $.fixedToolbars.show();
2715
+ if (autoHideMode) {
2716
+ autoHideMode = false;
2717
+ $.fixedToolbars.startShowTimer();
2294
2718
  }
2295
2719
  stateBefore = null;
2296
- });
2720
+ })
2721
+ .bind('silentscroll', showEventCallback);
2722
+
2723
+ $(window).bind('resize', showEventCallback);
2297
2724
  });
2298
2725
 
2299
2726
  //before page is shown, check for duplicate footer
2300
2727
  $('.ui-page').live('pagebeforeshow', function(event, ui){
2301
- var page = $(event.target);
2302
- var footer = page.find('[data-role="footer"]:not(.ui-sticky-footer)');
2303
- var id = footer.data('id');
2728
+ var page = $(event.target),
2729
+ footer = page.find('[data-role="footer"]:not(.ui-sticky-footer)'),
2730
+ id = footer.data('id');
2731
+ stickyFooter = null;
2304
2732
  if (id)
2305
2733
  {
2306
2734
  stickyFooter = $('.ui-footer[data-id="' + id + '"].ui-sticky-footer');
@@ -2380,6 +2808,7 @@ $.fixedToolbars = (function(){
2380
2808
  //exposed methods
2381
2809
  return {
2382
2810
  show: function(immediately, page){
2811
+ $.fixedToolbars.clearShowTimer();
2383
2812
  currentstate = 'overlay';
2384
2813
  var $ap = page ? $(page) : ($.mobile.activePage ? $.mobile.activePage : $(".ui-page-active"));
2385
2814
  return $ap.children( toolbarSelector ).each(function(){
@@ -2428,23 +2857,98 @@ $.fixedToolbars = (function(){
2428
2857
  }
2429
2858
  }
2430
2859
  });
2431
- },
2432
- hideAfterDelay: function(){
2433
- delayTimer = setTimeout(function(){
2434
- $.fixedToolbars.hide();
2435
- }, 3000);
2436
- },
2437
- toggle: function(from){
2438
- if(from){ currentstate = from; }
2439
- return (currentstate == 'overlay') ? $.fixedToolbars.hide() : $.fixedToolbars.show();
2440
- },
2441
- setTouchToggleEnabled: function(enabled) {
2442
- touchToggleEnabled = enabled;
2443
- }
2444
- };
2445
- })();
2860
+ },
2861
+ startShowTimer: function(){
2862
+ $.fixedToolbars.clearShowTimer();
2863
+ var args = $.makeArray(arguments);
2864
+ delayTimer = setTimeout(function(){
2865
+ delayTimer = undefined;
2866
+ $.fixedToolbars.show.apply(null, args);
2867
+ }, showDelay);
2868
+ },
2869
+ clearShowTimer: function() {
2870
+ if (delayTimer) {
2871
+ clearTimeout(delayTimer);
2872
+ }
2873
+ delayTimer = undefined;
2874
+ },
2875
+ toggle: function(from){
2876
+ if(from){ currentstate = from; }
2877
+ return (currentstate == 'overlay') ? $.fixedToolbars.hide() : $.fixedToolbars.show();
2878
+ },
2879
+ setTouchToggleEnabled: function(enabled) {
2880
+ touchToggleEnabled = enabled;
2881
+ }
2882
+ };
2883
+ })();
2884
+
2885
+ })(jQuery);
2886
+
2887
+ /*
2888
+ * jQuery Mobile Framework : "button" plugin - links that proxy to native input/buttons
2889
+ * Copyright (c) jQuery Project
2890
+ * Dual licensed under the MIT or GPL Version 2 licenses.
2891
+ * http://jquery.org/license
2892
+ */
2893
+ (function($, undefined ) {
2894
+ $.widget( "mobile.button", $.mobile.widget, {
2895
+ options: {
2896
+ theme: null,
2897
+ icon: null,
2898
+ iconpos: null,
2899
+ inline: null,
2900
+ corners: true,
2901
+ shadow: true,
2902
+ iconshadow: true
2903
+ },
2904
+ _create: function(){
2905
+ var $el = this.element,
2906
+ o = this.options;
2907
+
2908
+ //add ARIA role
2909
+ this.button = $( "<div></div>" )
2910
+ .text( $el.text() || $el.val() )
2911
+ .buttonMarkup({
2912
+ theme: o.theme,
2913
+ icon: o.icon,
2914
+ iconpos: o.iconpos,
2915
+ inline: o.inline,
2916
+ corners: o.corners,
2917
+ shadow: o.shadow,
2918
+ iconshadow: o.iconshadow
2919
+ })
2920
+ .insertBefore( $el )
2921
+ .append( $el.addClass('ui-btn-hidden') );
2922
+
2923
+ //add hidden input during submit
2924
+ if( $el.attr('type') !== 'reset' ){
2925
+ $el.click(function(){
2926
+ var $buttonPlaceholder = $("<input>",
2927
+ {type: "hidden", name: $el.attr("name"), value: $el.attr("value")})
2928
+ .insertBefore($el);
2929
+
2930
+ //bind to doc to remove after submit handling
2931
+ $(document).submit(function(){
2932
+ $buttonPlaceholder.remove();
2933
+ });
2934
+ });
2935
+ }
2936
+
2937
+ },
2446
2938
 
2447
- })(jQuery);
2939
+ enable: function(){
2940
+ this.element.attr("disabled", false);
2941
+ this.button.removeClass("ui-disabled").attr("aria-disabled", false);
2942
+ return this._setOption("disabled", false);
2943
+ },
2944
+
2945
+ disable: function(){
2946
+ this.element.attr("disabled", true);
2947
+ this.button.addClass("ui-disabled").attr("aria-disabled", true);
2948
+ return this._setOption("disabled", true);
2949
+ }
2950
+ });
2951
+ })( jQuery );
2448
2952
 
2449
2953
  /*
2450
2954
  * jQuery Mobile Framework : "checkboxradio" plugin
@@ -2458,8 +2962,9 @@ $.widget( "mobile.checkboxradio", $.mobile.widget, {
2458
2962
  theme: null
2459
2963
  },
2460
2964
  _create: function(){
2461
- var input = this.element,
2462
- label = $("label[for='" + input.attr( "id" ) + "']"),
2965
+ var self = this,
2966
+ input = this.element,
2967
+ label = input.closest("form,fieldset,[data-role='page']").find("label[for='" + input.attr( "id" ) + "']"),
2463
2968
  inputtype = input.attr( "type" ),
2464
2969
  checkedicon = "ui-icon-" + inputtype + "-on",
2465
2970
  uncheckedicon = "ui-icon-" + inputtype + "-off";
@@ -2488,25 +2993,25 @@ $.widget( "mobile.checkboxradio", $.mobile.widget, {
2488
2993
  if( $(this).parent().is('.ui-disabled') ){ return false; }
2489
2994
  },
2490
2995
 
2491
- mousedown: function() {
2492
- if( $(this).parent().is('.ui-disabled') ){ return false; }
2493
- label.data( "state", input.attr( "checked" ) );
2996
+ "tap": function( event ){
2997
+ self._cacheVals();
2998
+ input.attr( "checked", inputtype === "radio" && true || !input.is( ":checked" ) );
2999
+ self._updateAll();
3000
+ event.preventDefault();
2494
3001
  },
2495
3002
 
2496
- click: function() {
2497
- setTimeout(function() {
2498
- if ( input.attr( "checked" ) === label.data( "state" ) ) {
2499
- input.trigger( "click" );
2500
- }
2501
- }, 1);
2502
- }
3003
+ click: false
3004
+
2503
3005
  });
2504
3006
 
2505
3007
  input
2506
3008
  .bind({
2507
-
2508
- click: function() {
2509
- $( "input[name='" + input.attr( "name" ) + "'][type='" + inputtype + "']" ).checkboxradio( "refresh" );
3009
+ mousedown: function(){
3010
+ this._cacheVals();
3011
+ },
3012
+
3013
+ click: function(){
3014
+ self._updateAll();
2510
3015
  },
2511
3016
 
2512
3017
  focus: function() {
@@ -2522,9 +3027,31 @@ $.widget( "mobile.checkboxradio", $.mobile.widget, {
2522
3027
 
2523
3028
  },
2524
3029
 
3030
+ _cacheVals: function(){
3031
+ this._getInputSet().each(function(){
3032
+ $(this).data("cacheVal", $(this).is(":checked") );
3033
+ });
3034
+ },
3035
+
3036
+ //returns either a set of radios with the same name attribute, or a single checkbox
3037
+ _getInputSet: function(){
3038
+ return this.element.closest( "form,fieldset,[data-role='page']" )
3039
+ .find( "input[name='"+ this.element.attr( "name" ) +"'][type='"+ this.element.attr( "type" ) +"']" );
3040
+ },
3041
+
3042
+ _updateAll: function(){
3043
+ this._getInputSet().each(function(){
3044
+ var dVal = $(this).data("cacheVal");
3045
+ if( dVal && dVal !== $(this).is(":checked") || $(this).is( "[type='checkbox']" ) ){
3046
+ $(this).trigger("change");
3047
+ }
3048
+ })
3049
+ .checkboxradio( "refresh" );
3050
+ },
3051
+
2525
3052
  refresh: function( ){
2526
3053
  var input = this.element,
2527
- label = $("label[for='" + input.attr( "id" ) + "']"),
3054
+ label = input.closest("form,fieldset,[data-role='page']").find("label[for='" + input.attr( "id" ) + "']"),
2528
3055
  inputtype = input.attr( "type" ),
2529
3056
  icon = label.find( ".ui-icon" ),
2530
3057
  checkedicon = "ui-icon-" + inputtype + "-on",
@@ -2560,116 +3087,17 @@ $.widget( "mobile.checkboxradio", $.mobile.widget, {
2560
3087
  })( jQuery );
2561
3088
 
2562
3089
 
2563
- /*
2564
- * jQuery Mobile Framework : "textinput" plugin for text inputs, textareas
2565
- * Copyright (c) jQuery Project
2566
- * Dual licensed under the MIT or GPL Version 2 licenses.
2567
- * http://jquery.org/license
2568
- */
2569
- (function($, undefined ) {
2570
- $.widget( "mobile.textinput", $.mobile.widget, {
2571
- options: {
2572
- theme: null
2573
- },
2574
- _create: function(){
2575
- var input = this.element,
2576
- o = this.options,
2577
- theme = o.theme,
2578
- themeclass;
2579
-
2580
- if ( !theme ) {
2581
- var themedParent = this.element.closest("[class*='ui-bar-'],[class*='ui-body-']");
2582
- theme = themedParent.length ?
2583
- /ui-(bar|body)-([a-z])/.exec( themedParent.attr("class") )[2] :
2584
- "c";
2585
- }
2586
-
2587
- themeclass = " ui-body-" + theme;
2588
-
2589
- $('label[for='+input.attr('id')+']').addClass('ui-input-text');
2590
-
2591
- input.addClass('ui-input-text ui-body-'+ o.theme);
2592
-
2593
- var focusedEl = input;
2594
-
2595
- //"search" input widget
2596
- if( input.is('[type="search"],[data-type="search"]') ){
2597
- focusedEl = input.wrap('<div class="ui-input-search ui-shadow-inset ui-btn-corner-all ui-btn-shadow ui-icon-search'+ themeclass +'"></div>').parent();
2598
- var clearbtn = $('<a href="#" class="ui-input-clear" title="clear text">clear text</a>')
2599
- .click(function(){
2600
- input.val('').focus();
2601
- input.trigger('change');
2602
- clearbtn.addClass('ui-input-clear-hidden');
2603
- return false;
2604
- })
2605
- .appendTo(focusedEl)
2606
- .buttonMarkup({icon: 'delete', iconpos: 'notext', corners:true, shadow:true});
2607
-
2608
- function toggleClear(){
2609
- if(input.val() == ''){
2610
- clearbtn.addClass('ui-input-clear-hidden');
2611
- }
2612
- else{
2613
- clearbtn.removeClass('ui-input-clear-hidden');
2614
- }
2615
- }
2616
-
2617
- toggleClear();
2618
- input.keyup(toggleClear);
2619
- }
2620
- else{
2621
- input.addClass('ui-corner-all ui-shadow-inset' + themeclass);
2622
- }
2623
-
2624
- input
2625
- .focus(function(){
2626
- focusedEl.addClass('ui-focus');
2627
- })
2628
- .blur(function(){
2629
- focusedEl.removeClass('ui-focus');
2630
- });
2631
-
2632
- //autogrow
2633
- if ( input.is('textarea') ) {
2634
- var extraLineHeight = 15,
2635
- keyupTimeoutBuffer = 100,
2636
- keyup = function() {
2637
- var scrollHeight = input[0].scrollHeight,
2638
- clientHeight = input[0].clientHeight;
2639
- if ( clientHeight < scrollHeight ) {
2640
- input.css({ height: (scrollHeight + extraLineHeight) });
2641
- }
2642
- },
2643
- keyupTimeout;
2644
- input.keyup(function() {
2645
- clearTimeout( keyupTimeout );
2646
- keyupTimeout = setTimeout( keyup, keyupTimeoutBuffer );
2647
- });
2648
- }
2649
- },
2650
-
2651
- disable: function(){
2652
- ( this.element.attr("disabled",true).is('[type="search"],[data-type="search"]') ? this.element.parent() : this.element ).addClass("ui-disabled");
2653
- },
2654
-
2655
- enable: function(){
2656
- ( this.element.attr("disabled", false).is('[type="search"],[data-type="search"]') ? this.element.parent() : this.element ).removeClass("ui-disabled");
2657
- }
2658
- });
2659
- })( jQuery );
2660
-
2661
-
2662
3090
  /*
2663
3091
  * jQuery Mobile Framework : "selectmenu" plugin
2664
3092
  * Copyright (c) jQuery Project
2665
3093
  * Dual licensed under the MIT or GPL Version 2 licenses.
2666
3094
  * http://jquery.org/license
2667
- */
3095
+ */
2668
3096
  (function($, undefined ) {
2669
3097
  $.widget( "mobile.selectmenu", $.mobile.widget, {
2670
3098
  options: {
2671
3099
  theme: null,
2672
- disabled: false,
3100
+ disabled: false,
2673
3101
  icon: 'arrow-d',
2674
3102
  iconpos: 'right',
2675
3103
  inline: null,
@@ -2679,43 +3107,43 @@ $.widget( "mobile.selectmenu", $.mobile.widget, {
2679
3107
  menuPageTheme: 'b',
2680
3108
  overlayTheme: 'a',
2681
3109
  hidePlaceholderMenuItems: true,
2682
- closeText: 'Close'
3110
+ closeText: 'Close',
3111
+ useNativeMenu: false
2683
3112
  },
2684
3113
  _create: function(){
2685
-
3114
+
2686
3115
  var self = this,
2687
-
3116
+
2688
3117
  o = this.options,
2689
-
3118
+
2690
3119
  select = this.element
2691
- .attr( "tabindex", "-1" )
2692
3120
  .wrap( "<div class='ui-select'>" ),
2693
-
3121
+
2694
3122
  selectID = select.attr( "id" ),
2695
-
3123
+
2696
3124
  isMultiple = self.isMultiple = select[0].multiple,
2697
-
3125
+
2698
3126
  options = select.find("option"),
2699
-
3127
+
2700
3128
  label = $( "label[for="+ selectID +"]" ).addClass( "ui-select" ),
2701
-
3129
+
2702
3130
  buttonId = selectID + "-button",
2703
-
3131
+
2704
3132
  menuId = selectID + "-menu",
2705
-
3133
+
2706
3134
  thisPage = select.closest( ".ui-page" ),
2707
-
2708
- button = $( "<a>", {
3135
+
3136
+ button = $( "<a>", {
2709
3137
  "href": "#",
2710
3138
  "role": "button",
2711
3139
  "id": buttonId,
2712
3140
  "aria-haspopup": "true",
2713
- "aria-owns": menuId
3141
+ "aria-owns": menuId
2714
3142
  })
2715
3143
  .text( $( select[0].options.item(select[0].selectedIndex) ).text() )
2716
3144
  .insertBefore( select )
2717
3145
  .buttonMarkup({
2718
- theme: o.theme,
3146
+ theme: o.theme,
2719
3147
  icon: o.icon,
2720
3148
  iconpos: o.iconpos,
2721
3149
  inline: o.inline,
@@ -2723,9 +3151,9 @@ $.widget( "mobile.selectmenu", $.mobile.widget, {
2723
3151
  shadow: o.shadow,
2724
3152
  iconshadow: o.iconshadow
2725
3153
  }),
2726
-
3154
+
2727
3155
  theme = /ui-btn-up-([a-z])/.exec( button.attr("class") )[1],
2728
-
3156
+
2729
3157
  menuPage = $( "<div data-role='dialog' data-theme='"+ o.menuPageTheme +"'>" +
2730
3158
  "<div data-role='header'>" +
2731
3159
  "<div class='ui-title'>" + label.text() + "</div>"+
@@ -2733,46 +3161,52 @@ $.widget( "mobile.selectmenu", $.mobile.widget, {
2733
3161
  "<div data-role='content'></div>"+
2734
3162
  "</div>" )
2735
3163
  .appendTo( $.mobile.pageContainer )
2736
- .page(),
2737
-
3164
+ .page(),
3165
+
2738
3166
  menuPageContent = menuPage.find( ".ui-content" ),
2739
-
3167
+
2740
3168
  menuPageClose = menuPage.find( ".ui-header a" ),
2741
-
3169
+
2742
3170
  screen = $( "<div>", {"class": "ui-selectmenu-screen ui-screen-hidden"})
2743
- .appendTo( thisPage ),
2744
-
3171
+ .appendTo( thisPage ),
3172
+
2745
3173
  listbox = $( "<div>", { "class": "ui-selectmenu ui-selectmenu-hidden ui-overlay-shadow ui-corner-all pop ui-body-" + o.overlayTheme } )
2746
3174
  .insertAfter(screen),
2747
-
2748
- list = $( "<ul>", {
2749
- "class": "ui-selectmenu-list",
2750
- "id": menuId,
2751
- "role": "listbox",
3175
+
3176
+ list = $( "<ul>", {
3177
+ "class": "ui-selectmenu-list",
3178
+ "id": menuId,
3179
+ "role": "listbox",
2752
3180
  "aria-labelledby": buttonId,
2753
3181
  "data-theme": theme
2754
3182
  })
2755
3183
  .appendTo( listbox ),
2756
-
3184
+
2757
3185
  header = $( "<div>", {
2758
- "data-role": "header",
2759
- "data-nobackbtn": true
3186
+ "class": "ui-header ui-bar-" + theme
2760
3187
  })
2761
3188
  .prependTo( listbox ),
2762
-
2763
- headerTitle = $( "<h1>" )
3189
+
3190
+ headerTitle = $( "<h1>", {
3191
+ "class": "ui-title"
3192
+ })
2764
3193
  .appendTo( header ),
2765
-
3194
+
2766
3195
  headerClose = $( "<a>", {
2767
3196
  "data-iconpos": "notext",
2768
3197
  "data-icon": "delete",
2769
3198
  "text": o.closeText,
2770
- "href": "#"
3199
+ "href": "#",
3200
+ "class": "ui-btn-left"
2771
3201
  })
2772
- .appendTo( header ),
2773
-
3202
+ .appendTo( header )
3203
+ .buttonMarkup(),
3204
+
2774
3205
  menuType;
2775
-
3206
+
3207
+ // set to native menu
3208
+ o.useNativeMenu = $.mobile.nativeSelectMenus || select.is( "[data-native]" );
3209
+
2776
3210
  // add counter for multi selects
2777
3211
  if( isMultiple ){
2778
3212
  self.buttonCount = $('<span>')
@@ -2780,10 +3214,11 @@ $.widget( "mobile.selectmenu", $.mobile.widget, {
2780
3214
  .hide()
2781
3215
  .appendTo( button );
2782
3216
  }
2783
-
3217
+
2784
3218
  //expose to other methods
2785
3219
  $.extend(self, {
2786
3220
  select: select,
3221
+ optionElems: options,
2787
3222
  selectID: selectID,
2788
3223
  label: label,
2789
3224
  buttonId:buttonId,
@@ -2801,44 +3236,92 @@ $.widget( "mobile.selectmenu", $.mobile.widget, {
2801
3236
  headerTitle:headerTitle,
2802
3237
  placeholder: ''
2803
3238
  });
2804
-
3239
+
2805
3240
  //create list from select, update state
2806
3241
  self.refresh();
2807
-
3242
+
2808
3243
  //disable if specified
2809
3244
  if( o.disabled ){ this.disable(); }
2810
3245
 
2811
- //events on native select
2812
- select
2813
- .change(function(){
2814
- self.refresh();
2815
- })
2816
- .focus(function(){
2817
- $(this).blur();
2818
- button.focus();
2819
- });
2820
-
2821
- //button events
2822
- button.bind( $.support.touch ? "touchstart" : "click", function(event){
2823
- self.open();
2824
- event.preventDefault();
2825
- });
2826
-
3246
+ //events on native select
3247
+ select
3248
+ .change(function(){
3249
+ self.refresh();
3250
+ });
3251
+
3252
+ //support for using the native select menu with a custom button
3253
+ if( o.useNativeMenu ){
3254
+
3255
+ select
3256
+ .appendTo(button)
3257
+ .bind( "touchstart mousedown", function( e ){
3258
+ //add active class to button
3259
+ button.addClass( $.mobile.activeBtnClass );
3260
+
3261
+ //ensure button isn't clicked
3262
+ e.stopPropagation();
3263
+ })
3264
+ .bind( "focus mouseover", function(){
3265
+ button.trigger( "mouseover" );
3266
+ })
3267
+ .bind( "blur mouseout", function(){
3268
+ button
3269
+ .trigger( "mouseout" )
3270
+ .removeClass( $.mobile.activeBtnClass );
3271
+ });
3272
+
3273
+ button.attr( "tabindex", "-1" );
3274
+ } else {
3275
+
3276
+ select
3277
+ .attr( "tabindex", "-1" )
3278
+ .focus(function(){
3279
+ $(this).blur();
3280
+ button.focus();
3281
+ });
3282
+
3283
+ //button events
3284
+ button
3285
+ .bind( "touchstart" , function( event ){
3286
+ //set startTouches to cached copy of
3287
+ $( this ).data( "startTouches", $.extend({}, event.originalEvent.touches[ 0 ]) );
3288
+ })
3289
+ .bind( $.support.touch ? "touchend" : "mouseup" , function( event ){
3290
+ //if it's a scroll, don't open
3291
+ if( $( this ).data( "moved" ) ){
3292
+ $( this ).removeData( "moved" );
3293
+ } else {
3294
+ self.open();
3295
+ }
3296
+ event.preventDefault();
3297
+ })
3298
+ .bind( "touchmove", function( event ){
3299
+ //if touch moved enough, set data moved and don't open menu
3300
+ var thisTouches = event.originalEvent.touches[ 0 ],
3301
+ startTouches = $( this ).data( "startTouches" ),
3302
+ deltaX = Math.abs(thisTouches.pageX - startTouches.pageX),
3303
+ deltaY = Math.abs(thisTouches.pageY - startTouches.pageY);
3304
+
3305
+ if( deltaX > 10 || deltaY > 10 ){
3306
+ $( this ).data( "moved", true );
3307
+ }
3308
+ });
3309
+ }
3310
+
2827
3311
  //events for list items
2828
3312
  list.delegate("li:not(.ui-disabled, .ui-li-divider)", "click", function(event){
2829
-
2830
3313
  // clicking on the list item fires click on the link in listview.js.
2831
3314
  // to prevent this handler from firing twice if the link isn't clicked on,
2832
3315
  // short circuit unless the target is the link
2833
3316
  if( !$(event.target).is("a") ){ return; }
2834
3317
 
2835
- // index of option tag to be selected
3318
+ // index of option tag to be selected
2836
3319
  var newIndex = list.find( "li:not(.ui-li-divider)" ).index( this ),
2837
- option = options.eq( newIndex )[0];
2838
-
3320
+ option = self.optionElems.eq( newIndex )[0];
3321
+
2839
3322
  // toggle selected status on the tag for multi selects
2840
3323
  option.selected = isMultiple ? !option.selected : true;
2841
-
3324
+
2842
3325
  // toggle checkbox class for multiple selects
2843
3326
  if( isMultiple ){
2844
3327
  $(this)
@@ -2846,141 +3329,144 @@ $.widget( "mobile.selectmenu", $.mobile.widget, {
2846
3329
  .toggleClass('ui-icon-checkbox-on', option.selected)
2847
3330
  .toggleClass('ui-icon-checkbox-off', !option.selected);
2848
3331
  }
2849
-
3332
+
2850
3333
  // trigger change
2851
- select.trigger( "change" );
2852
-
3334
+ select.trigger( "change" );
3335
+
2853
3336
  //hide custom select for single selects only
2854
3337
  if( !isMultiple ){
2855
3338
  self.close();
2856
3339
  }
2857
-
3340
+
2858
3341
  event.preventDefault();
2859
3342
  });
2860
-
3343
+
2861
3344
  //events on "screen" overlay + close button
2862
- screen.add( headerClose ).add( menuPageClose ).click(function(event){
2863
- self.close();
2864
- event.preventDefault();
2865
-
2866
- // if the dialog's close icon was clicked, prevent the dialog's close
2867
- // handler from firing. selectmenu's should take precedence
2868
- if( $.contains(menuPageClose[0], event.target) ){
2869
- event.stopImmediatePropagation();
2870
- }
2871
- });
3345
+ screen
3346
+ .add( headerClose )
3347
+ .add( menuPageClose )
3348
+ .bind("click", function(event){
3349
+ self.close();
3350
+ event.preventDefault();
3351
+
3352
+ // if the dialog's close icon was clicked, prevent the dialog's close
3353
+ // handler from firing. selectmenu's should take precedence
3354
+ if( $.contains(menuPageClose[0], event.target) ){
3355
+ event.stopImmediatePropagation();
3356
+ }
3357
+ });
2872
3358
  },
2873
-
3359
+
2874
3360
  _buildList: function(){
2875
- var self = this,
3361
+ var self = this,
2876
3362
  optgroups = [],
2877
3363
  o = this.options,
2878
3364
  placeholder = this.placeholder;
2879
-
3365
+
2880
3366
  self.list.empty().filter('.ui-listview').listview('destroy');
2881
-
3367
+
2882
3368
  //populate menu with options from select element
2883
3369
  self.select.find( "option" ).each(function( i ){
2884
3370
  var $this = $(this),
2885
3371
  $parent = $this.parent(),
2886
3372
  text = $this.text();
2887
-
3373
+
2888
3374
  // are we inside an optgroup?
2889
3375
  if( $parent.is("optgroup") ){
2890
3376
  var optLabel = $parent.attr("label");
2891
-
3377
+
2892
3378
  // has this optgroup already been built yet?
2893
3379
  if( $.inArray(optLabel, optgroups) === -1 ){
2894
3380
  $("<li>", {
2895
3381
  "data-role":"list-divider",
2896
3382
  "text": optLabel
2897
3383
  }).appendTo( self.list );
2898
-
3384
+
2899
3385
  optgroups.push( optLabel );
2900
3386
  }
2901
3387
  }
2902
-
2903
- var anchor = $("<a>", {
2904
- "role": "",
3388
+
3389
+ var anchor = $("<a>", {
3390
+ "role": "",
2905
3391
  "href": "#",
2906
3392
  "text": text
2907
3393
  }),
2908
-
3394
+
2909
3395
  item = $( "<li>", { "data-icon": false });
2910
-
3396
+
2911
3397
  if( !this.getAttribute('value') || text.length == 0 || $this.data('placeholder') ){
2912
3398
  if( o.hidePlaceholderMenuItems ){
2913
3399
  item.addClass('ui-selectmenu-placeholder');
2914
3400
  }
2915
-
3401
+
2916
3402
  placeholder = self.placeholder = text;
2917
3403
  }
2918
-
3404
+
2919
3405
  // multiple select defaults
2920
3406
  if( self.isMultiple ){
2921
3407
  item.data('icon', 'checkbox-off');
2922
3408
  }
2923
-
3409
+
2924
3410
  // support disabled option tags
2925
3411
  if( this.disabled ){
2926
3412
  item.addClass("ui-disabled")
2927
3413
  .attr("aria-disabled", true);
2928
3414
  }
2929
-
3415
+
2930
3416
  item
2931
3417
  .append( anchor )
2932
3418
  .appendTo( self.list );
2933
3419
  });
2934
-
3420
+
2935
3421
  // hide header close link for single selects
2936
3422
  if( !this.isMultiple ){
2937
3423
  this.headerClose.hide();
2938
3424
  }
2939
-
3425
+
2940
3426
  // hide header if it's not a multiselect and there's no placeholder
2941
3427
  if( !this.isMultiple && !placeholder.length ){
2942
3428
  this.header.hide();
2943
3429
  } else {
2944
3430
  this.headerTitle.text( this.placeholder );
2945
3431
  }
2946
-
3432
+
2947
3433
  //now populated, create listview
2948
3434
  self.list.listview();
2949
3435
  },
2950
-
3436
+
2951
3437
  refresh: function( forceRebuild ){
2952
3438
  var self = this,
2953
3439
  select = this.element,
2954
3440
  isMultiple = this.isMultiple,
2955
- options = select.find("option"),
3441
+ options = this.optionElems = select.find("option"),
2956
3442
  selected = options.filter(":selected"),
2957
-
3443
+
2958
3444
  // return an array of all selected index's
2959
3445
  indicies = selected.map(function(){
2960
3446
  return options.index( this );
2961
3447
  }).get();
2962
-
3448
+
2963
3449
  if( forceRebuild || select[0].options.length > self.list.find('li').length ){
2964
3450
  self._buildList();
2965
3451
  }
2966
-
3452
+
2967
3453
  self.button
2968
3454
  .find( ".ui-btn-text" )
2969
3455
  .text(function(){
2970
3456
  if( !isMultiple ){
2971
3457
  return selected.text();
2972
3458
  }
2973
-
3459
+
2974
3460
  return selected.length ?
2975
3461
  selected.map(function(){ return $(this).text(); }).get().join(', ') :
2976
3462
  self.placeholder;
2977
3463
  });
2978
-
3464
+
2979
3465
  // multiple count inside button
2980
3466
  if( isMultiple ){
2981
3467
  self.buttonCount[ selected.length > 1 ? 'show' : 'hide' ]().text( selected.length );
2982
3468
  }
2983
-
3469
+
2984
3470
  self.list
2985
3471
  .find( 'li:not(.ui-li-divider)' )
2986
3472
  .removeClass( $.mobile.activeBtnClass )
@@ -2988,10 +3474,10 @@ $.widget( "mobile.selectmenu", $.mobile.widget, {
2988
3474
  .each(function( i ){
2989
3475
  if( $.inArray(i, indicies) > -1 ){
2990
3476
  var item = $(this).addClass( $.mobile.activeBtnClass );
2991
-
3477
+
2992
3478
  // aria selected attr
2993
3479
  item.find( 'a' ).attr( 'aria-selected', true );
2994
-
3480
+
2995
3481
  // multiple selects: add the "on" checkbox state to the icon
2996
3482
  if( isMultiple ){
2997
3483
  item.find('.ui-icon').removeClass('ui-icon-checkbox-off').addClass('ui-icon-checkbox-on');
@@ -2999,280 +3485,130 @@ $.widget( "mobile.selectmenu", $.mobile.widget, {
2999
3485
  }
3000
3486
  });
3001
3487
  },
3002
-
3488
+
3003
3489
  open: function(){
3004
3490
  if( this.options.disabled ){ return; }
3005
-
3491
+
3006
3492
  var self = this,
3007
3493
  menuHeight = self.list.outerHeight(),
3008
3494
  menuWidth = self.list.outerWidth(),
3009
3495
  scrollTop = $(window).scrollTop(),
3010
3496
  btnOffset = self.button.offset().top,
3011
3497
  screenHeight = window.innerHeight,
3012
- screenWidth = window.innerWidth;
3013
-
3498
+ screenWidth = window.innerWidth,
3499
+ dialogUsed = self.list.parents('.ui-dialog').length;
3500
+
3014
3501
  //add active class to button
3015
3502
  self.button.addClass( $.mobile.activeBtnClass );
3016
-
3503
+
3017
3504
  function focusMenuItem(){
3018
3505
  self.list.find( ".ui-btn-active" ).focus();
3019
3506
  }
3020
-
3021
- if( menuHeight > screenHeight - 80 || !$.support.scrollTop ){
3022
-
3507
+
3508
+ // NOTE addresses issue with firefox outerHeight when the parent dialog
3509
+ // is display: none. Upstream?
3510
+ if( dialogUsed || menuHeight > screenHeight - 80 || !$.support.scrollTop ){
3511
+
3023
3512
  //for webos (set lastscroll using button offset)
3024
3513
  if( scrollTop == 0 && btnOffset > screenHeight ){
3025
3514
  self.thisPage.one('pagehide',function(){
3026
3515
  $(this).data('lastScroll', btnOffset);
3027
- });
3028
- }
3029
-
3030
- self.menuPage.one('pageshow',focusMenuItem);
3031
-
3032
- self.menuType = "page";
3033
- self.menuPageContent.append( self.list );
3034
- $.mobile.changePage(self.menuPage, 'pop', false, false);
3035
- }
3036
- else {
3037
- self.menuType = "overlay";
3038
-
3039
- self.screen
3040
- .height( $(document).height() )
3041
- .removeClass('ui-screen-hidden');
3042
-
3043
- self.listbox
3044
- .append( self.list )
3045
- .removeClass( "ui-selectmenu-hidden" )
3046
- .position({
3047
- my: "center center",
3048
- at: "center center",
3049
- of: self.button,
3050
- collision: "fit"
3051
- })
3052
- .addClass("in");
3053
-
3054
- focusMenuItem();
3055
- }
3056
- },
3057
-
3058
- close: function(){
3059
- if( this.options.disabled ){ return; }
3060
- var self = this;
3061
-
3062
- function focusButton(){
3063
- setTimeout(function(){
3064
- self.button.focus();
3065
-
3066
- //remove active class from button
3067
- self.button.removeClass( $.mobile.activeBtnClass );
3068
- }, 40);
3069
-
3070
- self.listbox.removeAttr('style').append( self.list );
3071
- }
3072
-
3073
- if(self.menuType == "page"){
3074
- $.mobile.changePage([self.menuPage,self.thisPage], 'pop', true, false);
3075
- self.menuPage.one("pagehide", focusButton);
3076
- }
3077
- else{
3078
- self.screen.addClass( "ui-screen-hidden" );
3079
- self.listbox.addClass( "ui-selectmenu-hidden" ).removeAttr( "style" ).removeClass("in");
3080
- focusButton();
3081
- }
3082
-
3083
- },
3084
-
3085
- disable: function(){
3086
- this.element.attr("disabled",true);
3087
- this.button.addClass('ui-disabled').attr("aria-disabled", true);
3088
- return this._setOption( "disabled", true );
3089
- },
3090
-
3091
- enable: function(){
3092
- this.element.attr("disabled",false);
3093
- this.button.removeClass('ui-disabled').attr("aria-disabled", false);
3094
- return this._setOption( "disabled", false );
3095
- }
3096
- });
3097
- })( jQuery );
3098
-
3099
-
3100
-
3101
- /*
3102
- * jQuery Mobile Framework : plugin for making button-like links
3103
- * Copyright (c) jQuery Project
3104
- * Dual licensed under the MIT or GPL Version 2 licenses.
3105
- * http://jquery.org/license
3106
- */
3107
- (function($, undefined ) {
3108
-
3109
- $.fn.buttonMarkup = function( options ){
3110
- return this.each( function() {
3111
- var el = $( this ),
3112
- o = $.extend( {}, $.fn.buttonMarkup.defaults, el.data(), options),
3113
-
3114
- // Classes Defined
3115
- buttonClass,
3116
- innerClass = "ui-btn-inner",
3117
- iconClass;
3118
-
3119
- if ( attachEvents ) {
3120
- attachEvents();
3121
- }
3122
-
3123
- // if not, try to find closest theme container
3124
- if ( !o.theme ) {
3125
- var themedParent = el.closest("[class*='ui-bar-'],[class*='ui-body-']");
3126
- o.theme = themedParent.length ?
3127
- /ui-(bar|body)-([a-z])/.exec( themedParent.attr("class") )[2] :
3128
- "c";
3129
- }
3130
-
3131
- buttonClass = "ui-btn ui-btn-up-" + o.theme;
3132
-
3133
- if ( o.inline ) {
3134
- buttonClass += " ui-btn-inline";
3135
- }
3136
-
3137
- if ( o.icon ) {
3138
- o.icon = "ui-icon-" + o.icon;
3139
- o.iconpos = o.iconpos || "left";
3140
-
3141
- iconClass = "ui-icon " + o.icon;
3142
-
3143
- if ( o.shadow ) {
3144
- iconClass += " ui-icon-shadow"
3145
- }
3146
- }
3147
-
3148
- if ( o.iconpos ) {
3149
- buttonClass += " ui-btn-icon-" + o.iconpos;
3150
-
3151
- if ( o.iconpos == "notext" && !el.attr("title") ) {
3152
- el.attr( "title", el.text() );
3516
+ });
3153
3517
  }
3154
- }
3155
-
3156
- if ( o.corners ) {
3157
- buttonClass += " ui-btn-corner-all";
3158
- innerClass += " ui-btn-corner-all";
3159
- }
3160
-
3161
- if ( o.shadow ) {
3162
- buttonClass += " ui-shadow";
3163
- }
3164
-
3165
- el
3166
- .attr( "data-theme", o.theme )
3167
- .addClass( buttonClass );
3168
-
3169
- var wrap = ("<D class='" + innerClass + "'><D class='ui-btn-text'></D>" +
3170
- ( o.icon ? "<span class='" + iconClass + "'></span>" : "" ) +
3171
- "</D>").replace(/D/g, o.wrapperEls);
3172
-
3173
- el.wrapInner( wrap );
3174
- });
3175
- };
3176
3518
 
3177
- $.fn.buttonMarkup.defaults = {
3178
- corners: true,
3179
- shadow: true,
3180
- iconshadow: true,
3181
- wrapperEls: "span"
3182
- };
3519
+ self.menuPage.one('pageshow',focusMenuItem);
3183
3520
 
3184
- var attachEvents = function() {
3185
- $(".ui-btn:not(.ui-disabled)").live({
3186
- mousedown: function() {
3187
- var theme = $(this).attr( "data-theme" );
3188
- $(this).removeClass( "ui-btn-up-" + theme ).addClass( "ui-btn-down-" + theme );
3189
- },
3190
- mouseup: function() {
3191
- var theme = $(this).attr( "data-theme" );
3192
- $(this).removeClass( "ui-btn-down-" + theme ).addClass( "ui-btn-up-" + theme );
3193
- },
3194
- "mouseover focus": function() {
3195
- var theme = $(this).attr( "data-theme" );
3196
- $(this).removeClass( "ui-btn-up-" + theme ).addClass( "ui-btn-hover-" + theme );
3197
- },
3198
- "mouseout blur": function() {
3199
- var theme = $(this).attr( "data-theme" );
3200
- $(this).removeClass( "ui-btn-hover-" + theme ).addClass( "ui-btn-up-" + theme );
3521
+ self.menuType = "page";
3522
+ self.menuPageContent.append( self.list );
3523
+ $.mobile.changePage(self.menuPage, 'pop', false, false);
3201
3524
  }
3202
- });
3525
+ else {
3526
+ self.menuType = "overlay";
3203
3527
 
3204
- attachEvents = null;
3205
- };
3528
+ self.screen
3529
+ .height( $(document).height() )
3530
+ .removeClass('ui-screen-hidden');
3206
3531
 
3207
- })(jQuery);
3532
+ //try and center the overlay over the button
3533
+ var roomtop = btnOffset - scrollTop,
3534
+ roombot = scrollTop + screenHeight - btnOffset,
3535
+ halfheight = menuHeight / 2,
3536
+ newtop,newleft;
3537
+
3538
+ if( roomtop > menuHeight / 2 && roombot > menuHeight / 2 ){
3539
+ newtop = btnOffset + ( self.button.outerHeight() / 2 ) - halfheight;
3540
+ }
3541
+ else{
3542
+ //30px tolerance off the edges
3543
+ newtop = roomtop > roombot ? scrollTop + screenHeight - menuHeight - 30 : scrollTop + 30;
3544
+ }
3545
+
3546
+ newleft = self.button.offset().left + self.button.outerWidth() / 2 - menuWidth / 2;
3547
+
3208
3548
 
3549
+ self.listbox
3550
+ .append( self.list )
3551
+ .removeClass( "ui-selectmenu-hidden" )
3552
+ .css({
3553
+ top: newtop,
3554
+ left: newleft
3555
+ })
3556
+ .addClass("in");
3209
3557
 
3210
- /*
3211
- * jQuery Mobile Framework : "button" plugin - links that proxy to native input/buttons
3212
- * Copyright (c) jQuery Project
3213
- * Dual licensed under the MIT or GPL Version 2 licenses.
3214
- * http://jquery.org/license
3215
- */
3216
- (function($, undefined ) {
3217
- $.widget( "mobile.button", $.mobile.widget, {
3218
- options: {
3219
- theme: null,
3220
- icon: null,
3221
- iconpos: null,
3222
- inline: null,
3223
- corners: true,
3224
- shadow: true,
3225
- iconshadow: true
3226
- },
3227
- _create: function(){
3228
- var $el = this.element,
3229
- o = this.options;
3230
-
3231
- //add ARIA role
3232
- this.button = $( "<div></div>" )
3233
- .text( $el.text() || $el.val() )
3234
- .buttonMarkup({
3235
- theme: o.theme,
3236
- icon: o.icon,
3237
- iconpos: o.iconpos,
3238
- inline: o.inline,
3239
- corners: o.corners,
3240
- shadow: o.shadow,
3241
- iconshadow: o.iconshadow
3242
- })
3243
- .insertBefore( $el )
3244
- .append( $el.addClass('ui-btn-hidden') );
3245
-
3246
- //add hidden input during submit
3247
- if( $el.attr('type') !== 'reset' ){
3248
- $el.click(function(){
3249
- var $buttonPlaceholder = $("<input>",
3250
- {type: "hidden", name: $el.attr("name"), value: $el.attr("value")})
3251
- .insertBefore($el);
3252
-
3253
- //bind to doc to remove after submit handling
3254
- $(document).submit(function(){
3255
- $buttonPlaceholder.remove();
3256
- });
3257
- });
3558
+ focusMenuItem();
3258
3559
  }
3259
-
3560
+
3561
+ // wait before the dialog can be closed
3562
+ setTimeout(function(){
3563
+ self.isOpen = true;
3564
+ }, 400);
3260
3565
  },
3261
3566
 
3262
- enable: function(){
3263
- this.element.attr("disabled", false);
3264
- this.button.removeClass("ui-disabled").attr("aria-disabled", false);
3265
- return this._setOption("disabled", false);
3567
+ close: function(){
3568
+ if( this.options.disabled || !this.isOpen ){ return; }
3569
+ var self = this;
3570
+
3571
+ function focusButton(){
3572
+ setTimeout(function(){
3573
+ self.button.focus();
3574
+
3575
+ //remove active class from button
3576
+ self.button.removeClass( $.mobile.activeBtnClass );
3577
+ }, 40);
3578
+
3579
+ self.listbox.removeAttr('style').append( self.list );
3580
+ }
3581
+
3582
+ if(self.menuType == "page"){
3583
+ $.mobile.changePage([self.menuPage,self.thisPage], 'pop', true, false);
3584
+ self.menuPage.one("pagehide", focusButton);
3585
+ }
3586
+ else{
3587
+ self.screen.addClass( "ui-screen-hidden" );
3588
+ self.listbox.addClass( "ui-selectmenu-hidden" ).removeAttr( "style" ).removeClass("in");
3589
+ focusButton();
3590
+ }
3591
+
3592
+ // allow the dialog to be closed again
3593
+ this.isOpen = false;
3266
3594
  },
3267
3595
 
3268
3596
  disable: function(){
3269
- this.element.attr("disabled", true);
3270
- this.button.addClass("ui-disabled").attr("aria-disabled", true);
3271
- return this._setOption("disabled", true);
3597
+ this.element.attr("disabled",true);
3598
+ this.button.addClass('ui-disabled').attr("aria-disabled", true);
3599
+ return this._setOption( "disabled", true );
3600
+ },
3601
+
3602
+ enable: function(){
3603
+ this.element.attr("disabled",false);
3604
+ this.button.removeClass('ui-disabled').attr("aria-disabled", false);
3605
+ return this._setOption( "disabled", false );
3272
3606
  }
3273
3607
  });
3274
3608
  })( jQuery );
3275
3609
 
3610
+
3611
+
3276
3612
  /*
3277
3613
  * jQuery Mobile Framework : "slider" plugin
3278
3614
  * Copyright (c) jQuery Project
@@ -3304,11 +3640,12 @@ $.widget( "mobile.slider", $.mobile.widget, {
3304
3640
  controlID = control.attr('id'),
3305
3641
  labelID = controlID + '-label',
3306
3642
  label = $('[for='+ controlID +']').attr('id',labelID),
3307
- val = (cType == 'input') ? parseFloat(control.val()) : control[0].selectedIndex,
3643
+ val = function(){
3644
+ return (cType == 'input') ? parseFloat(control.val()) : control[0].selectedIndex;
3645
+ },
3308
3646
  min = (cType == 'input') ? parseFloat(control.attr('min')) : 0,
3309
3647
  max = (cType == 'input') ? parseFloat(control.attr('max')) : control.find('option').length-1,
3310
3648
  step = window.parseFloat(control.attr('data-step') || 1),
3311
-
3312
3649
  slider = $('<div class="ui-slider '+ selectClass +' ui-btn-down-'+ trackTheme+' ui-btn-corner-all" role="application"></div>'),
3313
3650
  handle = $('<a href="#" class="ui-slider-handle"></a>')
3314
3651
  .appendTo(slider)
@@ -3317,12 +3654,11 @@ $.widget( "mobile.slider", $.mobile.widget, {
3317
3654
  'role': 'slider',
3318
3655
  'aria-valuemin': min,
3319
3656
  'aria-valuemax': max,
3320
- 'aria-valuenow': val,
3321
- 'aria-valuetext': val,
3322
- 'title': val,
3657
+ 'aria-valuenow': val(),
3658
+ 'aria-valuetext': val(),
3659
+ 'title': val(),
3323
3660
  'aria-labelledby': labelID
3324
- }),
3325
- switchValues = {'off' : 0, 'on': 1};
3661
+ });
3326
3662
 
3327
3663
  $.extend(this, {
3328
3664
  slider: slider,
@@ -3347,13 +3683,21 @@ $.widget( "mobile.slider", $.mobile.widget, {
3347
3683
 
3348
3684
  label.addClass('ui-slider');
3349
3685
 
3686
+ // monitor the input for updated values
3350
3687
  control
3351
3688
  .addClass((cType == 'input') ? 'ui-slider-input' : 'ui-slider-switch')
3352
- .keyup(function(){
3353
- self.refresh( $(this).val() );
3689
+ .change(function(){
3690
+ self.refresh( val(), true );
3691
+ })
3692
+ .keyup(function(){ // necessary?
3693
+ self.refresh( val(), true, true );
3694
+ })
3695
+ .blur(function(){
3696
+ self.refresh( val(), true );
3354
3697
  });
3355
3698
 
3356
- $(document).bind($.support.touch ? "touchmove" : "mousemove", function(event){
3699
+ // prevent screen drag when slider activated
3700
+ $(document).bind( "touchmove mousemove", function(event){
3357
3701
  if ( self.dragging ) {
3358
3702
  self.refresh( event );
3359
3703
  return false;
@@ -3361,7 +3705,7 @@ $.widget( "mobile.slider", $.mobile.widget, {
3361
3705
  });
3362
3706
 
3363
3707
  slider
3364
- .bind($.support.touch ? "touchstart" : "mousedown", function(event){
3708
+ .bind( "touchstart mousedown", function(event){
3365
3709
  self.dragging = true;
3366
3710
  if ( cType === "select" ) {
3367
3711
  self.beforeStart = control[0].selectedIndex;
@@ -3372,7 +3716,7 @@ $.widget( "mobile.slider", $.mobile.widget, {
3372
3716
 
3373
3717
  slider
3374
3718
  .add(document)
3375
- .bind($.support.touch ? "touchend" : "mouseup", function(){
3719
+ .bind( "touchend mouseup", function(){
3376
3720
  if ( self.dragging ) {
3377
3721
  self.dragging = false;
3378
3722
  if ( cType === "select" ) {
@@ -3380,7 +3724,7 @@ $.widget( "mobile.slider", $.mobile.widget, {
3380
3724
  //tap occurred, but value didn't change. flip it!
3381
3725
  self.refresh( self.beforeStart === 0 ? 1 : 0 );
3382
3726
  }
3383
- var curval = (cType === "input") ? parseFloat(control.val()) : control[ 0 ].selectedIndex;
3727
+ var curval = val();
3384
3728
  var snapped = Math.round( curval / (max - min) * 100 );
3385
3729
  handle
3386
3730
  .addClass("ui-slider-handle-snapping")
@@ -3397,26 +3741,18 @@ $.widget( "mobile.slider", $.mobile.widget, {
3397
3741
 
3398
3742
  // NOTE force focus on handle
3399
3743
  this.handle
3400
- .bind($.support.touch ? "touchstart" : "mousedown", function(){
3744
+ .bind( "touchstart mousedown", function(){
3401
3745
  $(this).focus();
3402
3746
  });
3403
3747
 
3404
3748
  this.handle
3405
- .bind('keydown', function( event ) {
3406
- var valuenow = $( this ).attr( "aria-valuenow" ),
3407
- index;
3749
+ .bind( "keydown", function( event ) {
3750
+ var index = val();
3408
3751
 
3409
3752
  if ( self.options.disabled ) {
3410
3753
  return;
3411
3754
  }
3412
3755
 
3413
- // convert switch values to slider
3414
- if(valuenow.match(/off|on/)){
3415
- valuenow = switchValues[valuenow];
3416
- }
3417
-
3418
- index = window.parseFloat(valuenow, 10);
3419
-
3420
3756
  // In all cases prevent the default and mark the handle as active
3421
3757
  switch ( event.keyCode ) {
3422
3758
  case $.mobile.keyCode.HOME:
@@ -3466,7 +3802,7 @@ $.widget( "mobile.slider", $.mobile.widget, {
3466
3802
  this.refresh();
3467
3803
  },
3468
3804
 
3469
- refresh: function(val){
3805
+ refresh: function(val, isfromControl, preventInputUpdate){
3470
3806
  if ( this.options.disabled ) { return; }
3471
3807
 
3472
3808
  var control = this.element, percent,
@@ -3486,7 +3822,7 @@ $.widget( "mobile.slider", $.mobile.widget, {
3486
3822
  percent = Math.round( ((data.pageX - this.slider.offset().left) / this.slider.width() ) * 100 );
3487
3823
  } else {
3488
3824
  if ( val == null ) {
3489
- val = (cType === "input") ? parseFloat(control.val()) : control[ 0 ].selectedIndex;
3825
+ val = (cType === "input") ? parseFloat(control.val()) : control[0].selectedIndex;
3490
3826
  }
3491
3827
  percent = (parseFloat(val) - min) / (max - min) * 100;
3492
3828
  }
@@ -3521,13 +3857,15 @@ $.widget( "mobile.slider", $.mobile.widget, {
3521
3857
  }
3522
3858
  }
3523
3859
 
3524
- // update control's value
3525
- if ( cType === "input" ) {
3526
- control.val(newval);
3527
- } else {
3528
- control[ 0 ].selectedIndex = newval;
3860
+ if(!preventInputUpdate){
3861
+ // update control's value
3862
+ if ( cType === "input" ) {
3863
+ control.val(newval);
3864
+ } else {
3865
+ control[ 0 ].selectedIndex = newval;
3866
+ }
3867
+ if (!isfromControl) { control.trigger("change"); }
3529
3868
  }
3530
- control.trigger("change");
3531
3869
  },
3532
3870
 
3533
3871
  enable: function(){
@@ -3547,207 +3885,155 @@ $.widget( "mobile.slider", $.mobile.widget, {
3547
3885
 
3548
3886
 
3549
3887
  /*
3550
- * jQuery Mobile Framework : "collapsible" plugin
3888
+ * jQuery Mobile Framework : "textinput" plugin for text inputs, textareas
3551
3889
  * Copyright (c) jQuery Project
3552
3890
  * Dual licensed under the MIT or GPL Version 2 licenses.
3553
3891
  * http://jquery.org/license
3554
- */
3892
+ */
3555
3893
  (function($, undefined ) {
3556
- $.widget( "mobile.collapsible", $.mobile.widget, {
3894
+ $.widget( "mobile.textinput", $.mobile.widget, {
3557
3895
  options: {
3558
- expandCueText: ' click to expand contents',
3559
- collapseCueText: ' click to collapse contents',
3560
- collapsed: false,
3561
- heading: '>:header,>legend',
3562
- theme: null,
3563
- iconTheme: 'd'
3896
+ theme: null
3564
3897
  },
3565
3898
  _create: function(){
3566
-
3567
- var $el = this.element,
3899
+ var input = this.element,
3568
3900
  o = this.options,
3569
- collapsibleContain = $el.addClass('ui-collapsible-contain'),
3570
- collapsibleHeading = $el.find(o.heading).eq(0),
3571
- collapsibleContent = collapsibleContain.wrapInner('<div class="ui-collapsible-content"></div>').find('.ui-collapsible-content'),
3572
- collapsibleParent = $el.closest('[data-role="collapsible-set"]').addClass('ui-collapsible-set');
3573
-
3574
- //replace collapsibleHeading if it's a legend
3575
- if(collapsibleHeading.is('legend')){
3576
- collapsibleHeading = $('<div role="heading">'+ collapsibleHeading.html() +'</div>').insertBefore(collapsibleHeading);
3577
- collapsibleHeading.next().remove();
3901
+ theme = o.theme,
3902
+ themeclass;
3903
+
3904
+ if ( !theme ) {
3905
+ var themedParent = this.element.closest("[class*='ui-bar-'],[class*='ui-body-']");
3906
+ theme = themedParent.length ?
3907
+ /ui-(bar|body)-([a-z])/.exec( themedParent.attr("class") )[2] :
3908
+ "c";
3578
3909
  }
3579
3910
 
3580
- //drop heading in before content
3581
- collapsibleHeading.insertBefore(collapsibleContent);
3911
+ themeclass = " ui-body-" + theme;
3582
3912
 
3583
- //modify markup & attributes
3584
- collapsibleHeading.addClass('ui-collapsible-heading')
3585
- .append('<span class="ui-collapsible-heading-status"></span>')
3586
- .wrapInner('<a href="#" class="ui-collapsible-heading-toggle"></a>')
3587
- .find('a:eq(0)')
3588
- .buttonMarkup({
3589
- shadow: !!!collapsibleParent.length,
3590
- corners:false,
3591
- iconPos: 'left',
3592
- icon: 'plus',
3593
- theme: o.theme
3594
- })
3595
- .find('.ui-icon')
3596
- .removeAttr('class')
3597
- .buttonMarkup({
3598
- shadow: true,
3599
- corners:true,
3600
- iconPos: 'notext',
3601
- icon: 'plus',
3602
- theme: o.iconTheme
3603
- });
3604
-
3605
- if( !collapsibleParent.length ){
3606
- collapsibleHeading
3607
- .find('a:eq(0)')
3608
- .addClass('ui-corner-all')
3609
- .find('.ui-btn-inner')
3610
- .addClass('ui-corner-all');
3611
- }
3612
- else {
3613
- if( collapsibleContain.data('collapsible-last') ){
3614
- collapsibleHeading
3615
- .find('a:eq(0), .ui-btn-inner')
3616
- .addClass('ui-corner-bottom');
3617
- }
3618
- }
3619
-
3913
+ $('label[for='+input.attr('id')+']').addClass('ui-input-text');
3620
3914
 
3621
- //events
3622
- collapsibleContain
3623
- .bind('collapse', function(event){
3624
- if( !event.isDefaultPrevented() ){
3625
- event.preventDefault();
3626
- collapsibleHeading
3627
- .addClass('ui-collapsible-heading-collapsed')
3628
- .find('.ui-collapsible-heading-status').text(o.expandCueText);
3629
-
3630
- collapsibleHeading.find('.ui-icon').removeClass('ui-icon-minus').addClass('ui-icon-plus');
3631
- collapsibleContent.addClass('ui-collapsible-content-collapsed').attr('aria-hidden',true);
3632
-
3633
- if( collapsibleContain.data('collapsible-last') ){
3634
- collapsibleHeading
3635
- .find('a:eq(0), .ui-btn-inner')
3636
- .addClass('ui-corner-bottom');
3637
- }
3638
- }
3639
-
3640
- })
3641
- .bind('expand', function(event){
3642
- if( !event.isDefaultPrevented() ){
3643
- event.preventDefault();
3644
- collapsibleHeading
3645
- .removeClass('ui-collapsible-heading-collapsed')
3646
- .find('.ui-collapsible-heading-status').text(o.collapseCueText);
3647
-
3648
- collapsibleHeading.find('.ui-icon').removeClass('ui-icon-plus').addClass('ui-icon-minus');
3649
- collapsibleContent.removeClass('ui-collapsible-content-collapsed').attr('aria-hidden',false);
3650
-
3651
- if( collapsibleContain.data('collapsible-last') ){
3652
- collapsibleHeading
3653
- .find('a:eq(0), .ui-btn-inner')
3654
- .removeClass('ui-corner-bottom');
3655
- }
3656
-
3915
+ input.addClass('ui-input-text ui-body-'+ o.theme);
3916
+
3917
+ var focusedEl = input;
3918
+
3919
+ //"search" input widget
3920
+ if( input.is('[type="search"],[data-type="search"]') ){
3921
+ focusedEl = input.wrap('<div class="ui-input-search ui-shadow-inset ui-btn-corner-all ui-btn-shadow ui-icon-search'+ themeclass +'"></div>').parent();
3922
+ var clearbtn = $('<a href="#" class="ui-input-clear" title="clear text">clear text</a>')
3923
+ .tap(function( e ){
3924
+ input.val('').focus();
3925
+ input.trigger('change');
3926
+ clearbtn.addClass('ui-input-clear-hidden');
3927
+ e.preventDefault();
3928
+ })
3929
+ .appendTo(focusedEl)
3930
+ .buttonMarkup({icon: 'delete', iconpos: 'notext', corners:true, shadow:true});
3931
+
3932
+ function toggleClear(){
3933
+ if(input.val() == ''){
3934
+ clearbtn.addClass('ui-input-clear-hidden');
3935
+ }
3936
+ else{
3937
+ clearbtn.removeClass('ui-input-clear-hidden');
3657
3938
  }
3658
- })
3659
- .trigger(o.collapsed ? 'collapse' : 'expand');
3939
+ }
3660
3940
 
3661
-
3662
- //close others in a set
3663
- if( collapsibleParent.length && !collapsibleParent.data("collapsiblebound") ){
3664
- collapsibleParent
3665
- .data("collapsiblebound", true)
3666
- .bind("expand", function( event ){
3667
- $(this).find( ".ui-collapsible-contain" )
3668
- .not( $(event.target).closest( ".ui-collapsible-contain" ) )
3669
- .not( "> .ui-collapsible-contain .ui-collapsible-contain" )
3670
- .trigger( "collapse" );
3671
- })
3672
- var set = collapsibleParent.find('[data-role=collapsible]')
3673
-
3674
- set.first()
3675
- .find('a:eq(0)')
3676
- .addClass('ui-corner-top')
3677
- .find('.ui-btn-inner')
3678
- .addClass('ui-corner-top');
3679
-
3680
- set.last().data('collapsible-last', true)
3941
+ toggleClear();
3942
+ input.keyup(toggleClear);
3681
3943
  }
3682
-
3683
- collapsibleHeading.bind( $.support.touch ? "touchstart" : "click", function(){
3684
- if( collapsibleHeading.is('.ui-collapsible-heading-collapsed') ){
3685
- collapsibleContain.trigger('expand');
3686
- }
3687
- else {
3688
- collapsibleContain.trigger('collapse');
3689
- }
3690
- return false;
3691
- });
3944
+ else{
3945
+ input.addClass('ui-corner-all ui-shadow-inset' + themeclass);
3946
+ }
3947
+
3948
+ input
3949
+ .focus(function(){
3950
+ focusedEl.addClass('ui-focus');
3951
+ })
3952
+ .blur(function(){
3953
+ focusedEl.removeClass('ui-focus');
3954
+ });
3692
3955
 
3956
+ //autogrow
3957
+ if ( input.is('textarea') ) {
3958
+ var extraLineHeight = 15,
3959
+ keyupTimeoutBuffer = 100,
3960
+ keyup = function() {
3961
+ var scrollHeight = input[0].scrollHeight,
3962
+ clientHeight = input[0].clientHeight;
3963
+ if ( clientHeight < scrollHeight ) {
3964
+ input.css({ height: (scrollHeight + extraLineHeight) });
3965
+ }
3966
+ },
3967
+ keyupTimeout;
3968
+ input.keyup(function() {
3969
+ clearTimeout( keyupTimeout );
3970
+ keyupTimeout = setTimeout( keyup, keyupTimeoutBuffer );
3971
+ });
3972
+ }
3973
+ },
3974
+
3975
+ disable: function(){
3976
+ ( this.element.attr("disabled",true).is('[type="search"],[data-type="search"]') ? this.element.parent() : this.element ).addClass("ui-disabled");
3977
+ },
3978
+
3979
+ enable: function(){
3980
+ ( this.element.attr("disabled", false).is('[type="search"],[data-type="search"]') ? this.element.parent() : this.element ).removeClass("ui-disabled");
3693
3981
  }
3694
3982
  });
3695
3983
  })( jQuery );
3696
3984
 
3985
+
3697
3986
  /*
3698
- * jQuery Mobile Framework: "controlgroup" plugin - corner-rounding for groups of buttons, checks, radios, etc
3987
+ * jQuery Mobile Framework : plugin for creating CSS grids
3699
3988
  * Copyright (c) jQuery Project
3700
3989
  * Dual licensed under the MIT or GPL Version 2 licenses.
3701
3990
  * http://jquery.org/license
3702
- */
3991
+ */
3703
3992
  (function($, undefined ) {
3704
- $.fn.controlgroup = function(options){
3705
-
3706
- return $(this).each(function(){
3993
+ $.fn.grid = function(options){
3994
+ return this.each(function(){
3707
3995
  var o = $.extend({
3708
- direction: $( this ).data( "type" ) || "vertical",
3709
- shadow: false
3996
+ grid: null
3710
3997
  },options);
3711
- var groupheading = $(this).find('>legend'),
3712
- flCorners = o.direction == 'horizontal' ? ['ui-corner-left', 'ui-corner-right'] : ['ui-corner-top', 'ui-corner-bottom'],
3713
- type = $(this).find('input:eq(0)').attr('type');
3714
-
3715
- //replace legend with more stylable replacement div
3716
- if( groupheading.length ){
3717
- $(this).wrapInner('<div class="ui-controlgroup-controls"></div>');
3718
- $('<div role="heading" class="ui-controlgroup-label">'+ groupheading.html() +'</div>').insertBefore( $(this).children(0) );
3719
- groupheading.remove();
3720
- }
3721
-
3722
- $(this).addClass('ui-corner-all ui-controlgroup ui-controlgroup-'+o.direction);
3723
-
3724
- function flipClasses(els){
3725
- els
3726
- .removeClass('ui-btn-corner-all ui-shadow')
3727
- .eq(0).addClass(flCorners[0])
3728
- .end()
3729
- .filter(':last').addClass(flCorners[1]).addClass('ui-controlgroup-last');
3730
- }
3731
- flipClasses($(this).find('.ui-btn'));
3732
- flipClasses($(this).find('.ui-btn-inner'));
3733
- if(o.shadow){
3734
- $(this).addClass('ui-shadow');
3998
+
3999
+
4000
+ var $kids = $(this).children(),
4001
+ gridCols = {a: 2, b:3, c:4, d:5},
4002
+ grid = o.grid,
4003
+ iterator;
4004
+
4005
+ if( !grid ){
4006
+ if( $kids.length <= 5 ){
4007
+ for(var letter in gridCols){
4008
+ if(gridCols[letter] == $kids.length){ grid = letter; }
4009
+ }
4010
+ }
4011
+ else{
4012
+ grid = 'a';
4013
+ }
4014
+ }
4015
+ iterator = gridCols[grid];
4016
+
4017
+ $(this).addClass('ui-grid-' + grid);
4018
+
4019
+ $kids.filter(':nth-child(' + iterator + 'n+1)').addClass('ui-block-a');
4020
+ $kids.filter(':nth-child(' + iterator + 'n+2)').addClass('ui-block-b');
4021
+
4022
+ if(iterator > 2){
4023
+ $kids.filter(':nth-child(3n+3)').addClass('ui-block-c');
4024
+ }
4025
+ if(iterator> 3){
4026
+ $kids.filter(':nth-child(4n+4)').addClass('ui-block-d');
4027
+ }
4028
+ if(iterator > 4){
4029
+ $kids.filter(':nth-child(5n+5)').addClass('ui-block-e');
3735
4030
  }
4031
+
3736
4032
  });
3737
4033
  };
3738
4034
  })(jQuery);
3739
4035
 
3740
- /*
3741
- * jQuery Mobile Framework : "fieldcontain" plugin - simple class additions to make form row separators
3742
- * Copyright (c) jQuery Project
3743
- * Dual licensed under the MIT or GPL Version 2 licenses.
3744
- * http://jquery.org/license
3745
- */
3746
- (function($, undefined ) {
3747
- $.fn.fieldcontain = function(options){
3748
- return $(this).addClass('ui-field-contain ui-body ui-br');
3749
- };
3750
- })(jQuery);
4036
+
3751
4037
 
3752
4038
  /*
3753
4039
  * jQuery Mobile Framework : "listview" plugin
@@ -3878,7 +4164,7 @@ $.widget( "mobile.listview", $.mobile.widget, {
3878
4164
 
3879
4165
  item.find( "p, dl" ).addClass( "ui-li-desc" );
3880
4166
 
3881
- item.find( "img" ).addClass( "ui-li-thumb" ).each(function() {
4167
+ item.find( "li" ).find( "img:eq(0)" ).addClass( "ui-li-thumb" ).each(function() {
3882
4168
  $( this ).closest( "li" )
3883
4169
  .addClass( $(this).is( ".ui-li-icon" ) ? "ui-li-has-icon" : "ui-li-has-thumb" );
3884
4170
  });
@@ -4051,7 +4337,7 @@ $.widget( "mobile.listview", $.mobile.widget, {
4051
4337
  $( parentList.find( "ul, ol" ).toArray().reverse() ).each(function( i ) {
4052
4338
  var list = $( this ),
4053
4339
  parent = list.parent(),
4054
- title = $.trim(parent.contents()[ 0 ].nodeValue.split("\n")[0]) || parent.find('a:first').text(),
4340
+ title = $.trim(parent.contents()[ 0 ].nodeValue) || parent.find('a:first').text(),
4055
4341
  id = parentId + "&" + $.mobile.subPageUrlKey + "=" + self._idStringEscape(title + " " + i),
4056
4342
  theme = list.data( "theme" ) || o.theme,
4057
4343
  countTheme = list.data( "counttheme" ) || parentList.data( "counttheme" ) || o.countTheme,
@@ -4125,65 +4411,6 @@ $( "[data-role='listview']" ).live( "listviewcreate", function() {
4125
4411
  })( jQuery );
4126
4412
 
4127
4413
 
4128
- /*
4129
- * jQuery Mobile Framework : "dialog" plugin.
4130
- * Copyright (c) jQuery Project
4131
- * Dual licensed under the MIT (MIT-LICENSE.txt) and GPL (GPL-LICENSE.txt) licenses.
4132
- * Note: Code is in draft form and is subject to change
4133
- */
4134
- (function($, undefined ) {
4135
- $.widget( "mobile.dialog", $.mobile.widget, {
4136
- options: {},
4137
- _create: function(){
4138
- var self = this,
4139
- $el = self.element,
4140
- $prevPage = $.mobile.activePage,
4141
- $closeBtn = $('<a href="#" data-icon="delete" data-iconpos="notext">Close</a>');
4142
-
4143
- $el.delegate("a, form", "click submit", function(e){
4144
- if( e.type == "click" && ( $(e.target).closest('[data-back]')[0] || this==$closeBtn[0] ) ){
4145
- self.close();
4146
- return false;
4147
- }
4148
- //otherwise, assume we're headed somewhere new. set activepage to dialog so the transition will work
4149
- $.mobile.activePage = self.element;
4150
- });
4151
-
4152
- this.element
4153
- .bind("pageshow",function(){
4154
- return false;
4155
- })
4156
- //add ARIA role
4157
- .attr("role","dialog")
4158
- .addClass('ui-page ui-dialog ui-body-a')
4159
- .find('[data-role=header]')
4160
- .addClass('ui-corner-top ui-overlay-shadow')
4161
- .prepend( $closeBtn )
4162
- .end()
4163
- .find('.ui-content:not([class*="ui-body-"])')
4164
- .addClass('ui-body-c')
4165
- .end()
4166
- .find('.ui-content,[data-role=footer]')
4167
- .last()
4168
- .addClass('ui-corner-bottom ui-overlay-shadow');
4169
-
4170
- $(window).bind('hashchange',function(){
4171
- if( $el.is('.ui-page-active') ){
4172
- self.close();
4173
- $el.bind('pagehide',function(){
4174
- $.mobile.updateHash( $prevPage.attr('data-url'), true);
4175
- });
4176
- }
4177
- });
4178
-
4179
- },
4180
-
4181
- close: function(){
4182
- $.mobile.changePage([this.element, $.mobile.activePage], undefined, true, true );
4183
- }
4184
- });
4185
- })( jQuery );
4186
-
4187
4414
  /*
4188
4415
  * jQuery Mobile Framework : "navbar" plugin
4189
4416
  * Copyright (c) jQuery Project
@@ -4219,99 +4446,47 @@ $.widget( "mobile.navbar", $.mobile.widget, {
4219
4446
  });
4220
4447
 
4221
4448
  $navbar.delegate("a", "click",function(event){
4222
- $navbtns.removeClass("ui-btn-active");
4449
+ $navbtns.removeClass( "ui-btn-active" );
4450
+ $( this ).addClass( "ui-btn-active" );
4223
4451
  });
4224
4452
  }
4225
4453
  });
4226
4454
  })( jQuery );
4227
4455
 
4228
- /*
4229
- * jQuery Mobile Framework : plugin for creating CSS grids
4230
- * Copyright (c) jQuery Project
4231
- * Dual licensed under the MIT or GPL Version 2 licenses.
4232
- * http://jquery.org/license
4233
- */
4234
- (function($, undefined ) {
4235
- $.fn.grid = function(options){
4236
- return $(this).each(function(){
4237
- var o = $.extend({
4238
- grid: null
4239
- },options);
4240
-
4241
-
4242
- var $kids = $(this).children(),
4243
- gridCols = {a: 2, b:3, c:4, d:5},
4244
- grid = o.grid,
4245
- iterator;
4246
-
4247
- if( !grid ){
4248
- if( $kids.length <= 5 ){
4249
- for(var letter in gridCols){
4250
- if(gridCols[letter] == $kids.length){ grid = letter; }
4251
- }
4252
- }
4253
- else{
4254
- grid = 'a';
4255
- }
4256
- }
4257
- iterator = gridCols[grid];
4258
-
4259
- $(this).addClass('ui-grid-' + grid);
4260
-
4261
- $kids.filter(':nth-child(' + iterator + 'n+1)').addClass('ui-block-a');
4262
- $kids.filter(':nth-child(' + iterator + 'n+2)').addClass('ui-block-b');
4263
-
4264
- if(iterator > 2){
4265
- $kids.filter(':nth-child(3n+3)').addClass('ui-block-c');
4266
- }
4267
- if(iterator> 3){
4268
- $kids.filter(':nth-child(4n+4)').addClass('ui-block-d');
4269
- }
4270
- if(iterator > 4){
4271
- $kids.filter(':nth-child(5n+5)').addClass('ui-block-e');
4456
+ //quick & dirty theme switcher, written to potentially work as a bookmarklet
4457
+ (function($){
4458
+ $.themeswitcher = function(){
4459
+ if( $('[data-url=themeswitcher]').length ){ return; }
4460
+ var
4461
+ themesDir = '/stylesheets/compiled/jquery/mobile/',
4462
+ themes = ['default','valencia'],
4463
+ currentPage = $.mobile.activePage,
4464
+ menuPage = $( '<div data-url="themeswitcher" data-role=\'dialog\' data-theme=\'a\'>' +
4465
+ '<div data-role=\'header\' data-theme=\'b\'>' +
4466
+ '<div class=\'ui-title\'>Switch Theme:</div>'+
4467
+ '</div>'+
4468
+ '<div data-role=\'content\' data-theme=\'c\'><ul data-role=\'listview\' data-inset=\'true\'></ul></div>'+
4469
+ '</div>' )
4470
+ .appendTo( $.mobile.pageContainer ),
4471
+ menu = menuPage.find('ul');
4472
+
4473
+ //menu items
4474
+ $.each(themes, function( i ){
4475
+ $('<li><a href="#" data-rel="back">' + themes[ i ].charAt(0).toUpperCase() + themes[ i ].substr(1) + '</a></li>')
4476
+ .click(function(){
4477
+ addTheme( themes[i] );
4478
+ return false;
4479
+ })
4480
+ .appendTo(menu);
4481
+ });
4482
+
4483
+ //remover, adder
4484
+ function addTheme(theme){
4485
+ $('head').append( '<link rel=\'stylesheet\' href=\''+ themesDir + theme +'.css\' />' );
4272
4486
  }
4273
-
4274
- });
4275
- };
4276
- })(jQuery);
4277
-
4278
4487
 
4488
+ //create page, listview
4489
+ menuPage.page();
4279
4490
 
4280
- //quick & dirty theme switcher, written to potentially work as a bookmarklet
4281
- (function($){
4282
- $.themeswitcher = function(){
4283
- if( $('[data-url=themeswitcher]').length ){ return; }
4284
- var
4285
- themesDir = '/stylesheets/compiled/jquery/mobile/',
4286
- //themesDir = 'http://jquerymobile.com/test/themes/',themesDir = 'http://jquerymobile.com/test/themes/',
4287
- themes = ['default','valencia'],
4288
- currentPage = $.mobile.activePage,
4289
- menuPage = $(
4290
- '<div data-url="themeswitcher" data-role=\'dialog\' data-theme=\'a\'>' +
4291
- '<div data-role=\'header\' data-theme=\'b\'>' +
4292
- '<div class=\'ui-title\'>Switch Theme:</div>'+
4293
- '</div>'+
4294
- '<div data-role=\'content\' data-theme=\'c\'><ul data-role=\'listview\' data-inset=\'true\'></ul></div>'+
4295
- '</div>' )
4296
- .appendTo( $.mobile.pageContainer ),
4297
- menu = menuPage.find('ul');
4298
-
4299
- //menu items
4300
- $.each(themes, function( i ){
4301
- $('<li><a href=\'#\'>' + themes[ i ].charAt(0).toUpperCase() + themes[ i ].substr(1) + '</a></li>')
4302
- .click(function(){
4303
- addTheme( themes[i] );
4304
- menuPage.dialog('close');
4305
- })
4306
- .appendTo(menu);
4307
- });
4308
-
4309
- //remover, adder
4310
- function addTheme(theme){
4311
- $('head').append( '<link rel=\'stylesheet\' href=\''+ themesDir + theme +'.css\' />' );
4312
- }
4313
-
4314
- //create page, listview
4315
- menuPage.page();
4316
- };
4491
+ };
4317
4492
  })(jQuery);