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

Sign up to get free protection for your applications and to get access to all the features.
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);