jquery-mobile-rails-assets 1.4.1 → 1.4.5.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +5 -5
- data/README.md +7 -3
- data/app/assets/javascripts/jquery.mobile.js +1094 -571
- data/app/assets/stylesheets/jquery.mobile.css.scss +68 -50
- data/jquery-mobile-rails-assets.gemspec +1 -1
- data/lib/jquery-mobile-rails-assets/version.rb +1 -1
- metadata +12 -13
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: d3720f92443e18e8dc329074ff206af8ba81851a55c37e788d6718ccb19c6820
|
4
|
+
data.tar.gz: 94d2f332b90756803484e2901ddd427a1c91aefac0b517482ba70a91819854f3
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6c151d54f05af4b2c1e748647ab4235dacbe0a049cf53e32a36e4f9f23bbbc8ac7cc84ff246d2f68e58991fb011d70df3450558e80a0d9e36db2195b9f574b5d
|
7
|
+
data.tar.gz: 653c6183a311046e5e981e1accc4bd702a55bc474fec084b7a670aff88619320c21c2ce4e0bbc8500901da7869f542ffcd2baabfe1783c18a3057b12eacbe55c
|
data/README.md
CHANGED
@@ -1,4 +1,8 @@
|
|
1
|
-
#
|
1
|
+
# THIS GEM IS NOT LONGER UPDATED
|
2
|
+
|
3
|
+
Suggest you check out the [jquery_mobile_rails gem](https://rubygems.org/gems/jquery_mobile_rails) instead.
|
4
|
+
|
5
|
+
## Intro
|
2
6
|
|
3
7
|
This gem vendors the jQuery Mobile assets for Rails 3.1 and greater.
|
4
8
|
The files will be added to the asset pipeline and available for you to use.
|
@@ -15,13 +19,13 @@ In your Gemfile add:
|
|
15
19
|
gem 'jquery-mobile-rails-assets'
|
16
20
|
```
|
17
21
|
|
18
|
-
You can then include it in your app by adding the following to your javascript file:
|
22
|
+
You can then include it in your app by adding the following to your javascript application file:
|
19
23
|
|
20
24
|
```javascript
|
21
25
|
//= require jquery.mobile
|
22
26
|
```
|
23
27
|
|
24
|
-
And to the css file:
|
28
|
+
And to the css application file:
|
25
29
|
|
26
30
|
```css
|
27
31
|
*= require jquery.mobile
|
@@ -1,9 +1,9 @@
|
|
1
1
|
/*!
|
2
|
-
* jQuery Mobile 1.4.
|
3
|
-
* Git HEAD hash:
|
2
|
+
* jQuery Mobile 1.4.5
|
3
|
+
* Git HEAD hash: 68e55e78b292634d3991c795f06f5e37a512decc <> Date: Fri Oct 31 2014 17:33:30 UTC
|
4
4
|
* http://jquerymobile.com
|
5
5
|
*
|
6
|
-
* Copyright 2010, 2014 jQuery Foundation, Inc. and
|
6
|
+
* Copyright 2010, 2014 jQuery Foundation, Inc. and othercontributors
|
7
7
|
* Released under the MIT license.
|
8
8
|
* http://jquery.org/license
|
9
9
|
*
|
@@ -26,204 +26,6 @@
|
|
26
26
|
$.mobile = {};
|
27
27
|
}( jQuery ));
|
28
28
|
|
29
|
-
(function( $, window, undefined ) {
|
30
|
-
$.extend( $.mobile, {
|
31
|
-
|
32
|
-
// Version of the jQuery Mobile Framework
|
33
|
-
version: "1.4.1",
|
34
|
-
|
35
|
-
// Deprecated and no longer used in 1.4 remove in 1.5
|
36
|
-
// Define the url parameter used for referencing widget-generated sub-pages.
|
37
|
-
// Translates to example.html&ui-page=subpageIdentifier
|
38
|
-
// hash segment before &ui-page= is used to make Ajax request
|
39
|
-
subPageUrlKey: "ui-page",
|
40
|
-
|
41
|
-
hideUrlBar: true,
|
42
|
-
|
43
|
-
// Keepnative Selector
|
44
|
-
keepNative: ":jqmData(role='none'), :jqmData(role='nojs')",
|
45
|
-
|
46
|
-
// Deprecated in 1.4 remove in 1.5
|
47
|
-
// Class assigned to page currently in view, and during transitions
|
48
|
-
activePageClass: "ui-page-active",
|
49
|
-
|
50
|
-
// Deprecated in 1.4 remove in 1.5
|
51
|
-
// Class used for "active" button state, from CSS framework
|
52
|
-
activeBtnClass: "ui-btn-active",
|
53
|
-
|
54
|
-
// Deprecated in 1.4 remove in 1.5
|
55
|
-
// Class used for "focus" form element state, from CSS framework
|
56
|
-
focusClass: "ui-focus",
|
57
|
-
|
58
|
-
// Automatically handle clicks and form submissions through Ajax, when same-domain
|
59
|
-
ajaxEnabled: true,
|
60
|
-
|
61
|
-
// Automatically load and show pages based on location.hash
|
62
|
-
hashListeningEnabled: true,
|
63
|
-
|
64
|
-
// disable to prevent jquery from bothering with links
|
65
|
-
linkBindingEnabled: true,
|
66
|
-
|
67
|
-
// Set default page transition - 'none' for no transitions
|
68
|
-
defaultPageTransition: "fade",
|
69
|
-
|
70
|
-
// Set maximum window width for transitions to apply - 'false' for no limit
|
71
|
-
maxTransitionWidth: false,
|
72
|
-
|
73
|
-
// Minimum scroll distance that will be remembered when returning to a page
|
74
|
-
// Deprecated remove in 1.5
|
75
|
-
minScrollBack: 0,
|
76
|
-
|
77
|
-
// Set default dialog transition - 'none' for no transitions
|
78
|
-
defaultDialogTransition: "pop",
|
79
|
-
|
80
|
-
// Error response message - appears when an Ajax page request fails
|
81
|
-
pageLoadErrorMessage: "Error Loading Page",
|
82
|
-
|
83
|
-
// For error messages, which theme does the box uses?
|
84
|
-
pageLoadErrorMessageTheme: "a",
|
85
|
-
|
86
|
-
// replace calls to window.history.back with phonegaps navigation helper
|
87
|
-
// where it is provided on the window object
|
88
|
-
phonegapNavigationEnabled: false,
|
89
|
-
|
90
|
-
//automatically initialize the DOM when it's ready
|
91
|
-
autoInitializePage: true,
|
92
|
-
|
93
|
-
pushStateEnabled: true,
|
94
|
-
|
95
|
-
// allows users to opt in to ignoring content by marking a parent element as
|
96
|
-
// data-ignored
|
97
|
-
ignoreContentEnabled: false,
|
98
|
-
|
99
|
-
buttonMarkup: {
|
100
|
-
hoverDelay: 200
|
101
|
-
},
|
102
|
-
|
103
|
-
// disable the alteration of the dynamic base tag or links in the case
|
104
|
-
// that a dynamic base tag isn't supported
|
105
|
-
dynamicBaseEnabled: true,
|
106
|
-
|
107
|
-
// default the property to remove dependency on assignment in init module
|
108
|
-
pageContainer: $(),
|
109
|
-
|
110
|
-
//enable cross-domain page support
|
111
|
-
allowCrossDomainPages: false,
|
112
|
-
|
113
|
-
dialogHashKey: "&ui-state=dialog"
|
114
|
-
});
|
115
|
-
})( jQuery, this );
|
116
|
-
|
117
|
-
(function( $, window, undefined ) {
|
118
|
-
var nsNormalizeDict = {},
|
119
|
-
oldFind = $.find,
|
120
|
-
rbrace = /(?:\{[\s\S]*\}|\[[\s\S]*\])$/,
|
121
|
-
jqmDataRE = /:jqmData\(([^)]*)\)/g;
|
122
|
-
|
123
|
-
$.extend( $.mobile, {
|
124
|
-
|
125
|
-
// Namespace used framework-wide for data-attrs. Default is no namespace
|
126
|
-
|
127
|
-
ns: "",
|
128
|
-
|
129
|
-
// Retrieve an attribute from an element and perform some massaging of the value
|
130
|
-
|
131
|
-
getAttribute: function( element, key ) {
|
132
|
-
var data;
|
133
|
-
|
134
|
-
element = element.jquery ? element[0] : element;
|
135
|
-
|
136
|
-
if ( element && element.getAttribute ) {
|
137
|
-
data = element.getAttribute( "data-" + $.mobile.ns + key );
|
138
|
-
}
|
139
|
-
|
140
|
-
// Copied from core's src/data.js:dataAttr()
|
141
|
-
// Convert from a string to a proper data type
|
142
|
-
try {
|
143
|
-
data = data === "true" ? true :
|
144
|
-
data === "false" ? false :
|
145
|
-
data === "null" ? null :
|
146
|
-
// Only convert to a number if it doesn't change the string
|
147
|
-
+data + "" === data ? +data :
|
148
|
-
rbrace.test( data ) ? JSON.parse( data ) :
|
149
|
-
data;
|
150
|
-
} catch( err ) {}
|
151
|
-
|
152
|
-
return data;
|
153
|
-
},
|
154
|
-
|
155
|
-
// Expose our cache for testing purposes.
|
156
|
-
nsNormalizeDict: nsNormalizeDict,
|
157
|
-
|
158
|
-
// Take a data attribute property, prepend the namespace
|
159
|
-
// and then camel case the attribute string. Add the result
|
160
|
-
// to our nsNormalizeDict so we don't have to do this again.
|
161
|
-
nsNormalize: function( prop ) {
|
162
|
-
return nsNormalizeDict[ prop ] ||
|
163
|
-
( nsNormalizeDict[ prop ] = $.camelCase( $.mobile.ns + prop ) );
|
164
|
-
},
|
165
|
-
|
166
|
-
// Find the closest javascript page element to gather settings data jsperf test
|
167
|
-
// http://jsperf.com/single-complex-selector-vs-many-complex-selectors/edit
|
168
|
-
// possibly naive, but it shows that the parsing overhead for *just* the page selector vs
|
169
|
-
// the page and dialog selector is negligable. This could probably be speed up by
|
170
|
-
// doing a similar parent node traversal to the one found in the inherited theme code above
|
171
|
-
closestPageData: function( $target ) {
|
172
|
-
return $target
|
173
|
-
.closest( ":jqmData(role='page'), :jqmData(role='dialog')" )
|
174
|
-
.data( "mobile-page" );
|
175
|
-
}
|
176
|
-
|
177
|
-
});
|
178
|
-
|
179
|
-
// Mobile version of data and removeData and hasData methods
|
180
|
-
// ensures all data is set and retrieved using jQuery Mobile's data namespace
|
181
|
-
$.fn.jqmData = function( prop, value ) {
|
182
|
-
var result;
|
183
|
-
if ( typeof prop !== "undefined" ) {
|
184
|
-
if ( prop ) {
|
185
|
-
prop = $.mobile.nsNormalize( prop );
|
186
|
-
}
|
187
|
-
|
188
|
-
// undefined is permitted as an explicit input for the second param
|
189
|
-
// in this case it returns the value and does not set it to undefined
|
190
|
-
if ( arguments.length < 2 || value === undefined ) {
|
191
|
-
result = this.data( prop );
|
192
|
-
} else {
|
193
|
-
result = this.data( prop, value );
|
194
|
-
}
|
195
|
-
}
|
196
|
-
return result;
|
197
|
-
};
|
198
|
-
|
199
|
-
$.jqmData = function( elem, prop, value ) {
|
200
|
-
var result;
|
201
|
-
if ( typeof prop !== "undefined" ) {
|
202
|
-
result = $.data( elem, prop ? $.mobile.nsNormalize( prop ) : prop, value );
|
203
|
-
}
|
204
|
-
return result;
|
205
|
-
};
|
206
|
-
|
207
|
-
$.fn.jqmRemoveData = function( prop ) {
|
208
|
-
return this.removeData( $.mobile.nsNormalize( prop ) );
|
209
|
-
};
|
210
|
-
|
211
|
-
$.jqmRemoveData = function( elem, prop ) {
|
212
|
-
return $.removeData( elem, $.mobile.nsNormalize( prop ) );
|
213
|
-
};
|
214
|
-
|
215
|
-
$.find = function( selector, context, ret, extra ) {
|
216
|
-
if ( selector.indexOf( ":jqmData" ) > -1 ) {
|
217
|
-
selector = selector.replace( jqmDataRE, "[data-" + ( $.mobile.ns || "" ) + "$1]" );
|
218
|
-
}
|
219
|
-
|
220
|
-
return oldFind.call( this, selector, context, ret, extra );
|
221
|
-
};
|
222
|
-
|
223
|
-
$.extend( $.find, oldFind );
|
224
|
-
|
225
|
-
})( jQuery, this );
|
226
|
-
|
227
29
|
/*!
|
228
30
|
* jQuery UI Core c0ab71056b936627e8a7821f03c044aec6280a40
|
229
31
|
* http://jqueryui.com
|
@@ -520,6 +322,55 @@ $.ui.plugin = {
|
|
520
322
|
|
521
323
|
(function( $, window, undefined ) {
|
522
324
|
|
325
|
+
// Subtract the height of external toolbars from the page height, if the page does not have
|
326
|
+
// internal toolbars of the same type. We take care to use the widget options if we find a
|
327
|
+
// widget instance and the element's data-attributes otherwise.
|
328
|
+
var compensateToolbars = function( page, desiredHeight ) {
|
329
|
+
var pageParent = page.parent(),
|
330
|
+
toolbarsAffectingHeight = [],
|
331
|
+
|
332
|
+
// We use this function to filter fixed toolbars with option updatePagePadding set to
|
333
|
+
// true (which is the default) from our height subtraction, because fixed toolbars with
|
334
|
+
// option updatePagePadding set to true compensate for their presence by adding padding
|
335
|
+
// to the active page. We want to avoid double-counting by also subtracting their
|
336
|
+
// height from the desired page height.
|
337
|
+
noPadders = function() {
|
338
|
+
var theElement = $( this ),
|
339
|
+
widgetOptions = $.mobile.toolbar && theElement.data( "mobile-toolbar" ) ?
|
340
|
+
theElement.toolbar( "option" ) : {
|
341
|
+
position: theElement.attr( "data-" + $.mobile.ns + "position" ),
|
342
|
+
updatePagePadding: ( theElement.attr( "data-" + $.mobile.ns +
|
343
|
+
"update-page-padding" ) !== false )
|
344
|
+
};
|
345
|
+
|
346
|
+
return !( widgetOptions.position === "fixed" &&
|
347
|
+
widgetOptions.updatePagePadding === true );
|
348
|
+
},
|
349
|
+
externalHeaders = pageParent.children( ":jqmData(role='header')" ).filter( noPadders ),
|
350
|
+
internalHeaders = page.children( ":jqmData(role='header')" ),
|
351
|
+
externalFooters = pageParent.children( ":jqmData(role='footer')" ).filter( noPadders ),
|
352
|
+
internalFooters = page.children( ":jqmData(role='footer')" );
|
353
|
+
|
354
|
+
// If we have no internal headers, but we do have external headers, then their height
|
355
|
+
// reduces the page height
|
356
|
+
if ( internalHeaders.length === 0 && externalHeaders.length > 0 ) {
|
357
|
+
toolbarsAffectingHeight = toolbarsAffectingHeight.concat( externalHeaders.toArray() );
|
358
|
+
}
|
359
|
+
|
360
|
+
// If we have no internal footers, but we do have external footers, then their height
|
361
|
+
// reduces the page height
|
362
|
+
if ( internalFooters.length === 0 && externalFooters.length > 0 ) {
|
363
|
+
toolbarsAffectingHeight = toolbarsAffectingHeight.concat( externalFooters.toArray() );
|
364
|
+
}
|
365
|
+
|
366
|
+
$.each( toolbarsAffectingHeight, function( index, value ) {
|
367
|
+
desiredHeight -= $( value ).outerHeight();
|
368
|
+
});
|
369
|
+
|
370
|
+
// Height must be at least zero
|
371
|
+
return Math.max( 0, desiredHeight );
|
372
|
+
};
|
373
|
+
|
523
374
|
$.extend( $.mobile, {
|
524
375
|
// define the window and the document objects
|
525
376
|
window: $( window ),
|
@@ -650,9 +501,16 @@ $.ui.plugin = {
|
|
650
501
|
pageHeight = page.height(),
|
651
502
|
pageOuterHeight = page.outerHeight( true );
|
652
503
|
|
653
|
-
height = (
|
504
|
+
height = compensateToolbars( page,
|
505
|
+
( typeof height === "number" ) ? height : $.mobile.getScreenHeight() );
|
506
|
+
|
507
|
+
// Remove any previous min-height setting
|
508
|
+
page.css( "min-height", "" );
|
654
509
|
|
655
|
-
|
510
|
+
// Set the minimum height only if the height as determined by CSS is insufficient
|
511
|
+
if ( page.height() < height ) {
|
512
|
+
page.css( "min-height", height - ( pageOuterHeight - pageHeight ) );
|
513
|
+
}
|
656
514
|
},
|
657
515
|
|
658
516
|
loading: function() {
|
@@ -791,6 +649,93 @@ $.ui.plugin = {
|
|
791
649
|
|
792
650
|
})( jQuery, this );
|
793
651
|
|
652
|
+
(function( $, window, undefined ) {
|
653
|
+
$.extend( $.mobile, {
|
654
|
+
|
655
|
+
// Version of the jQuery Mobile Framework
|
656
|
+
version: "1.4.5",
|
657
|
+
|
658
|
+
// Deprecated and no longer used in 1.4 remove in 1.5
|
659
|
+
// Define the url parameter used for referencing widget-generated sub-pages.
|
660
|
+
// Translates to example.html&ui-page=subpageIdentifier
|
661
|
+
// hash segment before &ui-page= is used to make Ajax request
|
662
|
+
subPageUrlKey: "ui-page",
|
663
|
+
|
664
|
+
hideUrlBar: true,
|
665
|
+
|
666
|
+
// Keepnative Selector
|
667
|
+
keepNative: ":jqmData(role='none'), :jqmData(role='nojs')",
|
668
|
+
|
669
|
+
// Deprecated in 1.4 remove in 1.5
|
670
|
+
// Class assigned to page currently in view, and during transitions
|
671
|
+
activePageClass: "ui-page-active",
|
672
|
+
|
673
|
+
// Deprecated in 1.4 remove in 1.5
|
674
|
+
// Class used for "active" button state, from CSS framework
|
675
|
+
activeBtnClass: "ui-btn-active",
|
676
|
+
|
677
|
+
// Deprecated in 1.4 remove in 1.5
|
678
|
+
// Class used for "focus" form element state, from CSS framework
|
679
|
+
focusClass: "ui-focus",
|
680
|
+
|
681
|
+
// Automatically handle clicks and form submissions through Ajax, when same-domain
|
682
|
+
ajaxEnabled: true,
|
683
|
+
|
684
|
+
// Automatically load and show pages based on location.hash
|
685
|
+
hashListeningEnabled: true,
|
686
|
+
|
687
|
+
// disable to prevent jquery from bothering with links
|
688
|
+
linkBindingEnabled: true,
|
689
|
+
|
690
|
+
// Set default page transition - 'none' for no transitions
|
691
|
+
defaultPageTransition: "fade",
|
692
|
+
|
693
|
+
// Set maximum window width for transitions to apply - 'false' for no limit
|
694
|
+
maxTransitionWidth: false,
|
695
|
+
|
696
|
+
// Minimum scroll distance that will be remembered when returning to a page
|
697
|
+
// Deprecated remove in 1.5
|
698
|
+
minScrollBack: 0,
|
699
|
+
|
700
|
+
// Set default dialog transition - 'none' for no transitions
|
701
|
+
defaultDialogTransition: "pop",
|
702
|
+
|
703
|
+
// Error response message - appears when an Ajax page request fails
|
704
|
+
pageLoadErrorMessage: "Error Loading Page",
|
705
|
+
|
706
|
+
// For error messages, which theme does the box use?
|
707
|
+
pageLoadErrorMessageTheme: "a",
|
708
|
+
|
709
|
+
// replace calls to window.history.back with phonegaps navigation helper
|
710
|
+
// where it is provided on the window object
|
711
|
+
phonegapNavigationEnabled: false,
|
712
|
+
|
713
|
+
//automatically initialize the DOM when it's ready
|
714
|
+
autoInitializePage: true,
|
715
|
+
|
716
|
+
pushStateEnabled: true,
|
717
|
+
|
718
|
+
// allows users to opt in to ignoring content by marking a parent element as
|
719
|
+
// data-ignored
|
720
|
+
ignoreContentEnabled: false,
|
721
|
+
|
722
|
+
buttonMarkup: {
|
723
|
+
hoverDelay: 200
|
724
|
+
},
|
725
|
+
|
726
|
+
// disable the alteration of the dynamic base tag or links in the case
|
727
|
+
// that a dynamic base tag isn't supported
|
728
|
+
dynamicBaseEnabled: true,
|
729
|
+
|
730
|
+
// default the property to remove dependency on assignment in init module
|
731
|
+
pageContainer: $(),
|
732
|
+
|
733
|
+
//enable cross-domain page support
|
734
|
+
allowCrossDomainPages: false,
|
735
|
+
|
736
|
+
dialogHashKey: "&ui-state=dialog"
|
737
|
+
});
|
738
|
+
})( jQuery, this );
|
794
739
|
|
795
740
|
/*!
|
796
741
|
* jQuery UI Widget c0ab71056b936627e8a7821f03c044aec6280a40
|
@@ -1316,6 +1261,116 @@ $.each( { show: "fadeIn", hide: "fadeOut" }, function( method, defaultEffect ) {
|
|
1316
1261
|
|
1317
1262
|
})( jQuery );
|
1318
1263
|
|
1264
|
+
(function( $, window, undefined ) {
|
1265
|
+
var nsNormalizeDict = {},
|
1266
|
+
oldFind = $.find,
|
1267
|
+
rbrace = /(?:\{[\s\S]*\}|\[[\s\S]*\])$/,
|
1268
|
+
jqmDataRE = /:jqmData\(([^)]*)\)/g;
|
1269
|
+
|
1270
|
+
$.extend( $.mobile, {
|
1271
|
+
|
1272
|
+
// Namespace used framework-wide for data-attrs. Default is no namespace
|
1273
|
+
|
1274
|
+
ns: "",
|
1275
|
+
|
1276
|
+
// Retrieve an attribute from an element and perform some massaging of the value
|
1277
|
+
|
1278
|
+
getAttribute: function( element, key ) {
|
1279
|
+
var data;
|
1280
|
+
|
1281
|
+
element = element.jquery ? element[0] : element;
|
1282
|
+
|
1283
|
+
if ( element && element.getAttribute ) {
|
1284
|
+
data = element.getAttribute( "data-" + $.mobile.ns + key );
|
1285
|
+
}
|
1286
|
+
|
1287
|
+
// Copied from core's src/data.js:dataAttr()
|
1288
|
+
// Convert from a string to a proper data type
|
1289
|
+
try {
|
1290
|
+
data = data === "true" ? true :
|
1291
|
+
data === "false" ? false :
|
1292
|
+
data === "null" ? null :
|
1293
|
+
// Only convert to a number if it doesn't change the string
|
1294
|
+
+data + "" === data ? +data :
|
1295
|
+
rbrace.test( data ) ? JSON.parse( data ) :
|
1296
|
+
data;
|
1297
|
+
} catch( err ) {}
|
1298
|
+
|
1299
|
+
return data;
|
1300
|
+
},
|
1301
|
+
|
1302
|
+
// Expose our cache for testing purposes.
|
1303
|
+
nsNormalizeDict: nsNormalizeDict,
|
1304
|
+
|
1305
|
+
// Take a data attribute property, prepend the namespace
|
1306
|
+
// and then camel case the attribute string. Add the result
|
1307
|
+
// to our nsNormalizeDict so we don't have to do this again.
|
1308
|
+
nsNormalize: function( prop ) {
|
1309
|
+
return nsNormalizeDict[ prop ] ||
|
1310
|
+
( nsNormalizeDict[ prop ] = $.camelCase( $.mobile.ns + prop ) );
|
1311
|
+
},
|
1312
|
+
|
1313
|
+
// Find the closest javascript page element to gather settings data jsperf test
|
1314
|
+
// http://jsperf.com/single-complex-selector-vs-many-complex-selectors/edit
|
1315
|
+
// possibly naive, but it shows that the parsing overhead for *just* the page selector vs
|
1316
|
+
// the page and dialog selector is negligable. This could probably be speed up by
|
1317
|
+
// doing a similar parent node traversal to the one found in the inherited theme code above
|
1318
|
+
closestPageData: function( $target ) {
|
1319
|
+
return $target
|
1320
|
+
.closest( ":jqmData(role='page'), :jqmData(role='dialog')" )
|
1321
|
+
.data( "mobile-page" );
|
1322
|
+
}
|
1323
|
+
|
1324
|
+
});
|
1325
|
+
|
1326
|
+
// Mobile version of data and removeData and hasData methods
|
1327
|
+
// ensures all data is set and retrieved using jQuery Mobile's data namespace
|
1328
|
+
$.fn.jqmData = function( prop, value ) {
|
1329
|
+
var result;
|
1330
|
+
if ( typeof prop !== "undefined" ) {
|
1331
|
+
if ( prop ) {
|
1332
|
+
prop = $.mobile.nsNormalize( prop );
|
1333
|
+
}
|
1334
|
+
|
1335
|
+
// undefined is permitted as an explicit input for the second param
|
1336
|
+
// in this case it returns the value and does not set it to undefined
|
1337
|
+
if ( arguments.length < 2 || value === undefined ) {
|
1338
|
+
result = this.data( prop );
|
1339
|
+
} else {
|
1340
|
+
result = this.data( prop, value );
|
1341
|
+
}
|
1342
|
+
}
|
1343
|
+
return result;
|
1344
|
+
};
|
1345
|
+
|
1346
|
+
$.jqmData = function( elem, prop, value ) {
|
1347
|
+
var result;
|
1348
|
+
if ( typeof prop !== "undefined" ) {
|
1349
|
+
result = $.data( elem, prop ? $.mobile.nsNormalize( prop ) : prop, value );
|
1350
|
+
}
|
1351
|
+
return result;
|
1352
|
+
};
|
1353
|
+
|
1354
|
+
$.fn.jqmRemoveData = function( prop ) {
|
1355
|
+
return this.removeData( $.mobile.nsNormalize( prop ) );
|
1356
|
+
};
|
1357
|
+
|
1358
|
+
$.jqmRemoveData = function( elem, prop ) {
|
1359
|
+
return $.removeData( elem, $.mobile.nsNormalize( prop ) );
|
1360
|
+
};
|
1361
|
+
|
1362
|
+
$.find = function( selector, context, ret, extra ) {
|
1363
|
+
if ( selector.indexOf( ":jqmData" ) > -1 ) {
|
1364
|
+
selector = selector.replace( jqmDataRE, "[data-" + ( $.mobile.ns || "" ) + "$1]" );
|
1365
|
+
}
|
1366
|
+
|
1367
|
+
return oldFind.call( this, selector, context, ret, extra );
|
1368
|
+
};
|
1369
|
+
|
1370
|
+
$.extend( $.find, oldFind );
|
1371
|
+
|
1372
|
+
})( jQuery, this );
|
1373
|
+
|
1319
1374
|
(function( $, undefined ) {
|
1320
1375
|
|
1321
1376
|
var rcapitals = /[A-Z]/g,
|
@@ -1458,8 +1513,11 @@ $.mobile.widget = $.Widget;
|
|
1458
1513
|
this.element.find( "h1" ).text( message );
|
1459
1514
|
}
|
1460
1515
|
|
1461
|
-
//
|
1462
|
-
|
1516
|
+
// If the pagecontainer widget has been defined we may use the :mobile-pagecontainer
|
1517
|
+
// and attach to the element on which the pagecontainer widget has been defined. If not,
|
1518
|
+
// we attach to the body.
|
1519
|
+
this.element.appendTo( $.mobile.pagecontainer ?
|
1520
|
+
$( ":mobile-pagecontainer" ) : $( "body" ) );
|
1463
1521
|
|
1464
1522
|
// check that the loader is visible
|
1465
1523
|
this.checkLoaderPosition();
|
@@ -1475,8 +1533,8 @@ $.mobile.widget = $.Widget;
|
|
1475
1533
|
this.element.removeClass( "ui-loader-fakefix" );
|
1476
1534
|
}
|
1477
1535
|
|
1478
|
-
|
1479
|
-
|
1536
|
+
this.window.unbind( "scroll", this.fakeFixLoader );
|
1537
|
+
this.window.unbind( "scroll", this.checkLoaderPosition );
|
1480
1538
|
}
|
1481
1539
|
});
|
1482
1540
|
|
@@ -1855,7 +1913,7 @@ $.mobile.widget = $.Widget;
|
|
1855
1913
|
iframe_doc.open();
|
1856
1914
|
|
1857
1915
|
// Set document.domain for the Iframe document as well, if necessary.
|
1858
|
-
domain && iframe_doc.write( '
|
1916
|
+
domain && iframe_doc.write( '\x3cscript>document.domain="' + domain + '"\x3c/script>' );
|
1859
1917
|
|
1860
1918
|
iframe_doc.close();
|
1861
1919
|
|
@@ -1874,6 +1932,7 @@ $.mobile.widget = $.Widget;
|
|
1874
1932
|
|
1875
1933
|
})(jQuery,this);
|
1876
1934
|
|
1935
|
+
|
1877
1936
|
(function( $, undefined ) {
|
1878
1937
|
|
1879
1938
|
/*! matchMedia() polyfill - Test a CSS media type/query in JS. Authors & copyright (c) 2012: Scott Jehl, Paul Irish, Nicholas Zakas. Dual MIT/BSD license */
|
@@ -2326,19 +2385,34 @@ if ( !$.support.boxShadow ) {
|
|
2326
2385
|
urlParseRE: /^\s*(((([^:\/#\?]+:)?(?:(\/\/)((?:(([^:@\/#\?]+)(?:\:([^:@\/#\?]+))?)@)?(([^:\/#\?\]\[]+|\[[^\/\]@#?]+\])(?:\:([0-9]+))?))?)?)?((\/?(?:[^\/\?#]+\/+)*)([^\?#]*)))?(\?[^#]+)?)(#.*)?/,
|
2327
2386
|
|
2328
2387
|
// Abstraction to address xss (Issue #4787) by removing the authority in
|
2329
|
-
// browsers that auto
|
2388
|
+
// browsers that auto-decode it. All references to location.href should be
|
2330
2389
|
// replaced with a call to this method so that it can be dealt with properly here
|
2331
2390
|
getLocation: function( url ) {
|
2332
|
-
var
|
2333
|
-
|
2391
|
+
var parsedUrl = this.parseUrl( url || location.href ),
|
2392
|
+
uri = url ? parsedUrl : location,
|
2393
|
+
|
2394
|
+
// Make sure to parse the url or the location object for the hash because using
|
2395
|
+
// location.hash is autodecoded in firefox, the rest of the url should be from
|
2396
|
+
// the object (location unless we're testing) to avoid the inclusion of the
|
2397
|
+
// authority
|
2398
|
+
hash = parsedUrl.hash;
|
2334
2399
|
|
2335
2400
|
// mimic the browser with an empty string when the hash is empty
|
2336
2401
|
hash = hash === "#" ? "" : hash;
|
2337
2402
|
|
2338
|
-
|
2339
|
-
|
2340
|
-
|
2341
|
-
|
2403
|
+
return uri.protocol +
|
2404
|
+
parsedUrl.doubleSlash +
|
2405
|
+
uri.host +
|
2406
|
+
|
2407
|
+
// The pathname must start with a slash if there's a protocol, because you
|
2408
|
+
// can't have a protocol followed by a relative path. Also, it's impossible to
|
2409
|
+
// calculate absolute URLs from relative ones if the absolute one doesn't have
|
2410
|
+
// a leading "/".
|
2411
|
+
( ( uri.protocol !== "" && uri.pathname.substring( 0, 1 ) !== "/" ) ?
|
2412
|
+
"/" : "" ) +
|
2413
|
+
uri.pathname +
|
2414
|
+
uri.search +
|
2415
|
+
hash;
|
2342
2416
|
},
|
2343
2417
|
|
2344
2418
|
//return the original document url
|
@@ -2424,7 +2498,8 @@ if ( !$.support.boxShadow ) {
|
|
2424
2498
|
|
2425
2499
|
//Returns true if both urls have the same domain.
|
2426
2500
|
isSameDomain: function( absUrl1, absUrl2 ) {
|
2427
|
-
return path.parseUrl( absUrl1 ).domain
|
2501
|
+
return path.parseUrl( absUrl1 ).domain.toLowerCase() ===
|
2502
|
+
path.parseUrl( absUrl2 ).domain.toLowerCase();
|
2428
2503
|
},
|
2429
2504
|
|
2430
2505
|
//Returns true for any relative variant.
|
@@ -2471,19 +2546,21 @@ if ( !$.support.boxShadow ) {
|
|
2471
2546
|
},
|
2472
2547
|
|
2473
2548
|
convertUrlToDataUrl: function( absUrl ) {
|
2474
|
-
var
|
2549
|
+
var result = absUrl,
|
2550
|
+
u = path.parseUrl( absUrl );
|
2551
|
+
|
2475
2552
|
if ( path.isEmbeddedPage( u ) ) {
|
2476
2553
|
// For embedded pages, remove the dialog hash key as in getFilePath(),
|
2477
2554
|
// and remove otherwise the Data Url won't match the id of the embedded Page.
|
2478
|
-
|
2555
|
+
result = u.hash
|
2479
2556
|
.split( dialogHashKey )[0]
|
2480
2557
|
.replace( /^#/, "" )
|
2481
2558
|
.replace( /\?.*$/, "" );
|
2482
2559
|
} else if ( path.isSameDomain( u, this.documentBase ) ) {
|
2483
|
-
|
2560
|
+
result = u.hrefNoHash.replace( this.documentBase.domain, "" ).split( dialogHashKey )[0];
|
2484
2561
|
}
|
2485
2562
|
|
2486
|
-
return window.decodeURIComponent(
|
2563
|
+
return window.decodeURIComponent( result );
|
2487
2564
|
},
|
2488
2565
|
|
2489
2566
|
//get path from current hash, or from a file path
|
@@ -2532,7 +2609,9 @@ if ( !$.support.boxShadow ) {
|
|
2532
2609
|
//could be mailto, etc
|
2533
2610
|
isExternal: function( url ) {
|
2534
2611
|
var u = path.parseUrl( url );
|
2535
|
-
|
2612
|
+
|
2613
|
+
return !!( u.protocol &&
|
2614
|
+
( u.domain.toLowerCase() !== this.documentUrl.domain.toLowerCase() ) );
|
2536
2615
|
},
|
2537
2616
|
|
2538
2617
|
hasProtocol: function( url ) {
|
@@ -2554,14 +2633,25 @@ if ( !$.support.boxShadow ) {
|
|
2554
2633
|
},
|
2555
2634
|
|
2556
2635
|
squash: function( url, resolutionUrl ) {
|
2557
|
-
var href, cleanedUrl, search, stateIndex,
|
2636
|
+
var href, cleanedUrl, search, stateIndex, docUrl,
|
2558
2637
|
isPath = this.isPath( url ),
|
2559
2638
|
uri = this.parseUrl( url ),
|
2560
2639
|
preservedHash = uri.hash,
|
2561
2640
|
uiState = "";
|
2562
2641
|
|
2563
|
-
// produce a url against which we can
|
2564
|
-
|
2642
|
+
// produce a url against which we can resolve the provided path
|
2643
|
+
if ( !resolutionUrl ) {
|
2644
|
+
if ( isPath ) {
|
2645
|
+
resolutionUrl = path.getLocation();
|
2646
|
+
} else {
|
2647
|
+
docUrl = path.getDocumentUrl( true );
|
2648
|
+
if ( path.isPath( docUrl.hash ) ) {
|
2649
|
+
resolutionUrl = path.squash( docUrl.href );
|
2650
|
+
} else {
|
2651
|
+
resolutionUrl = docUrl.href;
|
2652
|
+
}
|
2653
|
+
}
|
2654
|
+
}
|
2565
2655
|
|
2566
2656
|
// If the url is anything but a simple string, remove any preceding hash
|
2567
2657
|
// eg #foo/bar -> foo/bar
|
@@ -2608,7 +2698,8 @@ if ( !$.support.boxShadow ) {
|
|
2608
2698
|
|
2609
2699
|
// reconstruct each of the pieces with the new search string and hash
|
2610
2700
|
href = path.parseUrl( href );
|
2611
|
-
href = href.protocol +
|
2701
|
+
href = href.protocol + href.doubleSlash + href.host + href.pathname + search +
|
2702
|
+
preservedHash;
|
2612
2703
|
} else {
|
2613
2704
|
href += href.indexOf( "#" ) > -1 ? uiState : "#" + uiState;
|
2614
2705
|
}
|
@@ -2629,11 +2720,10 @@ if ( !$.support.boxShadow ) {
|
|
2629
2720
|
return ( hasHash ? "#" : "" ) + hash.replace( /([!"#$%&'()*+,./:;<=>?@[\]^`{|}~])/g, "\\$1" );
|
2630
2721
|
},
|
2631
2722
|
|
2632
|
-
// return the substring of a filepath before the
|
2633
|
-
//
|
2723
|
+
// return the substring of a filepath before the dialogHashKey, for making a server
|
2724
|
+
// request
|
2634
2725
|
getFilePath: function( path ) {
|
2635
|
-
|
2636
|
-
return path && path.split( splitkey )[0].split( dialogHashKey )[0];
|
2726
|
+
return path && path.split( dialogHashKey )[0];
|
2637
2727
|
},
|
2638
2728
|
|
2639
2729
|
// check if the specified url refers to the first page in the main
|
@@ -3155,7 +3245,6 @@ if ( !$.support.boxShadow ) {
|
|
3155
3245
|
|
3156
3246
|
// All lower case if not a vendor prop
|
3157
3247
|
if ( props[ test ][ "prefix" ] === "" ) {
|
3158
|
-
props[ test ][ "duration" ] = props[ test ][ "duration" ].toLowerCase();
|
3159
3248
|
props[ test ][ "event" ] = props[ test ][ "event" ].toLowerCase();
|
3160
3249
|
}
|
3161
3250
|
});
|
@@ -3171,6 +3260,12 @@ if ( !$.support.boxShadow ) {
|
|
3171
3260
|
$.fn.animationComplete = function( callback, type, fallbackTime ) {
|
3172
3261
|
var timer, duration,
|
3173
3262
|
that = this,
|
3263
|
+
eventBinding = function() {
|
3264
|
+
|
3265
|
+
// Clear the timer so we don't call callback twice
|
3266
|
+
clearTimeout( timer );
|
3267
|
+
callback.apply( this, arguments );
|
3268
|
+
},
|
3174
3269
|
animationType = ( !type || type === "animation" ) ? "animation" : "transition";
|
3175
3270
|
|
3176
3271
|
// Make sure selected type is supported by browser
|
@@ -3191,24 +3286,19 @@ if ( !$.support.boxShadow ) {
|
|
3191
3286
|
}
|
3192
3287
|
|
3193
3288
|
// If we could not read a duration use the default
|
3194
|
-
if ( duration === 0 || duration === undefined ) {
|
3195
|
-
duration = $.fn.animationComplete.
|
3289
|
+
if ( duration === 0 || duration === undefined || isNaN( duration ) ) {
|
3290
|
+
duration = $.fn.animationComplete.defaultDuration;
|
3196
3291
|
}
|
3197
3292
|
}
|
3198
3293
|
|
3199
3294
|
// Sets up the fallback if event never comes
|
3200
3295
|
timer = setTimeout( function() {
|
3201
|
-
$( that ).off( props[ animationType ].event );
|
3296
|
+
$( that ).off( props[ animationType ].event, eventBinding );
|
3202
3297
|
callback.apply( that );
|
3203
3298
|
}, duration );
|
3204
3299
|
|
3205
3300
|
// Bind the event
|
3206
|
-
return $( this ).one( props[ animationType ].event,
|
3207
|
-
|
3208
|
-
// Clear the timer so we dont call callback twice
|
3209
|
-
clearTimeout( timer );
|
3210
|
-
callback.call( this, arguments );
|
3211
|
-
});
|
3301
|
+
return $( this ).one( props[ animationType ].event, eventBinding );
|
3212
3302
|
} else {
|
3213
3303
|
|
3214
3304
|
// CSS animation / transitions not supported
|
@@ -3219,7 +3309,7 @@ if ( !$.support.boxShadow ) {
|
|
3219
3309
|
};
|
3220
3310
|
|
3221
3311
|
// Allow default callback to be configured on mobileInit
|
3222
|
-
$.fn.animationComplete.
|
3312
|
+
$.fn.animationComplete.defaultDuration = 1000;
|
3223
3313
|
})( jQuery );
|
3224
3314
|
|
3225
3315
|
// This plugin is an experiment for abstracting away the touch and mouse
|
@@ -3837,7 +3927,7 @@ if ( eventCaptureSupported ) {
|
|
3837
3927
|
if ( !isTaphold && origTarget === event.target ) {
|
3838
3928
|
triggerCustomEvent( thisObject, "tap", event );
|
3839
3929
|
} else if ( isTaphold ) {
|
3840
|
-
event.
|
3930
|
+
event.preventDefault();
|
3841
3931
|
}
|
3842
3932
|
}
|
3843
3933
|
|
@@ -3970,7 +4060,7 @@ if ( eventCaptureSupported ) {
|
|
3970
4060
|
emitted = false;
|
3971
4061
|
|
3972
4062
|
context.move = function( event ) {
|
3973
|
-
if ( !start ) {
|
4063
|
+
if ( !start || event.isDefaultPrevented() ) {
|
3974
4064
|
return;
|
3975
4065
|
}
|
3976
4066
|
|
@@ -4033,8 +4123,8 @@ if ( eventCaptureSupported ) {
|
|
4033
4123
|
$.each({
|
4034
4124
|
scrollstop: "scrollstart",
|
4035
4125
|
taphold: "tap",
|
4036
|
-
swipeleft: "swipe",
|
4037
|
-
swiperight: "swipe"
|
4126
|
+
swipeleft: "swipe.left",
|
4127
|
+
swiperight: "swipe.right"
|
4038
4128
|
}, function( event, sourceEvent ) {
|
4039
4129
|
|
4040
4130
|
$.event.special[ event ] = {
|
@@ -4270,13 +4360,14 @@ if ( eventCaptureSupported ) {
|
|
4270
4360
|
page.find( base.linkSelector ).each(function( i, link ) {
|
4271
4361
|
var thisAttr = $( link ).is( "[href]" ) ? "href" :
|
4272
4362
|
$( link ).is( "[src]" ) ? "src" : "action",
|
4363
|
+
theLocation = $.mobile.path.parseLocation(),
|
4273
4364
|
thisUrl = $( link ).attr( thisAttr );
|
4274
4365
|
|
4275
4366
|
// XXX_jblas: We need to fix this so that it removes the document
|
4276
4367
|
// base URL, and then prepends with the new page URL.
|
4277
4368
|
// if full path exists and is same, chop it - helps IE out
|
4278
|
-
thisUrl = thisUrl.replace(
|
4279
|
-
|
4369
|
+
thisUrl = thisUrl.replace( theLocation.protocol + theLocation.doubleSlash +
|
4370
|
+
theLocation.host + theLocation.pathname, "" );
|
4280
4371
|
|
4281
4372
|
if ( !/^(\w+:|#|\/)/.test( thisUrl ) ) {
|
4282
4373
|
$( link ).attr( thisAttr, newPath + thisUrl );
|
@@ -4476,13 +4567,9 @@ $.widget( "mobile.page", {
|
|
4476
4567
|
initSelector: false,
|
4477
4568
|
|
4478
4569
|
_create: function() {
|
4570
|
+
this._trigger( "beforecreate" );
|
4479
4571
|
this.setLastScrollEnabled = true;
|
4480
4572
|
|
4481
|
-
// TODO consider moving the navigation handler OUT of widget into
|
4482
|
-
// some other object as glue between the navigate event and the
|
4483
|
-
// content widget load and change methods
|
4484
|
-
this._on( this.window, { navigate: "_filterNavigateEvents" });
|
4485
|
-
|
4486
4573
|
this._on( this.window, {
|
4487
4574
|
// disable an scroll setting when a hashchange has been fired,
|
4488
4575
|
// this only works because the recording of the scroll position
|
@@ -4495,6 +4582,11 @@ $.widget( "mobile.page", {
|
|
4495
4582
|
scrollstop: "_delayedRecordScroll"
|
4496
4583
|
});
|
4497
4584
|
|
4585
|
+
// TODO consider moving the navigation handler OUT of widget into
|
4586
|
+
// some other object as glue between the navigate event and the
|
4587
|
+
// content widget load and change methods
|
4588
|
+
this._on( this.window, { navigate: "_filterNavigateEvents" });
|
4589
|
+
|
4498
4590
|
// TODO move from page* events to content* events
|
4499
4591
|
this._on({ pagechange: "_afterContentChange" });
|
4500
4592
|
|
@@ -4615,9 +4707,8 @@ $.widget( "mobile.page", {
|
|
4615
4707
|
return $.mobile.navigate.history;
|
4616
4708
|
},
|
4617
4709
|
|
4618
|
-
// TODO use _getHistory
|
4619
4710
|
_getActiveHistory: function() {
|
4620
|
-
return
|
4711
|
+
return this._getHistory().getActive();
|
4621
4712
|
},
|
4622
4713
|
|
4623
4714
|
// TODO the document base should be determined at creation
|
@@ -4677,28 +4768,26 @@ $.widget( "mobile.page", {
|
|
4677
4768
|
//
|
4678
4769
|
// TODO move check to history object or path object?
|
4679
4770
|
to = !$.mobile.path.isPath( to ) ? ( $.mobile.path.makeUrlAbsolute( "#" + to, this._getDocumentBase() ) ) : to;
|
4680
|
-
|
4681
|
-
// If we're about to go to an initial URL that contains a
|
4682
|
-
// reference to a non-existent internal page, go to the first
|
4683
|
-
// page instead. We know that the initial hash refers to a
|
4684
|
-
// non-existent page, because the initial hash did not end
|
4685
|
-
// up in the initial history entry
|
4686
|
-
// TODO move check to history object?
|
4687
|
-
if ( to === $.mobile.path.makeUrlAbsolute( "#" + history.initialDst, this._getDocumentBase() ) &&
|
4688
|
-
history.stack.length &&
|
4689
|
-
history.stack[0].url !== history.initialDst.replace( $.mobile.dialogHashKey, "" ) ) {
|
4690
|
-
to = this._getInitialContent();
|
4691
|
-
}
|
4692
4771
|
}
|
4693
4772
|
return to || this._getInitialContent();
|
4694
4773
|
},
|
4695
4774
|
|
4775
|
+
_transitionFromHistory: function( direction, defaultTransition ) {
|
4776
|
+
var history = this._getHistory(),
|
4777
|
+
entry = ( direction === "back" ? history.getLast() : history.getActive() );
|
4778
|
+
|
4779
|
+
return ( entry && entry.transition ) || defaultTransition;
|
4780
|
+
},
|
4781
|
+
|
4696
4782
|
_handleDialog: function( changePageOptions, data ) {
|
4697
4783
|
var to, active, activeContent = this.getActivePage();
|
4698
4784
|
|
4699
4785
|
// If current active page is not a dialog skip the dialog and continue
|
4700
4786
|
// in the same direction
|
4701
|
-
|
4787
|
+
// Note: The dialog widget is deprecated as of 1.4.0 and will be removed in 1.5.0.
|
4788
|
+
// Thus, as of 1.5.0 activeContent.data( "mobile-dialog" ) will always evaluate to
|
4789
|
+
// falsy, so the second condition in the if-statement below can be removed altogether.
|
4790
|
+
if ( activeContent && !activeContent.data( "mobile-dialog" ) ) {
|
4702
4791
|
// determine if we're heading forward or backward and continue
|
4703
4792
|
// accordingly past the current dialog
|
4704
4793
|
if ( data.direction === "back" ) {
|
@@ -4719,7 +4808,9 @@ $.widget( "mobile.page", {
|
|
4719
4808
|
// as most of this is lost by the domCache cleaning
|
4720
4809
|
$.extend( changePageOptions, {
|
4721
4810
|
role: active.role,
|
4722
|
-
transition:
|
4811
|
+
transition: this._transitionFromHistory(
|
4812
|
+
data.direction,
|
4813
|
+
changePageOptions.transition ),
|
4723
4814
|
reverse: data.direction === "back"
|
4724
4815
|
});
|
4725
4816
|
}
|
@@ -4734,7 +4825,8 @@ $.widget( "mobile.page", {
|
|
4734
4825
|
|
4735
4826
|
// transition is false if it's the first page, undefined
|
4736
4827
|
// otherwise (and may be overridden by default)
|
4737
|
-
transition = history.stack.length === 0 ? "none" :
|
4828
|
+
transition = history.stack.length === 0 ? "none" :
|
4829
|
+
this._transitionFromHistory( data.direction ),
|
4738
4830
|
|
4739
4831
|
// default options for the changPage calls made after examining
|
4740
4832
|
// the current state of the page and the hash, NOTE that the
|
@@ -4746,7 +4838,7 @@ $.widget( "mobile.page", {
|
|
4746
4838
|
};
|
4747
4839
|
|
4748
4840
|
$.extend( changePageOptions, data, {
|
4749
|
-
transition:
|
4841
|
+
transition: transition
|
4750
4842
|
});
|
4751
4843
|
|
4752
4844
|
// TODO move to _handleDestination ?
|
@@ -4754,8 +4846,7 @@ $.widget( "mobile.page", {
|
|
4754
4846
|
// key, and the initial destination isn't equal to the current target
|
4755
4847
|
// page, use the special dialog handling
|
4756
4848
|
if ( history.activeIndex > 0 &&
|
4757
|
-
to.indexOf( $.mobile.dialogHashKey ) > -1
|
4758
|
-
history.initialDst !== to ) {
|
4849
|
+
to.indexOf( $.mobile.dialogHashKey ) > -1 ) {
|
4759
4850
|
|
4760
4851
|
to = this._handleDialog( changePageOptions, data );
|
4761
4852
|
|
@@ -4806,7 +4897,8 @@ $.widget( "mobile.page", {
|
|
4806
4897
|
// NOTE do _not_ use the :jqmData pseudo selector because parenthesis
|
4807
4898
|
// are a valid url char and it breaks on the first occurence
|
4808
4899
|
page = this.element
|
4809
|
-
.children( "[data-" + this._getNs() +
|
4900
|
+
.children( "[data-" + this._getNs() +
|
4901
|
+
"url='" + $.mobile.path.hashToSelector( dataUrl ) + "']" );
|
4810
4902
|
|
4811
4903
|
// If we failed to find the page, check to see if the url is a
|
4812
4904
|
// reference to an embedded page. If so, it may have been dynamically
|
@@ -4891,7 +4983,7 @@ $.widget( "mobile.page", {
|
|
4891
4983
|
// TODO tagging a page with external to make sure that embedded pages aren't
|
4892
4984
|
// removed by the various page handling code is bad. Having page handling code
|
4893
4985
|
// in many places is bad. Solutions post 1.0
|
4894
|
-
page.attr( "data-" + this._getNs() + "url",
|
4986
|
+
page.attr( "data-" + this._getNs() + "url", this._createDataUrl( fileUrl ) )
|
4895
4987
|
.attr( "data-" + this._getNs() + "external-page", true );
|
4896
4988
|
|
4897
4989
|
return page;
|
@@ -4928,7 +5020,7 @@ $.widget( "mobile.page", {
|
|
4928
5020
|
( page || this.element ).trigger( deprecatedEvent, data );
|
4929
5021
|
|
4930
5022
|
// use the widget trigger method for the new content* event
|
4931
|
-
this.
|
5023
|
+
this._trigger( name, newEvent, data );
|
4932
5024
|
|
4933
5025
|
return {
|
4934
5026
|
deprecatedEvent: deprecatedEvent,
|
@@ -4940,8 +5032,7 @@ $.widget( "mobile.page", {
|
|
4940
5032
|
// or require ordering such that other bits are sprinkled in between parts that
|
4941
5033
|
// could be abstracted out as a group
|
4942
5034
|
_loadSuccess: function( absUrl, triggerData, settings, deferred ) {
|
4943
|
-
var fileUrl = this._createFileUrl( absUrl )
|
4944
|
-
dataUrl = this._createDataUrl( absUrl );
|
5035
|
+
var fileUrl = this._createFileUrl( absUrl );
|
4945
5036
|
|
4946
5037
|
return $.proxy(function( html, textStatus, xhr ) {
|
4947
5038
|
//pre-parse html to check for a data-url,
|
@@ -4961,6 +5052,11 @@ $.widget( "mobile.page", {
|
|
4961
5052
|
dataUrlRegex.test( RegExp.$1 ) &&
|
4962
5053
|
RegExp.$1 ) {
|
4963
5054
|
fileUrl = $.mobile.path.getFilePath( $("<div>" + RegExp.$1 + "</div>").text() );
|
5055
|
+
|
5056
|
+
// We specify that, if a data-url attribute is given on the page div, its value
|
5057
|
+
// must be given non-URL-encoded. However, in this part of the code, fileUrl is
|
5058
|
+
// assumed to be URL-encoded, so we URL-encode the retrieved value here
|
5059
|
+
fileUrl = this.window[ 0 ].encodeURIComponent( fileUrl );
|
4964
5060
|
}
|
4965
5061
|
|
4966
5062
|
//dont update the base tag if we are prefetching
|
@@ -4981,11 +5077,13 @@ $.widget( "mobile.page", {
|
|
4981
5077
|
|
4982
5078
|
triggerData.content = content;
|
4983
5079
|
|
5080
|
+
triggerData.toPage = content;
|
5081
|
+
|
4984
5082
|
// If the default behavior is prevented, stop here!
|
4985
5083
|
// Note that it is the responsibility of the listener/handler
|
4986
5084
|
// that called preventDefault(), to resolve/reject the
|
4987
5085
|
// deferred object within the triggerData.
|
4988
|
-
if (
|
5086
|
+
if ( this._triggerWithDeprecated( "load", triggerData ).event.isDefaultPrevented() ) {
|
4989
5087
|
return;
|
4990
5088
|
}
|
4991
5089
|
|
@@ -4996,23 +5094,11 @@ $.widget( "mobile.page", {
|
|
4996
5094
|
|
4997
5095
|
this._include( content, settings );
|
4998
5096
|
|
4999
|
-
// Enhancing the content may result in new dialogs/sub content being inserted
|
5000
|
-
// into the DOM. If the original absUrl refers to a sub-content, that is the
|
5001
|
-
// real content we are interested in.
|
5002
|
-
if ( absUrl.indexOf( "&" + $.mobile.subPageUrlKey ) > -1 ) {
|
5003
|
-
content = this.element.children( "[data-" + this._getNs() +"url='" + dataUrl + "']" );
|
5004
|
-
}
|
5005
|
-
|
5006
5097
|
// Remove loading message.
|
5007
5098
|
if ( settings.showLoadMsg ) {
|
5008
5099
|
this._hideLoading();
|
5009
5100
|
}
|
5010
5101
|
|
5011
|
-
// BEGIN DEPRECATED ---------------------------------------------------
|
5012
|
-
// Let listeners know the content loaded successfully.
|
5013
|
-
this.element.trigger( "pageload" );
|
5014
|
-
// END DEPRECATED -----------------------------------------------------
|
5015
|
-
|
5016
5102
|
deferred.resolve( absUrl, settings, content );
|
5017
5103
|
}, this);
|
5018
5104
|
},
|
@@ -5041,8 +5127,16 @@ $.widget( "mobile.page", {
|
|
5041
5127
|
// know when the content is done loading, or if an error has occurred.
|
5042
5128
|
var deferred = ( options && options.deferred ) || $.Deferred(),
|
5043
5129
|
|
5130
|
+
// Examining the option "reloadPage" passed by the user is deprecated as of 1.4.0
|
5131
|
+
// and will be removed in 1.5.0.
|
5132
|
+
// Copy option "reloadPage" to "reload", but only if option "reload" is not present
|
5133
|
+
reloadOptionExtension =
|
5134
|
+
( ( options && options.reload === undefined &&
|
5135
|
+
options.reloadPage !== undefined ) ?
|
5136
|
+
{ reload: options.reloadPage } : {} ),
|
5137
|
+
|
5044
5138
|
// The default load options with overrides specified by the caller.
|
5045
|
-
settings = $.extend( {}, this._loadDefaults, options ),
|
5139
|
+
settings = $.extend( {}, this._loadDefaults, options, reloadOptionExtension ),
|
5046
5140
|
|
5047
5141
|
// The DOM element for the content after it has been loaded.
|
5048
5142
|
content = null,
|
@@ -5052,9 +5146,6 @@ $.widget( "mobile.page", {
|
|
5052
5146
|
absUrl = $.mobile.path.makeUrlAbsolute( url, this._findBaseWithDefault() ),
|
5053
5147
|
fileUrl, dataUrl, pblEvent, triggerData;
|
5054
5148
|
|
5055
|
-
// DEPRECATED reloadPage
|
5056
|
-
settings.reload = settings.reloadPage;
|
5057
|
-
|
5058
5149
|
// If the caller provided data, and we're using "get" request,
|
5059
5150
|
// append the data to the URL.
|
5060
5151
|
if ( settings.data && settings.type === "get" ) {
|
@@ -5086,7 +5177,7 @@ $.widget( "mobile.page", {
|
|
5086
5177
|
$.mobile.path.isEmbeddedPage(fileUrl) &&
|
5087
5178
|
!$.mobile.path.isFirstPageUrl(fileUrl) ) {
|
5088
5179
|
deferred.reject( absUrl, settings );
|
5089
|
-
return;
|
5180
|
+
return deferred.promise();
|
5090
5181
|
}
|
5091
5182
|
|
5092
5183
|
// Reset base to the default document base
|
@@ -5107,12 +5198,14 @@ $.widget( "mobile.page", {
|
|
5107
5198
|
this._getBase().set(url);
|
5108
5199
|
}
|
5109
5200
|
|
5110
|
-
return;
|
5201
|
+
return deferred.promise();
|
5111
5202
|
}
|
5112
5203
|
|
5113
5204
|
triggerData = {
|
5114
5205
|
url: url,
|
5115
5206
|
absUrl: absUrl,
|
5207
|
+
toPage: url,
|
5208
|
+
prevPage: options ? options.fromPage : undefined,
|
5116
5209
|
dataUrl: dataUrl,
|
5117
5210
|
deferred: deferred,
|
5118
5211
|
options: settings
|
@@ -5124,7 +5217,7 @@ $.widget( "mobile.page", {
|
|
5124
5217
|
// If the default behavior is prevented, stop here!
|
5125
5218
|
if ( pblEvent.deprecatedEvent.isDefaultPrevented() ||
|
5126
5219
|
pblEvent.event.isDefaultPrevented() ) {
|
5127
|
-
return;
|
5220
|
+
return deferred.promise();
|
5128
5221
|
}
|
5129
5222
|
|
5130
5223
|
if ( settings.showLoadMsg ) {
|
@@ -5140,7 +5233,7 @@ $.widget( "mobile.page", {
|
|
5140
5233
|
if ( !( $.mobile.allowCrossDomainPages ||
|
5141
5234
|
$.mobile.path.isSameDomain($.mobile.path.documentUrl, absUrl ) ) ) {
|
5142
5235
|
deferred.reject( absUrl, settings );
|
5143
|
-
return;
|
5236
|
+
return deferred.promise();
|
5144
5237
|
}
|
5145
5238
|
|
5146
5239
|
// Load the new content.
|
@@ -5153,6 +5246,8 @@ $.widget( "mobile.page", {
|
|
5153
5246
|
success: this._loadSuccess( absUrl, triggerData, settings, deferred ),
|
5154
5247
|
error: this._loadError( absUrl, triggerData, settings, deferred )
|
5155
5248
|
});
|
5249
|
+
|
5250
|
+
return deferred.promise();
|
5156
5251
|
},
|
5157
5252
|
|
5158
5253
|
_loadError: function( absUrl, triggerData, settings, deferred ) {
|
@@ -5211,11 +5306,21 @@ $.widget( "mobile.page", {
|
|
5211
5306
|
|
5212
5307
|
//trigger before show/hide events
|
5213
5308
|
// TODO deprecate nextPage in favor of next
|
5214
|
-
this._triggerWithDeprecated( prefix + "hide", {
|
5309
|
+
this._triggerWithDeprecated( prefix + "hide", {
|
5310
|
+
|
5311
|
+
// Deprecated in 1.4 remove in 1.5
|
5312
|
+
nextPage: to,
|
5313
|
+
toPage: to,
|
5314
|
+
prevPage: from,
|
5315
|
+
samePage: samePage
|
5316
|
+
}, from );
|
5215
5317
|
}
|
5216
5318
|
|
5217
5319
|
// TODO deprecate prevPage in favor of previous
|
5218
|
-
this._triggerWithDeprecated( prefix + "show", {
|
5320
|
+
this._triggerWithDeprecated( prefix + "show", {
|
5321
|
+
prevPage: from || $( "" ),
|
5322
|
+
toPage: to
|
5323
|
+
}, to );
|
5219
5324
|
},
|
5220
5325
|
|
5221
5326
|
// TODO make private once change has been defined in the widget
|
@@ -5235,14 +5340,14 @@ $.widget( "mobile.page", {
|
|
5235
5340
|
|
5236
5341
|
promise = ( new TransitionHandler( transition, reverse, to, from ) ).transition();
|
5237
5342
|
|
5343
|
+
promise.done( $.proxy( function() {
|
5344
|
+
this._triggerCssTransitionEvents( to, from );
|
5345
|
+
}, this ));
|
5346
|
+
|
5238
5347
|
// TODO temporary accomodation of argument deferred
|
5239
5348
|
promise.done(function() {
|
5240
5349
|
deferred.resolve.apply( deferred, arguments );
|
5241
5350
|
});
|
5242
|
-
|
5243
|
-
promise.done($.proxy(function() {
|
5244
|
-
this._triggerCssTransitionEvents( to, from );
|
5245
|
-
}, this));
|
5246
5351
|
},
|
5247
5352
|
|
5248
5353
|
_releaseTransitionLock: function() {
|
@@ -5287,9 +5392,13 @@ $.widget( "mobile.page", {
|
|
5287
5392
|
},
|
5288
5393
|
|
5289
5394
|
_triggerPageBeforeChange: function( to, triggerData, settings ) {
|
5290
|
-
var
|
5395
|
+
var returnEvents;
|
5291
5396
|
|
5292
|
-
|
5397
|
+
triggerData.prevPage = this.activePage;
|
5398
|
+
$.extend( triggerData, {
|
5399
|
+
toPage: to,
|
5400
|
+
options: settings
|
5401
|
+
});
|
5293
5402
|
|
5294
5403
|
// NOTE: preserve the original target as the dataUrl value will be
|
5295
5404
|
// simplified eg, removing ui-state, and removing query params from
|
@@ -5306,10 +5415,11 @@ $.widget( "mobile.page", {
|
|
5306
5415
|
}
|
5307
5416
|
|
5308
5417
|
// Let listeners know we're about to change the current page.
|
5309
|
-
this.
|
5418
|
+
returnEvents = this._triggerWithDeprecated( "beforechange", triggerData );
|
5310
5419
|
|
5311
5420
|
// If the default behavior is prevented, stop here!
|
5312
|
-
if (
|
5421
|
+
if ( returnEvents.event.isDefaultPrevented() ||
|
5422
|
+
returnEvents.deprecatedEvent.isDefaultPrevented() ) {
|
5313
5423
|
return false;
|
5314
5424
|
}
|
5315
5425
|
|
@@ -5382,6 +5492,7 @@ $.widget( "mobile.page", {
|
|
5382
5492
|
return;
|
5383
5493
|
}
|
5384
5494
|
|
5495
|
+
triggerData.prevPage = settings.fromPage;
|
5385
5496
|
// if the (content|page)beforetransition default is prevented return early
|
5386
5497
|
// Note, we have to check for both the deprecated and new events
|
5387
5498
|
beforeTransition = this._triggerWithDeprecated( "beforetransition", triggerData );
|
@@ -5437,7 +5548,7 @@ $.widget( "mobile.page", {
|
|
5437
5548
|
|
5438
5549
|
isPageTransitioning = false;
|
5439
5550
|
this._triggerWithDeprecated( "transition", triggerData );
|
5440
|
-
this.
|
5551
|
+
this._triggerWithDeprecated( "change", triggerData );
|
5441
5552
|
|
5442
5553
|
// Even if there is no page change to be done, we should keep the
|
5443
5554
|
// urlHistory in sync with the hash changes
|
@@ -5515,12 +5626,6 @@ $.widget( "mobile.page", {
|
|
5515
5626
|
} else {
|
5516
5627
|
url += "#" + $.mobile.dialogHashKey;
|
5517
5628
|
}
|
5518
|
-
|
5519
|
-
// tack on another dialogHashKey if this is the same as the initial hash
|
5520
|
-
// this makes sure that a history entry is created for this dialog
|
5521
|
-
if ( $.mobile.navigate.history.activeIndex === 0 && url === $.mobile.navigate.history.initialDst ) {
|
5522
|
-
url += $.mobile.dialogHashKey;
|
5523
|
-
}
|
5524
5629
|
}
|
5525
5630
|
|
5526
5631
|
// if title element wasn't found, try the page div data attr too
|
@@ -5563,7 +5668,7 @@ $.widget( "mobile.page", {
|
|
5563
5668
|
};
|
5564
5669
|
|
5565
5670
|
if ( settings.changeHash !== false && $.mobile.hashListeningEnabled ) {
|
5566
|
-
$.mobile.navigate( url, params, true);
|
5671
|
+
$.mobile.navigate( this.window[ 0 ].encodeURI( url ), params, true);
|
5567
5672
|
} else if ( toPage[ 0 ] !== $.mobile.firstPage[ 0 ] ) {
|
5568
5673
|
$.mobile.navigate.history.add( url, params );
|
5569
5674
|
}
|
@@ -5604,8 +5709,8 @@ $.widget( "mobile.page", {
|
|
5604
5709
|
}
|
5605
5710
|
|
5606
5711
|
this._releaseTransitionLock();
|
5607
|
-
this.element.trigger( "pagechange", triggerData );
|
5608
5712
|
this._triggerWithDeprecated( "transition", triggerData );
|
5713
|
+
this._triggerWithDeprecated( "change", triggerData );
|
5609
5714
|
}, this));
|
5610
5715
|
},
|
5611
5716
|
|
@@ -5634,6 +5739,18 @@ $.widget( "mobile.page", {
|
|
5634
5739
|
|
5635
5740
|
// resolved on domready
|
5636
5741
|
var domreadyDeferred = $.Deferred(),
|
5742
|
+
|
5743
|
+
// resolved and nulled on window.load()
|
5744
|
+
loadDeferred = $.Deferred(),
|
5745
|
+
|
5746
|
+
// function that resolves the above deferred
|
5747
|
+
pageIsFullyLoaded = function() {
|
5748
|
+
|
5749
|
+
// Resolve and null the deferred
|
5750
|
+
loadDeferred.resolve();
|
5751
|
+
loadDeferred = null;
|
5752
|
+
},
|
5753
|
+
|
5637
5754
|
documentUrl = $.mobile.path.documentUrl,
|
5638
5755
|
|
5639
5756
|
// used to track last vclicked element to make sure its value is added to form data
|
@@ -5964,9 +6081,10 @@ $.widget( "mobile.page", {
|
|
5964
6081
|
// lists and select dialogs, just write a hash in the link they
|
5965
6082
|
// create. This means the actual URL path is based on whatever
|
5966
6083
|
// the current value of the base tag is at the time this code
|
5967
|
-
// is called.
|
5968
|
-
|
5969
|
-
|
6084
|
+
// is called.
|
6085
|
+
if ( href.search( "#" ) !== -1 &&
|
6086
|
+
!( $.mobile.path.isExternal( href ) && $.mobile.path.isAbsoluteUrl( href ) ) ) {
|
6087
|
+
|
5970
6088
|
href = href.replace( /[^#]*#/, "" );
|
5971
6089
|
if ( !href ) {
|
5972
6090
|
//link was an empty hash meant purely
|
@@ -6035,13 +6153,29 @@ $.widget( "mobile.page", {
|
|
6035
6153
|
$.mobile.pageContainer.pagecontainer();
|
6036
6154
|
|
6037
6155
|
//set page min-heights to be device specific
|
6038
|
-
$.mobile.document.bind( "pageshow",
|
6156
|
+
$.mobile.document.bind( "pageshow", function() {
|
6157
|
+
|
6158
|
+
// We need to wait for window.load to make sure that styles have already been rendered,
|
6159
|
+
// otherwise heights of external toolbars will have the wrong value
|
6160
|
+
if ( loadDeferred ) {
|
6161
|
+
loadDeferred.done( $.mobile.resetActivePageHeight );
|
6162
|
+
} else {
|
6163
|
+
$.mobile.resetActivePageHeight();
|
6164
|
+
}
|
6165
|
+
});
|
6039
6166
|
$.mobile.window.bind( "throttledresize", $.mobile.resetActivePageHeight );
|
6040
6167
|
|
6041
6168
|
};//navreadyDeferred done callback
|
6042
6169
|
|
6043
6170
|
$( function() { domreadyDeferred.resolve(); } );
|
6044
6171
|
|
6172
|
+
// Account for the possibility that the load event has already fired
|
6173
|
+
if ( document.readyState === "complete" ) {
|
6174
|
+
pageIsFullyLoaded();
|
6175
|
+
} else {
|
6176
|
+
$.mobile.window.load( pageIsFullyLoaded );
|
6177
|
+
}
|
6178
|
+
|
6045
6179
|
$.when( domreadyDeferred, $.mobile.navreadyDeferred ).done( function() { $.mobile._registerInternalEvents(); } );
|
6046
6180
|
})( jQuery );
|
6047
6181
|
|
@@ -6174,12 +6308,19 @@ $.widget( "mobile.page", {
|
|
6174
6308
|
// better transitions with fewer bugs. Ie, it's not guaranteed that the
|
6175
6309
|
// object will be created and transition will be run immediately after as
|
6176
6310
|
// it is today. So we wait until transition is invoked to gather the following
|
6177
|
-
var
|
6311
|
+
var none,
|
6312
|
+
reverseClass = this.reverse ? " reverse" : "",
|
6178
6313
|
screenHeight = $.mobile.getScreenHeight(),
|
6179
|
-
maxTransitionOverride = $.mobile.maxTransitionWidth !== false &&
|
6180
|
-
|
6314
|
+
maxTransitionOverride = $.mobile.maxTransitionWidth !== false &&
|
6315
|
+
$.mobile.window.width() > $.mobile.maxTransitionWidth;
|
6181
6316
|
|
6182
6317
|
this.toScroll = $.mobile.navigate.history.getActive().lastScroll || $.mobile.defaultHomeScroll;
|
6318
|
+
|
6319
|
+
none = !$.support.cssTransitions || !$.support.cssAnimations ||
|
6320
|
+
maxTransitionOverride || !this.name || this.name === "none" ||
|
6321
|
+
Math.max( $.mobile.window.scrollTop(), this.toScroll ) >
|
6322
|
+
$.mobile.getMaxScrollForTransition();
|
6323
|
+
|
6183
6324
|
this.toggleViewportClass();
|
6184
6325
|
|
6185
6326
|
if ( this.$from && !none ) {
|
@@ -6724,9 +6865,9 @@ $.widget( "mobile.collapsible", {
|
|
6724
6865
|
this._renderedOptions = this._getOptions( this.options );
|
6725
6866
|
|
6726
6867
|
if ( this.options.enhanced ) {
|
6727
|
-
ui.heading =
|
6868
|
+
ui.heading = this.element.children( ".ui-collapsible-heading" );
|
6728
6869
|
ui.content = ui.heading.next();
|
6729
|
-
ui.anchor =
|
6870
|
+
ui.anchor = ui.heading.children();
|
6730
6871
|
ui.status = ui.anchor.children( ".ui-collapsible-heading-status" );
|
6731
6872
|
} else {
|
6732
6873
|
this._enhance( elem, ui );
|
@@ -6840,7 +6981,7 @@ $.widget( "mobile.collapsible", {
|
|
6840
6981
|
},
|
6841
6982
|
|
6842
6983
|
_applyOptions: function( options ) {
|
6843
|
-
var isCollapsed, newTheme, oldTheme, hasCorners,
|
6984
|
+
var isCollapsed, newTheme, oldTheme, hasCorners, hasIcon,
|
6844
6985
|
elem = this.element,
|
6845
6986
|
currentOpts = this._renderedOptions,
|
6846
6987
|
ui = this._ui,
|
@@ -6857,38 +6998,61 @@ $.widget( "mobile.collapsible", {
|
|
6857
6998
|
|
6858
6999
|
isCollapsed = elem.hasClass( "ui-collapsible-collapsed" );
|
6859
7000
|
|
6860
|
-
//
|
6861
|
-
//
|
7001
|
+
// We only need to apply the cue text for the current state right away.
|
7002
|
+
// The cue text for the alternate state will be stored in the options
|
7003
|
+
// and applied the next time the collapsible's state is toggled
|
6862
7004
|
if ( isCollapsed ) {
|
6863
7005
|
if ( opts.expandCueText !== undefined ) {
|
6864
7006
|
status.text( opts.expandCueText );
|
6865
7007
|
}
|
6866
|
-
if ( opts.collapsedIcon !== undefined ) {
|
6867
|
-
if ( currentOpts.collapsedIcon ) {
|
6868
|
-
anchor.removeClass( "ui-icon-" + currentOpts.collapsedIcon );
|
6869
|
-
}
|
6870
|
-
if ( opts.collapsedIcon ) {
|
6871
|
-
anchor.addClass( "ui-icon-" + opts.collapsedIcon );
|
6872
|
-
}
|
6873
|
-
}
|
6874
7008
|
} else {
|
6875
7009
|
if ( opts.collapseCueText !== undefined ) {
|
6876
7010
|
status.text( opts.collapseCueText );
|
6877
7011
|
}
|
6878
|
-
if ( opts.expandedIcon !== undefined ) {
|
6879
|
-
if ( currentOpts.expandedIcon ) {
|
6880
|
-
anchor.removeClass( "ui-icon-" + currentOpts.expandedIcon );
|
6881
|
-
}
|
6882
|
-
if ( opts.expandedIcon ) {
|
6883
|
-
anchor.addClass( "ui-icon-" + opts.expandedIcon );
|
6884
|
-
}
|
6885
|
-
}
|
6886
7012
|
}
|
6887
7013
|
|
6888
|
-
|
6889
|
-
|
6890
|
-
|
6891
|
-
|
7014
|
+
// Update icon
|
7015
|
+
|
7016
|
+
// Is it supposed to have an icon?
|
7017
|
+
hasIcon =
|
7018
|
+
|
7019
|
+
// If the collapsedIcon is being set, consult that
|
7020
|
+
( opts.collapsedIcon !== undefined ? opts.collapsedIcon !== false :
|
7021
|
+
|
7022
|
+
// Otherwise consult the existing option value
|
7023
|
+
currentOpts.collapsedIcon !== false );
|
7024
|
+
|
7025
|
+
|
7026
|
+
// If any icon-related options have changed, make sure the new icon
|
7027
|
+
// state is reflected by first removing all icon-related classes
|
7028
|
+
// reflecting the current state and then adding all icon-related
|
7029
|
+
// classes for the new state
|
7030
|
+
if ( !( opts.iconpos === undefined &&
|
7031
|
+
opts.collapsedIcon === undefined &&
|
7032
|
+
opts.expandedIcon === undefined ) ) {
|
7033
|
+
|
7034
|
+
// Remove all current icon-related classes
|
7035
|
+
anchor.removeClass( [ iconposClass( currentOpts.iconpos ) ]
|
7036
|
+
.concat( ( currentOpts.expandedIcon ?
|
7037
|
+
[ "ui-icon-" + currentOpts.expandedIcon ] : [] ) )
|
7038
|
+
.concat( ( currentOpts.collapsedIcon ?
|
7039
|
+
[ "ui-icon-" + currentOpts.collapsedIcon ] : [] ) )
|
7040
|
+
.join( " " ) );
|
7041
|
+
|
7042
|
+
// Add new classes if an icon is supposed to be present
|
7043
|
+
if ( hasIcon ) {
|
7044
|
+
anchor.addClass(
|
7045
|
+
[ iconposClass( opts.iconpos !== undefined ?
|
7046
|
+
opts.iconpos : currentOpts.iconpos ) ]
|
7047
|
+
.concat( isCollapsed ?
|
7048
|
+
[ "ui-icon-" + ( opts.collapsedIcon !== undefined ?
|
7049
|
+
opts.collapsedIcon :
|
7050
|
+
currentOpts.collapsedIcon ) ] :
|
7051
|
+
[ "ui-icon-" + ( opts.expandedIcon !== undefined ?
|
7052
|
+
opts.expandedIcon :
|
7053
|
+
currentOpts.expandedIcon ) ] )
|
7054
|
+
.join( " " ) );
|
7055
|
+
}
|
6892
7056
|
}
|
6893
7057
|
|
6894
7058
|
if ( opts.theme !== undefined ) {
|
@@ -7010,16 +7174,31 @@ $.mobile.collapsible.defaults = {
|
|
7010
7174
|
|
7011
7175
|
(function( $, undefined ) {
|
7012
7176
|
|
7177
|
+
var uiScreenHiddenRegex = /\bui-screen-hidden\b/;
|
7178
|
+
function noHiddenClass( elements ) {
|
7179
|
+
var index,
|
7180
|
+
length = elements.length,
|
7181
|
+
result = [];
|
7182
|
+
|
7183
|
+
for ( index = 0; index < length; index++ ) {
|
7184
|
+
if ( !elements[ index ].className.match( uiScreenHiddenRegex ) ) {
|
7185
|
+
result.push( elements[ index ] );
|
7186
|
+
}
|
7187
|
+
}
|
7188
|
+
|
7189
|
+
return $( result );
|
7190
|
+
}
|
7191
|
+
|
7013
7192
|
$.mobile.behaviors.addFirstLastClasses = {
|
7014
7193
|
_getVisibles: function( $els, create ) {
|
7015
7194
|
var visibles;
|
7016
7195
|
|
7017
7196
|
if ( create ) {
|
7018
|
-
visibles = $els
|
7197
|
+
visibles = noHiddenClass( $els );
|
7019
7198
|
} else {
|
7020
7199
|
visibles = $els.filter( ":visible" );
|
7021
7200
|
if ( visibles.length === 0 ) {
|
7022
|
-
visibles = $els
|
7201
|
+
visibles = noHiddenClass( $els );
|
7023
7202
|
}
|
7024
7203
|
}
|
7025
7204
|
|
@@ -7222,7 +7401,7 @@ $.widget( "mobile.navbar", {
|
|
7222
7401
|
_create: function() {
|
7223
7402
|
|
7224
7403
|
var $navbar = this.element,
|
7225
|
-
$navbtns = $navbar.find( "a" ),
|
7404
|
+
$navbtns = $navbar.find( "a, button" ),
|
7226
7405
|
iconpos = $navbtns.filter( ":jqmData(icon)" ).length ? this.options.iconpos : undefined;
|
7227
7406
|
|
7228
7407
|
$navbar.addClass( "ui-navbar" )
|
@@ -7413,11 +7592,15 @@ $.widget( "mobile.listview", $.extend( {
|
|
7413
7592
|
.attr( "title", $.trim( last.getEncodedText() ) )
|
7414
7593
|
.addClass( altButtonClass )
|
7415
7594
|
.empty();
|
7595
|
+
|
7596
|
+
// Reduce to the first anchor, because only the first gets the buttonClass
|
7597
|
+
a = a.first();
|
7416
7598
|
} else if ( icon ) {
|
7417
7599
|
buttonClass += " ui-btn-icon-right ui-icon-" + icon;
|
7418
7600
|
}
|
7419
7601
|
|
7420
|
-
|
7602
|
+
// Apply buttonClass to the (first) anchor
|
7603
|
+
a.addClass( buttonClass );
|
7421
7604
|
} else if ( isDivider ) {
|
7422
7605
|
dividerTheme = ( getAttr( item[ 0 ], "theme" ) || o.dividerTheme || o.theme );
|
7423
7606
|
|
@@ -7460,7 +7643,7 @@ $.widget( "mobile.listview", $.extend( {
|
|
7460
7643
|
$( this ).closest( "li" ).addClass( "ui-li-has-count" );
|
7461
7644
|
});
|
7462
7645
|
if ( countThemeClass ) {
|
7463
|
-
countBubbles.addClass( countThemeClass );
|
7646
|
+
countBubbles.not( "[class*='ui-body-']" ).addClass( countThemeClass );
|
7464
7647
|
}
|
7465
7648
|
|
7466
7649
|
// Deprecated in 1.4. From 1.5 you have to add class ui-li-has-thumb or ui-li-has-icon to the LI.
|
@@ -7596,6 +7779,8 @@ $.mobile.behaviors.formReset = {
|
|
7596
7779
|
|
7597
7780
|
(function( $, undefined ) {
|
7598
7781
|
|
7782
|
+
var escapeId = $.mobile.path.hashToSelector;
|
7783
|
+
|
7599
7784
|
$.widget( "mobile.checkboxradio", $.extend( {
|
7600
7785
|
|
7601
7786
|
initSelector: "input:not( :jqmData(role='flipswitch' ) )[type='checkbox'],input[type='radio']:not( :jqmData(role='flipswitch' ))",
|
@@ -7615,15 +7800,12 @@ $.widget( "mobile.checkboxradio", $.extend( {
|
|
7615
7800
|
return input.jqmData( dataAttr ) ||
|
7616
7801
|
input.closest( "form, fieldset" ).jqmData( dataAttr );
|
7617
7802
|
},
|
7618
|
-
|
7619
|
-
|
7620
|
-
|
7621
|
-
|
7622
|
-
|
7623
|
-
|
7624
|
-
.find( "label" )
|
7625
|
-
.filter( "[for='" + $.mobile.path.hashToSelector( input[0].id ) + "']" )
|
7626
|
-
.first(),
|
7803
|
+
label = this.options.enhanced ?
|
7804
|
+
{
|
7805
|
+
element: this.element.siblings( "label" ),
|
7806
|
+
isParent: false
|
7807
|
+
} :
|
7808
|
+
this._findLabel(),
|
7627
7809
|
inputtype = input[0].type,
|
7628
7810
|
checkedClass = "ui-" + inputtype + "-on",
|
7629
7811
|
uncheckedClass = "ui-" + inputtype + "-off";
|
@@ -7636,7 +7818,8 @@ $.widget( "mobile.checkboxradio", $.extend( {
|
|
7636
7818
|
this.options.disabled = true;
|
7637
7819
|
}
|
7638
7820
|
|
7639
|
-
o.iconpos = inheritAttr( input, "iconpos" ) ||
|
7821
|
+
o.iconpos = inheritAttr( input, "iconpos" ) ||
|
7822
|
+
label.element.attr( "data-" + $.mobile.ns + "iconpos" ) || o.iconpos,
|
7640
7823
|
|
7641
7824
|
// Establish options
|
7642
7825
|
o.mini = inheritAttr( input, "mini" ) || o.mini;
|
@@ -7644,8 +7827,8 @@ $.widget( "mobile.checkboxradio", $.extend( {
|
|
7644
7827
|
// Expose for other methods
|
7645
7828
|
$.extend( this, {
|
7646
7829
|
input: input,
|
7647
|
-
label: label,
|
7648
|
-
|
7830
|
+
label: label.element,
|
7831
|
+
labelIsParent: label.isParent,
|
7649
7832
|
inputtype: inputtype,
|
7650
7833
|
checkedClass: checkedClass,
|
7651
7834
|
uncheckedClass: uncheckedClass
|
@@ -7655,7 +7838,7 @@ $.widget( "mobile.checkboxradio", $.extend( {
|
|
7655
7838
|
this._enhance();
|
7656
7839
|
}
|
7657
7840
|
|
7658
|
-
this._on( label, {
|
7841
|
+
this._on( label.element, {
|
7659
7842
|
vmouseover: "_handleLabelVMouseOver",
|
7660
7843
|
vclick: "_handleLabelVClick"
|
7661
7844
|
});
|
@@ -7671,10 +7854,36 @@ $.widget( "mobile.checkboxradio", $.extend( {
|
|
7671
7854
|
this.refresh();
|
7672
7855
|
},
|
7673
7856
|
|
7857
|
+
_findLabel: function() {
|
7858
|
+
var parentLabel, label, isParent,
|
7859
|
+
input = this.element,
|
7860
|
+
labelsList = input[ 0 ].labels;
|
7861
|
+
|
7862
|
+
if( labelsList && labelsList.length > 0 ) {
|
7863
|
+
label = $( labelsList[ 0 ] );
|
7864
|
+
isParent = $.contains( label[ 0 ], input[ 0 ] );
|
7865
|
+
} else {
|
7866
|
+
parentLabel = input.closest( "label" );
|
7867
|
+
isParent = ( parentLabel.length > 0 );
|
7868
|
+
|
7869
|
+
// NOTE: Windows Phone could not find the label through a selector
|
7870
|
+
// filter works though.
|
7871
|
+
label = isParent ? parentLabel :
|
7872
|
+
$( this.document[ 0 ].getElementsByTagName( "label" ) )
|
7873
|
+
.filter( "[for='" + escapeId( input[ 0 ].id ) + "']" )
|
7874
|
+
.first();
|
7875
|
+
}
|
7876
|
+
|
7877
|
+
return {
|
7878
|
+
element: label,
|
7879
|
+
isParent: isParent
|
7880
|
+
};
|
7881
|
+
},
|
7882
|
+
|
7674
7883
|
_enhance: function() {
|
7675
7884
|
this.label.addClass( "ui-btn ui-corner-all");
|
7676
7885
|
|
7677
|
-
if ( this.
|
7886
|
+
if ( this.labelIsParent ) {
|
7678
7887
|
this.input.add( this.label ).wrapAll( this._wrapper() );
|
7679
7888
|
} else {
|
7680
7889
|
//this.element.replaceWith( this.input.add( this.label ).wrapAll( this._wrapper() ) );
|
@@ -7708,18 +7917,10 @@ $.widget( "mobile.checkboxradio", $.extend( {
|
|
7708
7917
|
},
|
7709
7918
|
|
7710
7919
|
_handleInputVClick: function() {
|
7711
|
-
var $this = this.element;
|
7712
|
-
|
7713
7920
|
// Adds checked attribute to checked input when keyboard is used
|
7714
|
-
|
7715
|
-
|
7716
|
-
|
7717
|
-
this._getInputSet().not( $this ).prop( "checked", false );
|
7718
|
-
} else {
|
7719
|
-
$this.prop( "checked", false );
|
7720
|
-
}
|
7721
|
-
|
7722
|
-
this._updateAll();
|
7921
|
+
this.element.prop( "checked", this.element.is( ":checked" ) );
|
7922
|
+
this._getInputSet().not( this.element ).prop( "checked", false );
|
7923
|
+
this._updateAll( true );
|
7723
7924
|
},
|
7724
7925
|
|
7725
7926
|
_handleLabelVMouseOver: function( event ) {
|
@@ -7762,23 +7963,60 @@ $.widget( "mobile.checkboxradio", $.extend( {
|
|
7762
7963
|
});
|
7763
7964
|
},
|
7764
7965
|
|
7765
|
-
//
|
7966
|
+
// Returns those radio buttons that are supposed to be in the same group as
|
7967
|
+
// this radio button. In the case of a checkbox or a radio lacking a name
|
7968
|
+
// attribute, it returns this.element.
|
7766
7969
|
_getInputSet: function() {
|
7767
|
-
|
7768
|
-
|
7769
|
-
|
7970
|
+
var selector, formId,
|
7971
|
+
radio = this.element[ 0 ],
|
7972
|
+
name = radio.name,
|
7973
|
+
form = radio.form,
|
7974
|
+
doc = this.element.parents().last().get( 0 ),
|
7975
|
+
|
7976
|
+
// A radio is always a member of its own group
|
7977
|
+
radios = this.element;
|
7978
|
+
|
7979
|
+
// Only start running selectors if this is an attached radio button with a name
|
7980
|
+
if ( name && this.inputtype === "radio" && doc ) {
|
7981
|
+
selector = "input[type='radio'][name='" + escapeId( name ) + "']";
|
7982
|
+
|
7983
|
+
// If we're inside a form
|
7984
|
+
if ( form ) {
|
7985
|
+
formId = form.getAttribute( "id" );
|
7986
|
+
|
7987
|
+
// If the form has an ID, collect radios scattered throught the document which
|
7988
|
+
// nevertheless are part of the form by way of the value of their form attribute
|
7989
|
+
if ( formId ) {
|
7990
|
+
radios = $( selector + "[form='" + escapeId( formId ) + "']", doc );
|
7991
|
+
}
|
7992
|
+
|
7993
|
+
// Also add to those the radios in the form itself
|
7994
|
+
radios = $( form ).find( selector ).filter( function() {
|
7770
7995
|
|
7771
|
-
|
7772
|
-
|
7996
|
+
// Some radios inside the form may belong to some other form by virtue of
|
7997
|
+
// having a form attribute defined on them, so we must filter them out here
|
7998
|
+
return ( this.form === form );
|
7999
|
+
}).add( radios );
|
8000
|
+
|
8001
|
+
// If we're outside a form
|
8002
|
+
} else {
|
8003
|
+
|
8004
|
+
// Collect all those radios which are also outside of a form and match our name
|
8005
|
+
radios = $( selector, doc ).filter( function() {
|
8006
|
+
return !this.form;
|
8007
|
+
});
|
8008
|
+
}
|
8009
|
+
}
|
8010
|
+
return radios;
|
7773
8011
|
},
|
7774
8012
|
|
7775
|
-
_updateAll: function() {
|
8013
|
+
_updateAll: function( changeTriggered ) {
|
7776
8014
|
var self = this;
|
7777
8015
|
|
7778
8016
|
this._getInputSet().each( function() {
|
7779
8017
|
var $this = $( this );
|
7780
8018
|
|
7781
|
-
if ( this.checked || self.inputtype === "checkbox" ) {
|
8019
|
+
if ( ( this.checked || self.inputtype === "checkbox" ) && !changeTriggered ) {
|
7782
8020
|
$this.trigger( "change" );
|
7783
8021
|
}
|
7784
8022
|
})
|
@@ -7819,14 +8057,13 @@ $.widget( "mobile.checkboxradio", $.extend( {
|
|
7819
8057
|
},
|
7820
8058
|
|
7821
8059
|
refresh: function() {
|
7822
|
-
var
|
7823
|
-
isChecked = this.element[ 0 ].checked,
|
8060
|
+
var isChecked = this.element[ 0 ].checked,
|
7824
8061
|
active = $.mobile.activeBtnClass,
|
7825
8062
|
iconposClass = "ui-btn-icon-" + this.options.iconpos,
|
7826
8063
|
addClasses = [],
|
7827
8064
|
removeClasses = [];
|
7828
8065
|
|
7829
|
-
if (
|
8066
|
+
if ( this._hasIcon() ) {
|
7830
8067
|
removeClasses.push( active );
|
7831
8068
|
addClasses.push( iconposClass );
|
7832
8069
|
} else {
|
@@ -7842,6 +8079,8 @@ $.widget( "mobile.checkboxradio", $.extend( {
|
|
7842
8079
|
removeClasses.push( this.checkedClass );
|
7843
8080
|
}
|
7844
8081
|
|
8082
|
+
this.widget().toggleClass( "ui-state-disabled", this.element.prop( "disabled" ) );
|
8083
|
+
|
7845
8084
|
this.label
|
7846
8085
|
.addClass( addClasses.join( " " ) )
|
7847
8086
|
.removeClass( removeClasses.join( " " ) );
|
@@ -7957,8 +8196,8 @@ $.widget( "mobile.button", {
|
|
7957
8196
|
},
|
7958
8197
|
|
7959
8198
|
_destroy: function() {
|
7960
|
-
this.element.insertBefore( this.
|
7961
|
-
this.
|
8199
|
+
this.element.insertBefore( this.wrapper );
|
8200
|
+
this.wrapper.remove();
|
7962
8201
|
},
|
7963
8202
|
|
7964
8203
|
_getIconClasses: function( options ) {
|
@@ -8005,13 +8244,19 @@ $.widget( "mobile.button", {
|
|
8005
8244
|
},
|
8006
8245
|
|
8007
8246
|
refresh: function( create ) {
|
8247
|
+
var originalElement,
|
8248
|
+
isDisabled = this.element.prop( "disabled" );
|
8249
|
+
|
8008
8250
|
if ( this.options.icon && this.options.iconpos === "notext" && this.element.attr( "title" ) ) {
|
8009
8251
|
this.element.attr( "title", this.element.val() );
|
8010
8252
|
}
|
8011
8253
|
if ( !create ) {
|
8012
|
-
|
8254
|
+
originalElement = this.element.detach();
|
8013
8255
|
$( this.wrapper ).text( this.element.val() ).append( originalElement );
|
8014
8256
|
}
|
8257
|
+
if ( this.options.disabled !== isDisabled ) {
|
8258
|
+
this._setOptions({ disabled: isDisabled });
|
8259
|
+
}
|
8015
8260
|
}
|
8016
8261
|
});
|
8017
8262
|
|
@@ -8749,7 +8994,7 @@ $.widget( "mobile.slider", $.extend( {
|
|
8749
8994
|
|
8750
8995
|
// update control"s value
|
8751
8996
|
if ( isInput ) {
|
8752
|
-
valueChanged = control.val() !== newval;
|
8997
|
+
valueChanged = parseFloat( control.val() ) !== newval;
|
8753
8998
|
control.val( newval );
|
8754
8999
|
} else {
|
8755
9000
|
valueChanged = control[ 0 ].selectedIndex !== newval;
|
@@ -8820,6 +9065,8 @@ $.widget( "mobile.slider", $.extend( {
|
|
8820
9065
|
this.slider
|
8821
9066
|
.toggleClass( "ui-state-disabled", value )
|
8822
9067
|
.attr( "aria-disabled", value );
|
9068
|
+
|
9069
|
+
this.element.toggleClass( "ui-state-disabled", value );
|
8823
9070
|
}
|
8824
9071
|
|
8825
9072
|
}, $.mobile.behaviors.formReset ) );
|
@@ -8912,7 +9159,9 @@ $.widget( "mobile.slider", $.mobile.slider, {
|
|
8912
9159
|
if ( o.popupEnabled && this._popup ) {
|
8913
9160
|
this._positionPopup();
|
8914
9161
|
this._popup.html( newValue );
|
8915
|
-
}
|
9162
|
+
}
|
9163
|
+
|
9164
|
+
if ( o.showValue && !this.options.mini ) {
|
8916
9165
|
this.handle.html( newValue );
|
8917
9166
|
}
|
8918
9167
|
},
|
@@ -9241,6 +9490,7 @@ $.widget( "mobile.flipswitch", $.extend({
|
|
9241
9490
|
//if the first handle is dragged send the event to the first slider
|
9242
9491
|
$.data( this._inputFirst.get(0), "mobile-slider" ).dragging = true;
|
9243
9492
|
$.data( this._inputFirst.get(0), "mobile-slider" ).refresh( event );
|
9493
|
+
$.data( this._inputFirst.get(0), "mobile-slider" )._trigger( "start" );
|
9244
9494
|
return false;
|
9245
9495
|
},
|
9246
9496
|
|
@@ -9293,6 +9543,11 @@ $.widget( "mobile.flipswitch", $.extend({
|
|
9293
9543
|
if ( options.highlight !== undefined ) {
|
9294
9544
|
this._setHighlight( options.highlight );
|
9295
9545
|
}
|
9546
|
+
|
9547
|
+
if ( options.disabled !== undefined ) {
|
9548
|
+
this._setDisabled( options.disabled );
|
9549
|
+
}
|
9550
|
+
|
9296
9551
|
this._super( options );
|
9297
9552
|
this.refresh();
|
9298
9553
|
},
|
@@ -9399,6 +9654,11 @@ $.widget( "mobile.flipswitch", $.extend({
|
|
9399
9654
|
this._inputLast.slider( "option", "highlight", value );
|
9400
9655
|
},
|
9401
9656
|
|
9657
|
+
_setDisabled: function( value ) {
|
9658
|
+
this._inputFirst.prop( "disabled", value );
|
9659
|
+
this._inputLast.prop( "disabled", value );
|
9660
|
+
},
|
9661
|
+
|
9402
9662
|
_destroy: function() {
|
9403
9663
|
this._label.prependTo( this.element );
|
9404
9664
|
this.element.removeClass( "ui-rangeslider ui-mini" );
|
@@ -9423,16 +9683,21 @@ $.widget( "mobile.flipswitch", $.extend({
|
|
9423
9683
|
_create: function() {
|
9424
9684
|
this._super();
|
9425
9685
|
|
9426
|
-
if (
|
9686
|
+
if ( this.isSearch ) {
|
9687
|
+
this.options.clearBtn = true;
|
9688
|
+
}
|
9689
|
+
|
9690
|
+
if ( !!this.options.clearBtn && this.inputNeedsWrap ) {
|
9427
9691
|
this._addClearBtn();
|
9428
9692
|
}
|
9429
9693
|
},
|
9430
9694
|
|
9431
9695
|
clearButton: function() {
|
9432
|
-
|
9433
|
-
|
9434
|
-
|
9435
|
-
|
9696
|
+
return $( "<a href='#' tabindex='-1' aria-hidden='true' " +
|
9697
|
+
"class='ui-input-clear ui-btn ui-icon-delete ui-btn-icon-notext ui-corner-all'>" +
|
9698
|
+
"</a>" )
|
9699
|
+
.attr( "title", this.options.clearBtnText )
|
9700
|
+
.text( this.options.clearBtnText );
|
9436
9701
|
},
|
9437
9702
|
|
9438
9703
|
_clearBtnClick: function( event ) {
|
@@ -9525,7 +9790,9 @@ $.widget( "mobile.flipswitch", $.extend({
|
|
9525
9790
|
|
9526
9791
|
_destroy: function() {
|
9527
9792
|
this._super();
|
9528
|
-
this.
|
9793
|
+
if ( this.options.clearBtn ) {
|
9794
|
+
this._destroyClear();
|
9795
|
+
}
|
9529
9796
|
}
|
9530
9797
|
|
9531
9798
|
});
|
@@ -9555,7 +9822,7 @@ $.widget( "mobile.flipswitch", $.extend({
|
|
9555
9822
|
"keyup": "_timeout",
|
9556
9823
|
"change": "_timeout",
|
9557
9824
|
"input": "_timeout",
|
9558
|
-
"paste": "_timeout"
|
9825
|
+
"paste": "_timeout"
|
9559
9826
|
});
|
9560
9827
|
|
9561
9828
|
// Attach to the various you-have-become-visible notifications that the
|
@@ -9591,7 +9858,7 @@ $.widget( "mobile.flipswitch", $.extend({
|
|
9591
9858
|
}, this ),
|
9592
9859
|
"transition" );
|
9593
9860
|
}
|
9594
|
-
this.
|
9861
|
+
this._prepareHeightUpdate();
|
9595
9862
|
}
|
9596
9863
|
},
|
9597
9864
|
|
@@ -9822,7 +10089,9 @@ $.widget( "mobile.selectmenu", $.extend( {
|
|
9822
10089
|
self.refresh();
|
9823
10090
|
|
9824
10091
|
if ( !!options.nativeMenu ) {
|
9825
|
-
|
10092
|
+
self._delay( function() {
|
10093
|
+
self.select.blur();
|
10094
|
+
});
|
9826
10095
|
}
|
9827
10096
|
});
|
9828
10097
|
|
@@ -10059,6 +10328,14 @@ $.widget( "mobile.popup", {
|
|
10059
10328
|
history: !$.mobile.browser.oldIE
|
10060
10329
|
},
|
10061
10330
|
|
10331
|
+
// When the user depresses the mouse/finger on an element inside the popup while the popup is
|
10332
|
+
// open, we ignore resize events for a short while. This prevents #6961.
|
10333
|
+
_handleDocumentVmousedown: function( theEvent ) {
|
10334
|
+
if ( this._isOpen && $.contains( this._ui.container[ 0 ], theEvent.target ) ) {
|
10335
|
+
this._ignoreResizeEvents();
|
10336
|
+
}
|
10337
|
+
},
|
10338
|
+
|
10062
10339
|
_create: function() {
|
10063
10340
|
var theElement = this.element,
|
10064
10341
|
myId = theElement.attr( "id" ),
|
@@ -10069,6 +10346,10 @@ $.widget( "mobile.popup", {
|
|
10069
10346
|
// it is determined whether there shall be AJAX nav.
|
10070
10347
|
currentOptions.history = currentOptions.history && $.mobile.ajaxEnabled && $.mobile.hashListeningEnabled;
|
10071
10348
|
|
10349
|
+
this._on( this.document, {
|
10350
|
+
"vmousedown": "_handleDocumentVmousedown"
|
10351
|
+
});
|
10352
|
+
|
10072
10353
|
// Define instance variables
|
10073
10354
|
$.extend( this, {
|
10074
10355
|
_scrollTop: 0,
|
@@ -10270,10 +10551,10 @@ $.widget( "mobile.popup", {
|
|
10270
10551
|
|
10271
10552
|
if ( targetElement !== ui.container[ 0 ] ) {
|
10272
10553
|
target = $( targetElement );
|
10273
|
-
if (
|
10274
|
-
$( this.document[ 0 ].activeElement ).one( "focus", function(
|
10275
|
-
|
10276
|
-
});
|
10554
|
+
if ( !$.contains( ui.container[ 0 ], targetElement ) ) {
|
10555
|
+
$( this.document[ 0 ].activeElement ).one( "focus", $.proxy( function() {
|
10556
|
+
this._safelyBlur( targetElement );
|
10557
|
+
}, this ) );
|
10277
10558
|
ui.focusElement.focus();
|
10278
10559
|
theEvent.preventDefault();
|
10279
10560
|
theEvent.stopImmediatePropagation();
|
@@ -10604,13 +10885,28 @@ $.widget( "mobile.popup", {
|
|
10604
10885
|
}
|
10605
10886
|
},
|
10606
10887
|
|
10888
|
+
_safelyBlur: function( currentElement ){
|
10889
|
+
if ( currentElement !== this.window[ 0 ] &&
|
10890
|
+
currentElement.nodeName.toLowerCase() !== "body" ) {
|
10891
|
+
$( currentElement ).blur();
|
10892
|
+
}
|
10893
|
+
},
|
10894
|
+
|
10607
10895
|
_openPrerequisitesComplete: function() {
|
10608
|
-
var id = this.element.attr( "id" )
|
10896
|
+
var id = this.element.attr( "id" ),
|
10897
|
+
firstFocus = this._ui.container.find( ":focusable" ).first();
|
10609
10898
|
|
10610
10899
|
this._ui.container.addClass( "ui-popup-active" );
|
10611
10900
|
this._isOpen = true;
|
10612
10901
|
this._resizeScreen();
|
10613
|
-
|
10902
|
+
|
10903
|
+
// Check to see if currElement is not a child of the container. If it's not, blur
|
10904
|
+
if ( !$.contains( this._ui.container[ 0 ], this.document[ 0 ].activeElement ) ) {
|
10905
|
+
this._safelyBlur( this.document[ 0 ].activeElement );
|
10906
|
+
}
|
10907
|
+
if ( firstFocus.length > 0 ) {
|
10908
|
+
this._ui.focusElement = firstFocus;
|
10909
|
+
}
|
10614
10910
|
this._ignoreResizeEvents();
|
10615
10911
|
if ( id ) {
|
10616
10912
|
this.document.find( "[aria-haspopup='true'][aria-owns='" + id + "']" ).attr( "aria-expanded", true );
|
@@ -10695,8 +10991,6 @@ $.widget( "mobile.popup", {
|
|
10695
10991
|
var container = this._ui.container,
|
10696
10992
|
id = this.element.attr( "id" );
|
10697
10993
|
|
10698
|
-
container.removeAttr( "tabindex" );
|
10699
|
-
|
10700
10994
|
// remove the global mutex for popups
|
10701
10995
|
$.mobile.popup.active = undefined;
|
10702
10996
|
|
@@ -10876,11 +11170,6 @@ $.widget( "mobile.popup", {
|
|
10876
11170
|
url = $.mobile.path.parseLocation().hash + hashkey;
|
10877
11171
|
}
|
10878
11172
|
|
10879
|
-
// Tack on an extra hashkey if this is the first page and we've just reconstructed the initial hash
|
10880
|
-
if ( urlHistory.activeIndex === 0 && url === urlHistory.initialDst ) {
|
10881
|
-
url += hashkey;
|
10882
|
-
}
|
10883
|
-
|
10884
11173
|
// swallow the the initial navigation event, and bind for the next
|
10885
11174
|
this.window.one( "beforenavigate", function( theEvent ) {
|
10886
11175
|
theEvent.preventDefault();
|
@@ -10993,7 +11282,7 @@ $.widget( "mobile.selectmenu", $.mobile.selectmenu, {
|
|
10993
11282
|
},
|
10994
11283
|
|
10995
11284
|
_handleButtonVclickKeydown: function( event ) {
|
10996
|
-
if ( this.options.disabled || this.isOpen ) {
|
11285
|
+
if ( this.options.disabled || this.isOpen || this.options.nativeMenu ) {
|
10997
11286
|
return;
|
10998
11287
|
}
|
10999
11288
|
|
@@ -11044,6 +11333,10 @@ $.widget( "mobile.selectmenu", $.mobile.selectmenu, {
|
|
11044
11333
|
},
|
11045
11334
|
|
11046
11335
|
_handleMenuPageHide: function() {
|
11336
|
+
|
11337
|
+
// After the dialog's done, we may want to trigger change if the value has actually changed
|
11338
|
+
this._delayedTrigger();
|
11339
|
+
|
11047
11340
|
// TODO centralize page removal binding / handling in the page plugin.
|
11048
11341
|
// Suggestion from @jblas to do refcounting
|
11049
11342
|
//
|
@@ -11066,18 +11359,55 @@ $.widget( "mobile.selectmenu", $.mobile.selectmenu, {
|
|
11066
11359
|
}
|
11067
11360
|
},
|
11068
11361
|
|
11362
|
+
_handleListItemClick: function( event ) {
|
11363
|
+
var listItem = $( event.target ).closest( "li" ),
|
11364
|
+
|
11365
|
+
// Index of option tag to be selected
|
11366
|
+
oldIndex = this.select[ 0 ].selectedIndex,
|
11367
|
+
newIndex = $.mobile.getAttribute( listItem, "option-index" ),
|
11368
|
+
option = this._selectOptions().eq( newIndex )[ 0 ];
|
11369
|
+
|
11370
|
+
// Toggle selected status on the tag for multi selects
|
11371
|
+
option.selected = this.isMultiple ? !option.selected : true;
|
11372
|
+
|
11373
|
+
// Toggle checkbox class for multiple selects
|
11374
|
+
if ( this.isMultiple ) {
|
11375
|
+
listItem.find( "a" )
|
11376
|
+
.toggleClass( "ui-checkbox-on", option.selected )
|
11377
|
+
.toggleClass( "ui-checkbox-off", !option.selected );
|
11378
|
+
}
|
11379
|
+
|
11380
|
+
// If it's not a multiple select, trigger change after it has finished closing
|
11381
|
+
if ( !this.isMultiple && oldIndex !== newIndex ) {
|
11382
|
+
this._triggerChange = true;
|
11383
|
+
}
|
11384
|
+
|
11385
|
+
// Trigger change if it's a multiple select
|
11386
|
+
// Hide custom select for single selects only - otherwise focus clicked item
|
11387
|
+
// We need to grab the clicked item the hard way, because the list may have been rebuilt
|
11388
|
+
if ( this.isMultiple ) {
|
11389
|
+
this.select.trigger( "change" );
|
11390
|
+
this.list.find( "li:not(.ui-li-divider)" ).eq( newIndex )
|
11391
|
+
.find( "a" ).first().focus();
|
11392
|
+
}
|
11393
|
+
else {
|
11394
|
+
this.close();
|
11395
|
+
}
|
11396
|
+
|
11397
|
+
event.preventDefault();
|
11398
|
+
},
|
11399
|
+
|
11069
11400
|
build: function() {
|
11070
11401
|
var selectId, popupId, dialogId, label, thisPage, isMultiple, menuId,
|
11071
11402
|
themeAttr, overlayTheme, overlayThemeAttr, dividerThemeAttr,
|
11072
11403
|
menuPage, listbox, list, header, headerTitle, menuPageContent,
|
11073
|
-
menuPageClose, headerClose,
|
11404
|
+
menuPageClose, headerClose,
|
11074
11405
|
o = this.options;
|
11075
11406
|
|
11076
11407
|
if ( o.nativeMenu ) {
|
11077
11408
|
return this._super();
|
11078
11409
|
}
|
11079
11410
|
|
11080
|
-
self = this;
|
11081
11411
|
selectId = this.selectId;
|
11082
11412
|
popupId = selectId + "-listbox";
|
11083
11413
|
dialogId = selectId + "-dialog";
|
@@ -11092,11 +11422,14 @@ $.widget( "mobile.selectmenu", $.mobile.selectmenu, {
|
|
11092
11422
|
dividerThemeAttr = ( o.dividerTheme && isMultiple ) ? ( " data-" + $.mobile.ns + "divider-theme='" + o.dividerTheme + "'" ) : "";
|
11093
11423
|
menuPage = $( "<div data-" + $.mobile.ns + "role='dialog' class='ui-selectmenu' id='" + dialogId + "'" + themeAttr + overlayThemeAttr + ">" +
|
11094
11424
|
"<div data-" + $.mobile.ns + "role='header'>" +
|
11095
|
-
"<div class='ui-title'
|
11425
|
+
"<div class='ui-title'></div>"+
|
11096
11426
|
"</div>"+
|
11097
11427
|
"<div data-" + $.mobile.ns + "role='content'></div>"+
|
11098
11428
|
"</div>" );
|
11099
|
-
listbox = $( "<div
|
11429
|
+
listbox = $( "<div" + themeAttr + overlayThemeAttr + " id='" + popupId +
|
11430
|
+
"' class='ui-selectmenu'></div>" )
|
11431
|
+
.insertAfter( this.select )
|
11432
|
+
.popup();
|
11100
11433
|
list = $( "<ul class='ui-selectmenu-list' id='" + menuId + "' role='listbox' aria-labelledby='" + this.buttonId + "'" + themeAttr + dividerThemeAttr + "></ul>" ).appendTo( listbox );
|
11101
11434
|
header = $( "<div class='ui-header ui-bar-" + ( o.theme ? o.theme : "inherit" ) + "'></div>" ).prependTo( listbox );
|
11102
11435
|
headerTitle = $( "<h1 class='ui-title'></h1>" ).appendTo( header );
|
@@ -11152,52 +11485,18 @@ $.widget( "mobile.selectmenu", $.mobile.selectmenu, {
|
|
11152
11485
|
// Events for list items
|
11153
11486
|
this.list.attr( "role", "listbox" );
|
11154
11487
|
this._on( this.list, {
|
11155
|
-
focusin
|
11156
|
-
focusout
|
11157
|
-
keydown: "_handleListKeydown"
|
11488
|
+
"focusin": "_handleListFocus",
|
11489
|
+
"focusout": "_handleListFocus",
|
11490
|
+
"keydown": "_handleListKeydown",
|
11491
|
+
"click li:not(.ui-disabled,.ui-state-disabled,.ui-li-divider)": "_handleListItemClick"
|
11158
11492
|
});
|
11159
|
-
this.list
|
11160
|
-
.delegate( "li:not(.ui-disabled,.ui-state-disabled,.ui-li-divider)", "click", function( event ) {
|
11161
|
-
|
11162
|
-
// index of option tag to be selected
|
11163
|
-
var oldIndex = self.select[ 0 ].selectedIndex,
|
11164
|
-
newIndex = $.mobile.getAttribute( this, "option-index" ),
|
11165
|
-
option = self._selectOptions().eq( newIndex )[ 0 ];
|
11166
|
-
|
11167
|
-
// toggle selected status on the tag for multi selects
|
11168
|
-
option.selected = self.isMultiple ? !option.selected : true;
|
11169
|
-
|
11170
|
-
// toggle checkbox class for multiple selects
|
11171
|
-
if ( self.isMultiple ) {
|
11172
|
-
$( this ).find( "a" )
|
11173
|
-
.toggleClass( "ui-checkbox-on", option.selected )
|
11174
|
-
.toggleClass( "ui-checkbox-off", !option.selected );
|
11175
|
-
}
|
11176
|
-
|
11177
|
-
// trigger change if value changed
|
11178
|
-
if ( self.isMultiple || oldIndex !== newIndex ) {
|
11179
|
-
self.select.trigger( "change" );
|
11180
|
-
}
|
11181
|
-
|
11182
|
-
// hide custom select for single selects only - otherwise focus clicked item
|
11183
|
-
// We need to grab the clicked item the hard way, because the list may have been rebuilt
|
11184
|
-
if ( self.isMultiple ) {
|
11185
|
-
self.list.find( "li:not(.ui-li-divider)" ).eq( newIndex )
|
11186
|
-
.find( "a" ).first().focus();
|
11187
|
-
}
|
11188
|
-
else {
|
11189
|
-
self.close();
|
11190
|
-
}
|
11191
|
-
|
11192
|
-
event.preventDefault();
|
11193
|
-
});
|
11194
11493
|
|
11195
11494
|
// button refocus ensures proper height calculation
|
11196
11495
|
// by removing the inline style and ensuring page inclusion
|
11197
11496
|
this._on( this.menuPage, { pagehide: "_handleMenuPageHide" } );
|
11198
11497
|
|
11199
11498
|
// Events on the popup
|
11200
|
-
this._on( this.listbox, { popupafterclose: "
|
11499
|
+
this._on( this.listbox, { popupafterclose: "_popupClosed" } );
|
11201
11500
|
|
11202
11501
|
// Close button on small overlays
|
11203
11502
|
if ( this.isMultiple ) {
|
@@ -11207,6 +11506,18 @@ $.widget( "mobile.selectmenu", $.mobile.selectmenu, {
|
|
11207
11506
|
return this;
|
11208
11507
|
},
|
11209
11508
|
|
11509
|
+
_popupClosed: function() {
|
11510
|
+
this.close();
|
11511
|
+
this._delayedTrigger();
|
11512
|
+
},
|
11513
|
+
|
11514
|
+
_delayedTrigger: function() {
|
11515
|
+
if ( this._triggerChange ) {
|
11516
|
+
this.element.trigger( "change" );
|
11517
|
+
}
|
11518
|
+
this._triggerChange = false;
|
11519
|
+
},
|
11520
|
+
|
11210
11521
|
_isRebuildRequired: function() {
|
11211
11522
|
var list = this.list.find( "li" ),
|
11212
11523
|
options = this._selectOptions().not( ".ui-screen-hidden" );
|
@@ -11242,9 +11553,8 @@ $.widget( "mobile.selectmenu", $.mobile.selectmenu, {
|
|
11242
11553
|
.find( "a" ).removeClass( $.mobile.activeBtnClass ).end()
|
11243
11554
|
.attr( "aria-selected", false )
|
11244
11555
|
.each(function( i ) {
|
11245
|
-
|
11556
|
+
var item = $( this );
|
11246
11557
|
if ( $.inArray( i, indices ) > -1 ) {
|
11247
|
-
var item = $( this );
|
11248
11558
|
|
11249
11559
|
// Aria selected attr
|
11250
11560
|
item.attr( "aria-selected", true );
|
@@ -11259,6 +11569,8 @@ $.widget( "mobile.selectmenu", $.mobile.selectmenu, {
|
|
11259
11569
|
item.find( "a" ).addClass( $.mobile.activeBtnClass );
|
11260
11570
|
}
|
11261
11571
|
}
|
11572
|
+
} else if ( self.isMultiple ) {
|
11573
|
+
item.find( "a" ).removeClass( "ui-checkbox-on" ).addClass( "ui-checkbox-off" );
|
11262
11574
|
}
|
11263
11575
|
});
|
11264
11576
|
},
|
@@ -11328,7 +11640,9 @@ $.widget( "mobile.selectmenu", $.mobile.selectmenu, {
|
|
11328
11640
|
|
11329
11641
|
self.menuType = "page";
|
11330
11642
|
self.menuPageContent.append( self.list );
|
11331
|
-
self.menuPage
|
11643
|
+
self.menuPage
|
11644
|
+
.find( "div .ui-title" )
|
11645
|
+
.text( self.label.getEncodedText() || self.placeholder );
|
11332
11646
|
} else {
|
11333
11647
|
self.menuType = "overlay";
|
11334
11648
|
|
@@ -11370,10 +11684,15 @@ $.widget( "mobile.selectmenu", $.mobile.selectmenu, {
|
|
11370
11684
|
}
|
11371
11685
|
|
11372
11686
|
parent = option.parentNode;
|
11373
|
-
text = $option.text();
|
11374
|
-
anchor = document.createElement( "a" );
|
11375
11687
|
classes = [];
|
11376
11688
|
|
11689
|
+
// Although using .text() here raises the risk that, when we later paste this into the
|
11690
|
+
// list item we end up pasting possibly malicious things like <script> tags, that risk
|
11691
|
+
// only arises if we do something like $( "<li><a href='#'>" + text + "</a></li>" ). We
|
11692
|
+
// don't do that. We do document.createTextNode( text ) instead, which guarantees that
|
11693
|
+
// whatever we paste in will end up as text, with characters like <, > and & escaped.
|
11694
|
+
text = $option.text();
|
11695
|
+
anchor = document.createElement( "a" );
|
11377
11696
|
anchor.setAttribute( "href", "#" );
|
11378
11697
|
anchor.appendChild( document.createTextNode( text ) );
|
11379
11698
|
|
@@ -11744,7 +12063,7 @@ $.fn.buttonMarkup.defaults = {
|
|
11744
12063
|
};
|
11745
12064
|
|
11746
12065
|
$.extend( $.fn.buttonMarkup, {
|
11747
|
-
initSelector: "a:jqmData(role='button'), .ui-bar > a, .ui-bar > :jqmData(role='controlgroup') > a, button"
|
12066
|
+
initSelector: "a:jqmData(role='button'), .ui-bar > a, .ui-bar > :jqmData(role='controlgroup') > a, button:not(:jqmData(role='navbar') button)"
|
11748
12067
|
});
|
11749
12068
|
|
11750
12069
|
})( jQuery );
|
@@ -11765,16 +12084,22 @@ $.widget( "mobile.controlgroup", $.extend( {
|
|
11765
12084
|
|
11766
12085
|
_create: function() {
|
11767
12086
|
var elem = this.element,
|
11768
|
-
opts = this.options
|
12087
|
+
opts = this.options,
|
12088
|
+
keepNative = $.mobile.page.prototype.keepNativeSelector();
|
11769
12089
|
|
11770
12090
|
// Run buttonmarkup
|
11771
12091
|
if ( $.fn.buttonMarkup ) {
|
11772
|
-
this.element
|
12092
|
+
this.element
|
12093
|
+
.find( $.fn.buttonMarkup.initSelector )
|
12094
|
+
.not( keepNative )
|
12095
|
+
.buttonMarkup();
|
11773
12096
|
}
|
11774
12097
|
// Enhance child widgets
|
11775
12098
|
$.each( this._childWidgets, $.proxy( function( number, widgetName ) {
|
11776
12099
|
if ( $.mobile[ widgetName ] ) {
|
11777
|
-
this.element
|
12100
|
+
this.element
|
12101
|
+
.find( $.mobile[ widgetName ].initSelector )
|
12102
|
+
.not( keepNative )[ widgetName ]();
|
11778
12103
|
}
|
11779
12104
|
}, this ));
|
11780
12105
|
|
@@ -11945,8 +12270,7 @@ $.widget( "mobile.controlgroup", $.extend( {
|
|
11945
12270
|
role: role,
|
11946
12271
|
page: page,
|
11947
12272
|
leftbtn: leftbtn,
|
11948
|
-
rightbtn: rightbtn
|
11949
|
-
backBtn: null
|
12273
|
+
rightbtn: rightbtn
|
11950
12274
|
});
|
11951
12275
|
this.element.attr( "role", role === "header" ? "banner" : "contentinfo" ).addClass( "ui-" + role );
|
11952
12276
|
this.refresh();
|
@@ -11954,15 +12278,7 @@ $.widget( "mobile.controlgroup", $.extend( {
|
|
11954
12278
|
},
|
11955
12279
|
_setOptions: function( o ) {
|
11956
12280
|
if ( o.addBackBtn !== undefined ) {
|
11957
|
-
|
11958
|
-
this.role === "header" &&
|
11959
|
-
$( ".ui-page" ).length > 1 &&
|
11960
|
-
this.page[ 0 ].getAttribute( "data-" + $.mobile.ns + "url" ) !== $.mobile.path.stripHash( location.hash ) &&
|
11961
|
-
!this.leftbtn ) {
|
11962
|
-
this._addBackButton();
|
11963
|
-
} else {
|
11964
|
-
this.element.find( ".ui-toolbar-back-btn" ).remove();
|
11965
|
-
}
|
12281
|
+
this._updateBackButton();
|
11966
12282
|
}
|
11967
12283
|
if ( o.backBtnTheme != null ) {
|
11968
12284
|
this.element
|
@@ -11989,6 +12305,8 @@ $.widget( "mobile.controlgroup", $.extend( {
|
|
11989
12305
|
this._setRelative();
|
11990
12306
|
if ( this.role === "footer" ) {
|
11991
12307
|
this.element.appendTo( "body" );
|
12308
|
+
} else if ( this.role === "header" ) {
|
12309
|
+
this._updateBackButton();
|
11992
12310
|
}
|
11993
12311
|
}
|
11994
12312
|
this._addHeadingClasses();
|
@@ -12010,27 +12328,70 @@ $.widget( "mobile.controlgroup", $.extend( {
|
|
12010
12328
|
},
|
12011
12329
|
// Deprecated in 1.4. As from 1.5 ui-btn-left/right classes have to be present in the markup.
|
12012
12330
|
_addHeaderButtonClasses: function() {
|
12013
|
-
var
|
12014
|
-
this.leftbtn = $headeranchors.hasClass( "ui-btn-left" );
|
12015
|
-
this.rightbtn = $headeranchors.hasClass( "ui-btn-right" );
|
12331
|
+
var headerAnchors = this.element.children( "a, button" );
|
12016
12332
|
|
12017
|
-
|
12333
|
+
// Do not mistake a back button for a left toolbar button
|
12334
|
+
this.leftbtn = headerAnchors.hasClass( "ui-btn-left" ) &&
|
12335
|
+
!headerAnchors.hasClass( "ui-toolbar-back-btn" );
|
12018
12336
|
|
12019
|
-
this.rightbtn =
|
12337
|
+
this.rightbtn = headerAnchors.hasClass( "ui-btn-right" );
|
12020
12338
|
|
12021
|
-
|
12022
|
-
|
12023
|
-
|
12024
|
-
|
12339
|
+
// Filter out right buttons and back buttons
|
12340
|
+
this.leftbtn = this.leftbtn ||
|
12341
|
+
headerAnchors.eq( 0 )
|
12342
|
+
.not( ".ui-btn-right,.ui-toolbar-back-btn" )
|
12343
|
+
.addClass( "ui-btn-left" )
|
12344
|
+
.length;
|
12025
12345
|
|
12026
|
-
|
12346
|
+
this.rightbtn = this.rightbtn || headerAnchors.eq( 1 ).addClass( "ui-btn-right" ).length;
|
12347
|
+
},
|
12348
|
+
_updateBackButton: function() {
|
12349
|
+
var backButton,
|
12350
|
+
options = this.options,
|
12027
12351
|
theme = options.backBtnTheme || options.theme;
|
12028
|
-
|
12029
|
-
|
12030
|
-
|
12031
|
-
|
12032
|
-
|
12033
|
-
|
12352
|
+
|
12353
|
+
// Retrieve the back button or create a new, empty one
|
12354
|
+
backButton = this._backButton = ( this._backButton || {} );
|
12355
|
+
|
12356
|
+
// We add a back button only if the option to do so is on
|
12357
|
+
if ( this.options.addBackBtn &&
|
12358
|
+
|
12359
|
+
// This must also be a header toolbar
|
12360
|
+
this.role === "header" &&
|
12361
|
+
|
12362
|
+
// There must be multiple pages in the DOM
|
12363
|
+
$( ".ui-page" ).length > 1 &&
|
12364
|
+
( this.page ?
|
12365
|
+
|
12366
|
+
// If the toolbar is internal the page's URL must differ from the hash
|
12367
|
+
( this.page[ 0 ].getAttribute( "data-" + $.mobile.ns + "url" ) !==
|
12368
|
+
$.mobile.path.stripHash( location.hash ) ) :
|
12369
|
+
|
12370
|
+
// Otherwise, if the toolbar is external there must be at least one
|
12371
|
+
// history item to which one can go back
|
12372
|
+
( $.mobile.navigate && $.mobile.navigate.history &&
|
12373
|
+
$.mobile.navigate.history.activeIndex > 0 ) ) &&
|
12374
|
+
|
12375
|
+
// The toolbar does not have a left button
|
12376
|
+
!this.leftbtn ) {
|
12377
|
+
|
12378
|
+
// Skip back button creation if one is already present
|
12379
|
+
if ( !backButton.attached ) {
|
12380
|
+
this.backButton = backButton.element = ( backButton.element ||
|
12381
|
+
$( "<a role='button' href='javascript:void(0);' " +
|
12382
|
+
"class='ui-btn ui-corner-all ui-shadow ui-btn-left " +
|
12383
|
+
( theme ? "ui-btn-" + theme + " " : "" ) +
|
12384
|
+
"ui-toolbar-back-btn ui-icon-carat-l ui-btn-icon-left' " +
|
12385
|
+
"data-" + $.mobile.ns + "rel='back'>" + options.backBtnText +
|
12386
|
+
"</a>" ) )
|
12387
|
+
.prependTo( this.element );
|
12388
|
+
backButton.attached = true;
|
12389
|
+
}
|
12390
|
+
|
12391
|
+
// If we are not adding a back button, then remove the one present, if any
|
12392
|
+
} else if ( backButton.element ) {
|
12393
|
+
backButton.element.detach();
|
12394
|
+
backButton.attached = false;
|
12034
12395
|
}
|
12035
12396
|
},
|
12036
12397
|
_addHeadingClasses: function() {
|
@@ -12041,6 +12402,27 @@ $.widget( "mobile.controlgroup", $.extend( {
|
|
12041
12402
|
"role": "heading",
|
12042
12403
|
"aria-level": "1"
|
12043
12404
|
});
|
12405
|
+
},
|
12406
|
+
_destroy: function() {
|
12407
|
+
var currentTheme;
|
12408
|
+
|
12409
|
+
this.element.children( "h1, h2, h3, h4, h5, h6" )
|
12410
|
+
.removeClass( "ui-title" )
|
12411
|
+
.removeAttr( "role" )
|
12412
|
+
.removeAttr( "aria-level" );
|
12413
|
+
|
12414
|
+
if ( this.role === "header" ) {
|
12415
|
+
this.element.children( "a, button" )
|
12416
|
+
.removeClass( "ui-btn-left ui-btn-right ui-btn ui-shadow ui-corner-all" );
|
12417
|
+
if ( this.backButton) {
|
12418
|
+
this.backButton.remove();
|
12419
|
+
}
|
12420
|
+
}
|
12421
|
+
|
12422
|
+
currentTheme = this.options.theme ? this.options.theme : "inherit";
|
12423
|
+
this.element.removeClass( "ui-bar-" + currentTheme );
|
12424
|
+
|
12425
|
+
this.element.removeClass( "ui-" + this.role ).removeAttr( "role" );
|
12044
12426
|
}
|
12045
12427
|
});
|
12046
12428
|
|
@@ -12074,6 +12456,7 @@ $.widget( "mobile.controlgroup", $.extend( {
|
|
12074
12456
|
|
12075
12457
|
_create: function() {
|
12076
12458
|
this._super();
|
12459
|
+
this.pagecontainer = $( ":mobile-pagecontainer" );
|
12077
12460
|
if ( this.options.position === "fixed" && !this.options.supportBlacklist() ) {
|
12078
12461
|
this._makeFixed();
|
12079
12462
|
}
|
@@ -12085,7 +12468,6 @@ $.widget( "mobile.controlgroup", $.extend( {
|
|
12085
12468
|
this._addTransitionClass();
|
12086
12469
|
this._bindPageEvents();
|
12087
12470
|
this._bindToggleHandlers();
|
12088
|
-
this._setOptions( this.options );
|
12089
12471
|
},
|
12090
12472
|
|
12091
12473
|
_setOptions: function( o ) {
|
@@ -12317,12 +12699,30 @@ $.widget( "mobile.controlgroup", $.extend( {
|
|
12317
12699
|
},
|
12318
12700
|
|
12319
12701
|
_destroy: function() {
|
12320
|
-
var
|
12321
|
-
|
12702
|
+
var pageClasses, toolbarClasses, hasFixed, header, hasFullscreen,
|
12703
|
+
page = this.pagecontainer.pagecontainer( "getActivePage" );
|
12322
12704
|
|
12323
|
-
|
12324
|
-
|
12325
|
-
|
12705
|
+
this._super();
|
12706
|
+
if ( this.options.position === "fixed" ) {
|
12707
|
+
hasFixed = $( "body>.ui-" + this.role + "-fixed" )
|
12708
|
+
.add( page.find( ".ui-" + this.options.role + "-fixed" ) )
|
12709
|
+
.not( this.element ).length > 0;
|
12710
|
+
hasFullscreen = $( "body>.ui-" + this.role + "-fixed" )
|
12711
|
+
.add( page.find( ".ui-" + this.options.role + "-fullscreen" ) )
|
12712
|
+
.not( this.element ).length > 0;
|
12713
|
+
toolbarClasses = "ui-header-fixed ui-footer-fixed ui-header-fullscreen in out" +
|
12714
|
+
" ui-footer-fullscreen fade slidedown slideup ui-fixed-hidden";
|
12715
|
+
this.element.removeClass( toolbarClasses );
|
12716
|
+
if ( !hasFullscreen ) {
|
12717
|
+
pageClasses = "ui-page-" + this.role + "-fullscreen";
|
12718
|
+
}
|
12719
|
+
if ( !hasFixed ) {
|
12720
|
+
header = this.role === "header";
|
12721
|
+
pageClasses += " ui-page-" + this.role + "-fixed";
|
12722
|
+
page.css( "padding-" + ( header ? "top" : "bottom" ), "" );
|
12723
|
+
}
|
12724
|
+
page.removeClass( pageClasses );
|
12725
|
+
}
|
12326
12726
|
}
|
12327
12727
|
|
12328
12728
|
});
|
@@ -12680,7 +13080,6 @@ $.widget( "mobile.panel", {
|
|
12680
13080
|
positionFixed: false
|
12681
13081
|
},
|
12682
13082
|
|
12683
|
-
_panelID: null,
|
12684
13083
|
_closeLink: null,
|
12685
13084
|
_parentPage: null,
|
12686
13085
|
_page: null,
|
@@ -12691,19 +13090,20 @@ $.widget( "mobile.panel", {
|
|
12691
13090
|
|
12692
13091
|
_create: function() {
|
12693
13092
|
var el = this.element,
|
12694
|
-
parentPage = el.closest( ":jqmData(role='page')" );
|
13093
|
+
parentPage = el.closest( ".ui-page, :jqmData(role='page')" );
|
12695
13094
|
|
12696
13095
|
// expose some private props to other methods
|
12697
13096
|
$.extend( this, {
|
12698
|
-
_panelID: el.attr( "id" ),
|
12699
13097
|
_closeLink: el.find( ":jqmData(rel='close')" ),
|
12700
13098
|
_parentPage: ( parentPage.length > 0 ) ? parentPage : false,
|
13099
|
+
_openedPage: null,
|
12701
13100
|
_page: this._getPage,
|
12702
13101
|
_panelInner: this._getPanelInner(),
|
12703
|
-
_wrapper: this._getWrapper,
|
12704
13102
|
_fixedToolbars: this._getFixedToolbars
|
12705
13103
|
});
|
12706
|
-
|
13104
|
+
if ( this.options.display !== "overlay" ){
|
13105
|
+
this._getWrapper();
|
13106
|
+
}
|
12707
13107
|
this._addPanelClasses();
|
12708
13108
|
|
12709
13109
|
// if animating, add the class to do so
|
@@ -12737,7 +13137,7 @@ $.widget( "mobile.panel", {
|
|
12737
13137
|
var self = this,
|
12738
13138
|
target = self._parentPage ? self._parentPage.parent() : self.element.parent();
|
12739
13139
|
|
12740
|
-
self._modal = $( "<div class='" + self.options.classes.modal + "'
|
13140
|
+
self._modal = $( "<div class='" + self.options.classes.modal + "'></div>" )
|
12741
13141
|
.on( "mousedown", function() {
|
12742
13142
|
self.close();
|
12743
13143
|
})
|
@@ -12745,21 +13145,20 @@ $.widget( "mobile.panel", {
|
|
12745
13145
|
},
|
12746
13146
|
|
12747
13147
|
_getPage: function() {
|
12748
|
-
var page = this.
|
13148
|
+
var page = this._openedPage || this._parentPage || $( "." + $.mobile.activePageClass );
|
12749
13149
|
|
12750
13150
|
return page;
|
12751
13151
|
},
|
12752
13152
|
|
12753
13153
|
_getWrapper: function() {
|
12754
13154
|
var wrapper = this._page().find( "." + this.options.classes.pageWrapper );
|
12755
|
-
|
12756
13155
|
if ( wrapper.length === 0 ) {
|
12757
13156
|
wrapper = this._page().children( ".ui-header:not(.ui-header-fixed), .ui-content:not(.ui-popup), .ui-footer:not(.ui-footer-fixed)" )
|
12758
13157
|
.wrapAll( "<div class='" + this.options.classes.pageWrapper + "'></div>" )
|
12759
13158
|
.parent();
|
12760
13159
|
}
|
12761
13160
|
|
12762
|
-
|
13161
|
+
this._wrapper = wrapper;
|
12763
13162
|
},
|
12764
13163
|
|
12765
13164
|
_getFixedToolbars: function() {
|
@@ -12791,14 +13190,6 @@ $.widget( "mobile.panel", {
|
|
12791
13190
|
this.element.addClass( this._getPanelClasses() );
|
12792
13191
|
},
|
12793
13192
|
|
12794
|
-
_handleCloseClickAndEatEvent: function( event ) {
|
12795
|
-
if ( !event.isDefaultPrevented() ) {
|
12796
|
-
event.preventDefault();
|
12797
|
-
this.close();
|
12798
|
-
return false;
|
12799
|
-
}
|
12800
|
-
},
|
12801
|
-
|
12802
13193
|
_handleCloseClick: function( event ) {
|
12803
13194
|
if ( !event.isDefaultPrevented() ) {
|
12804
13195
|
this.close();
|
@@ -12815,7 +13206,7 @@ $.widget( "mobile.panel", {
|
|
12815
13206
|
});
|
12816
13207
|
},
|
12817
13208
|
|
12818
|
-
_positionPanel: function() {
|
13209
|
+
_positionPanel: function( scrollToTop ) {
|
12819
13210
|
var self = this,
|
12820
13211
|
panelInnerHeight = self._panelInner.outerHeight(),
|
12821
13212
|
expand = panelInnerHeight > $.mobile.getScreenHeight();
|
@@ -12825,7 +13216,9 @@ $.widget( "mobile.panel", {
|
|
12825
13216
|
self._unfixPanel();
|
12826
13217
|
$.mobile.resetActivePageHeight( panelInnerHeight );
|
12827
13218
|
}
|
12828
|
-
|
13219
|
+
if ( scrollToTop ) {
|
13220
|
+
this.window[ 0 ].scrollTo( 0, $.mobile.defaultHomeScroll );
|
13221
|
+
}
|
12829
13222
|
} else {
|
12830
13223
|
self._fixPanel();
|
12831
13224
|
}
|
@@ -12869,9 +13262,13 @@ $.widget( "mobile.panel", {
|
|
12869
13262
|
},
|
12870
13263
|
|
12871
13264
|
_handleClick: function( e ) {
|
12872
|
-
|
13265
|
+
var link,
|
13266
|
+
panelId = this.element.attr( "id" );
|
13267
|
+
|
13268
|
+
if ( e.currentTarget.href.split( "#" )[ 1 ] === panelId && panelId !== undefined ) {
|
13269
|
+
|
12873
13270
|
e.preventDefault();
|
12874
|
-
|
13271
|
+
link = $( e.target );
|
12875
13272
|
if ( link.hasClass( "ui-btn" ) ) {
|
12876
13273
|
link.addClass( $.mobile.activeBtnClass );
|
12877
13274
|
this.element.one( "panelopen panelclose", function() {
|
@@ -12879,7 +13276,6 @@ $.widget( "mobile.panel", {
|
|
12879
13276
|
});
|
12880
13277
|
}
|
12881
13278
|
this.toggle();
|
12882
|
-
return false;
|
12883
13279
|
}
|
12884
13280
|
},
|
12885
13281
|
|
@@ -12917,7 +13313,14 @@ $.widget( "mobile.panel", {
|
|
12917
13313
|
self.close();
|
12918
13314
|
}
|
12919
13315
|
});
|
12920
|
-
|
13316
|
+
if ( !this._parentPage && this.options.display !== "overlay" ) {
|
13317
|
+
this._on( this.document, {
|
13318
|
+
"pageshow": function() {
|
13319
|
+
this._openedPage = null;
|
13320
|
+
this._getWrapper();
|
13321
|
+
}
|
13322
|
+
});
|
13323
|
+
}
|
12921
13324
|
// Clean up open panels after page hide
|
12922
13325
|
if ( self._parentPage ) {
|
12923
13326
|
this.document.on( "pagehide", ":jqmData(role='page')", function() {
|
@@ -12945,16 +13348,17 @@ $.widget( "mobile.panel", {
|
|
12945
13348
|
o = self.options,
|
12946
13349
|
|
12947
13350
|
_openPanel = function() {
|
12948
|
-
self.
|
13351
|
+
self._off( self.document , "panelclose" );
|
12949
13352
|
self._page().jqmData( "panel", "open" );
|
12950
13353
|
|
12951
13354
|
if ( $.support.cssTransform3d && !!o.animate && o.display !== "overlay" ) {
|
12952
|
-
self._wrapper
|
13355
|
+
self._wrapper.addClass( o.classes.animate );
|
12953
13356
|
self._fixedToolbars().addClass( o.classes.animate );
|
12954
13357
|
}
|
12955
13358
|
|
12956
13359
|
if ( !immediate && $.support.cssTransform3d && !!o.animate ) {
|
12957
|
-
self.
|
13360
|
+
( self._wrapper || self.element )
|
13361
|
+
.animationComplete( complete, "transition" );
|
12958
13362
|
} else {
|
12959
13363
|
setTimeout( complete, 0 );
|
12960
13364
|
}
|
@@ -12968,13 +13372,13 @@ $.widget( "mobile.panel", {
|
|
12968
13372
|
.removeClass( o.classes.panelClosed )
|
12969
13373
|
.addClass( o.classes.panelOpen );
|
12970
13374
|
|
12971
|
-
self._positionPanel();
|
13375
|
+
self._positionPanel( true );
|
12972
13376
|
|
12973
13377
|
self._pageContentOpenClasses = self._getPosDisplayClasses( o.classes.pageContentPrefix );
|
12974
13378
|
|
12975
13379
|
if ( o.display !== "overlay" ) {
|
12976
13380
|
self._page().parent().addClass( o.classes.pageContainer );
|
12977
|
-
self._wrapper
|
13381
|
+
self._wrapper.addClass( self._pageContentOpenClasses );
|
12978
13382
|
self._fixedToolbars().addClass( self._pageContentOpenClasses );
|
12979
13383
|
}
|
12980
13384
|
|
@@ -12987,21 +13391,28 @@ $.widget( "mobile.panel", {
|
|
12987
13391
|
},
|
12988
13392
|
complete = function() {
|
12989
13393
|
|
13394
|
+
// Bail if the panel was closed before the opening animation has completed
|
13395
|
+
if ( !self._open ) {
|
13396
|
+
return;
|
13397
|
+
}
|
13398
|
+
|
12990
13399
|
if ( o.display !== "overlay" ) {
|
12991
|
-
self._wrapper
|
13400
|
+
self._wrapper.addClass( o.classes.pageContentPrefix + "-open" );
|
12992
13401
|
self._fixedToolbars().addClass( o.classes.pageContentPrefix + "-open" );
|
12993
13402
|
}
|
12994
13403
|
|
12995
13404
|
self._bindFixListener();
|
12996
13405
|
|
12997
13406
|
self._trigger( "open" );
|
13407
|
+
|
13408
|
+
self._openedPage = self._page();
|
12998
13409
|
};
|
12999
13410
|
|
13000
13411
|
self._trigger( "beforeopen" );
|
13001
13412
|
|
13002
13413
|
if ( self._page().jqmData( "panel" ) === "open" ) {
|
13003
|
-
self.
|
13004
|
-
_openPanel
|
13414
|
+
self._on( self.document, {
|
13415
|
+
"panelclose": _openPanel
|
13005
13416
|
});
|
13006
13417
|
} else {
|
13007
13418
|
_openPanel();
|
@@ -13021,18 +13432,21 @@ $.widget( "mobile.panel", {
|
|
13021
13432
|
self.element.removeClass( o.classes.panelOpen );
|
13022
13433
|
|
13023
13434
|
if ( o.display !== "overlay" ) {
|
13024
|
-
self._wrapper
|
13435
|
+
self._wrapper.removeClass( self._pageContentOpenClasses );
|
13025
13436
|
self._fixedToolbars().removeClass( self._pageContentOpenClasses );
|
13026
13437
|
}
|
13027
13438
|
|
13028
13439
|
if ( !immediate && $.support.cssTransform3d && !!o.animate ) {
|
13029
|
-
self.
|
13440
|
+
( self._wrapper || self.element )
|
13441
|
+
.animationComplete( complete, "transition" );
|
13030
13442
|
} else {
|
13031
13443
|
setTimeout( complete, 0 );
|
13032
13444
|
}
|
13033
13445
|
|
13034
13446
|
if ( self._modal ) {
|
13035
|
-
self._modal
|
13447
|
+
self._modal
|
13448
|
+
.removeClass( self._modalOpenClasses )
|
13449
|
+
.height( "" );
|
13036
13450
|
}
|
13037
13451
|
},
|
13038
13452
|
complete = function() {
|
@@ -13044,12 +13458,12 @@ $.widget( "mobile.panel", {
|
|
13044
13458
|
|
13045
13459
|
if ( o.display !== "overlay" ) {
|
13046
13460
|
self._page().parent().removeClass( o.classes.pageContainer );
|
13047
|
-
self._wrapper
|
13461
|
+
self._wrapper.removeClass( o.classes.pageContentPrefix + "-open" );
|
13048
13462
|
self._fixedToolbars().removeClass( o.classes.pageContentPrefix + "-open" );
|
13049
13463
|
}
|
13050
13464
|
|
13051
13465
|
if ( $.support.cssTransform3d && !!o.animate && o.display !== "overlay" ) {
|
13052
|
-
self._wrapper
|
13466
|
+
self._wrapper.removeClass( o.classes.animate );
|
13053
13467
|
self._fixedToolbars().removeClass( o.classes.animate );
|
13054
13468
|
}
|
13055
13469
|
|
@@ -13060,6 +13474,8 @@ $.widget( "mobile.panel", {
|
|
13060
13474
|
self._page().jqmRemoveData( "panel" );
|
13061
13475
|
|
13062
13476
|
self._trigger( "close" );
|
13477
|
+
|
13478
|
+
self._openedPage = null;
|
13063
13479
|
};
|
13064
13480
|
|
13065
13481
|
self._trigger( "beforeclose" );
|
@@ -13084,7 +13500,7 @@ $.widget( "mobile.panel", {
|
|
13084
13500
|
// remove the wrapper if not in use by another panel
|
13085
13501
|
otherPanels = $( "body > :mobile-panel" ).add( $.mobile.activePage.find( ":mobile-panel" ) );
|
13086
13502
|
if ( otherPanels.not( ".ui-panel-display-overlay" ).not( this.element ).length === 0 ) {
|
13087
|
-
this._wrapper
|
13503
|
+
this._wrapper.children().unwrap();
|
13088
13504
|
}
|
13089
13505
|
|
13090
13506
|
if ( this._open ) {
|
@@ -13285,14 +13701,17 @@ $.widget( "mobile.table", $.mobile.table, {
|
|
13285
13701
|
|
13286
13702
|
// create the hide/show toggles
|
13287
13703
|
this.headers.not( "td" ).each( function() {
|
13288
|
-
var
|
13289
|
-
|
13290
|
-
|
13704
|
+
var input, cells,
|
13705
|
+
header = $( this ),
|
13706
|
+
priority = $.mobile.getAttribute( this, "priority" );
|
13291
13707
|
|
13292
13708
|
if ( priority ) {
|
13709
|
+
cells = header.add( header.jqmData( "cells" ) );
|
13293
13710
|
cells.addClass( opts.classes.priorityPrefix + priority );
|
13294
13711
|
|
13295
|
-
|
13712
|
+
// Make sure the (new?) checkbox is associated with its header via .jqmData() and
|
13713
|
+
// that, vice versa, the header is also associated with the checkbox
|
13714
|
+
input = ( keep ? inputs.eq( checkboxIndex++ ) :
|
13296
13715
|
$("<label><input type='checkbox' checked />" +
|
13297
13716
|
( header.children( "abbr" ).first().attr( "title" ) ||
|
13298
13717
|
header.text() ) +
|
@@ -13302,7 +13721,13 @@ $.widget( "mobile.table", $.mobile.table, {
|
|
13302
13721
|
.checkboxradio( {
|
13303
13722
|
theme: opts.columnPopupTheme
|
13304
13723
|
}) )
|
13305
|
-
|
13724
|
+
|
13725
|
+
// Associate the header with the checkbox
|
13726
|
+
.jqmData( "header", header )
|
13727
|
+
.jqmData( "cells", cells );
|
13728
|
+
|
13729
|
+
// Associate the checkbox with the header
|
13730
|
+
header.jqmData( "input", input );
|
13306
13731
|
}
|
13307
13732
|
});
|
13308
13733
|
|
@@ -13319,14 +13744,6 @@ $.widget( "mobile.table", $.mobile.table, {
|
|
13319
13744
|
input.jqmData( "cells" )
|
13320
13745
|
.toggleClass( "ui-table-cell-hidden", !checked )
|
13321
13746
|
.toggleClass( "ui-table-cell-visible", checked );
|
13322
|
-
|
13323
|
-
if ( input[ 0 ].getAttribute( "locked" ) ) {
|
13324
|
-
input.removeAttr( "locked" );
|
13325
|
-
|
13326
|
-
this._unlockCells( input.jqmData( "cells" ) );
|
13327
|
-
} else {
|
13328
|
-
input.attr( "locked", true );
|
13329
|
-
}
|
13330
13747
|
},
|
13331
13748
|
|
13332
13749
|
_unlockCells: function( cells ) {
|
@@ -13376,17 +13793,48 @@ $.widget( "mobile.table", $.mobile.table, {
|
|
13376
13793
|
},
|
13377
13794
|
|
13378
13795
|
_refresh: function( create ) {
|
13796
|
+
var headers, hiddenColumns, index;
|
13797
|
+
|
13798
|
+
// Calling _super() here updates this.headers
|
13379
13799
|
this._super( create );
|
13380
13800
|
|
13381
13801
|
if ( !create && this.options.mode === "columntoggle" ) {
|
13802
|
+
headers = this.headers;
|
13803
|
+
hiddenColumns = [];
|
13804
|
+
|
13805
|
+
// Find the index of the column header associated with each old checkbox among the
|
13806
|
+
// post-refresh headers and, if the header is still there, make sure the corresponding
|
13807
|
+
// column will be hidden if the pre-refresh checkbox indicates that the column is
|
13808
|
+
// hidden by recording its index in the array of hidden columns.
|
13809
|
+
this._menu.find( "input" ).each( function() {
|
13810
|
+
var input = $( this ),
|
13811
|
+
header = input.jqmData( "header" ),
|
13812
|
+
index = headers.index( header[ 0 ] );
|
13813
|
+
|
13814
|
+
if ( index > -1 && !input.prop( "checked" ) ) {
|
13815
|
+
|
13816
|
+
// The column header associated with /this/ checkbox is still present in the
|
13817
|
+
// post-refresh table and the checkbox is not checked, so the column associated
|
13818
|
+
// with this column header is currently hidden. Let's record that.
|
13819
|
+
hiddenColumns.push( index );
|
13820
|
+
}
|
13821
|
+
});
|
13822
|
+
|
13382
13823
|
// columns not being replaced must be cleared from input toggle-locks
|
13383
|
-
this._unlockCells( this.
|
13824
|
+
this._unlockCells( this.element.find( ".ui-table-cell-hidden, " +
|
13825
|
+
".ui-table-cell-visible" ) );
|
13384
13826
|
|
13385
13827
|
// update columntoggles and cells
|
13386
13828
|
this._addToggles( this._menu, create );
|
13387
13829
|
|
13388
|
-
//
|
13389
|
-
|
13830
|
+
// At this point all columns are visible, so uncheck the checkboxes that correspond to
|
13831
|
+
// those columns we've found to be hidden
|
13832
|
+
for ( index = hiddenColumns.length - 1 ; index > -1 ; index-- ) {
|
13833
|
+
headers.eq( hiddenColumns[ index ] ).jqmData( "input" )
|
13834
|
+
.prop( "checked", false )
|
13835
|
+
.checkboxradio( "refresh" )
|
13836
|
+
.trigger( "change" );
|
13837
|
+
}
|
13390
13838
|
}
|
13391
13839
|
},
|
13392
13840
|
|
@@ -13456,10 +13904,10 @@ $.widget( "mobile.table", $.mobile.table, {
|
|
13456
13904
|
var cells = $( this ).jqmData( "cells" ),
|
13457
13905
|
colstart = $.mobile.getAttribute( this, "colstart" ),
|
13458
13906
|
hierarchyClass = cells.not( this ).filter( "thead th" ).length && " ui-table-cell-label-top",
|
13459
|
-
|
13907
|
+
contents = $( this ).clone().contents(),
|
13460
13908
|
iteration, filter;
|
13461
13909
|
|
13462
|
-
if (
|
13910
|
+
if ( contents.length > 0 ) {
|
13463
13911
|
|
13464
13912
|
if ( hierarchyClass ) {
|
13465
13913
|
iteration = parseInt( this.getAttribute( "colspan" ), 10 );
|
@@ -13469,18 +13917,24 @@ $.widget( "mobile.table", $.mobile.table, {
|
|
13469
13917
|
filter = "td:nth-child("+ iteration +"n + " + ( colstart ) +")";
|
13470
13918
|
}
|
13471
13919
|
|
13472
|
-
table._addLabels( cells.filter( filter ),
|
13920
|
+
table._addLabels( cells.filter( filter ),
|
13921
|
+
opts.classes.cellLabels + hierarchyClass, contents );
|
13473
13922
|
} else {
|
13474
|
-
table._addLabels( cells, opts.classes.cellLabels,
|
13923
|
+
table._addLabels( cells, opts.classes.cellLabels, contents );
|
13475
13924
|
}
|
13476
13925
|
|
13477
13926
|
}
|
13478
13927
|
});
|
13479
13928
|
},
|
13480
13929
|
|
13481
|
-
_addLabels: function( cells, label,
|
13930
|
+
_addLabels: function( cells, label, contents ) {
|
13931
|
+
if ( contents.length === 1 && contents[ 0 ].nodeName.toLowerCase() === "abbr" ) {
|
13932
|
+
contents = contents.eq( 0 ).attr( "title" );
|
13933
|
+
}
|
13482
13934
|
// .not fixes #6006
|
13483
|
-
cells
|
13935
|
+
cells
|
13936
|
+
.not( ":has(b." + label + ")" )
|
13937
|
+
.prepend( $( "<b class='" + label + "'></b>" ).append( contents ) );
|
13484
13938
|
}
|
13485
13939
|
});
|
13486
13940
|
|
@@ -13539,7 +13993,9 @@ $.widget( "mobile.filterable", {
|
|
13539
13993
|
}
|
13540
13994
|
|
13541
13995
|
this._timer = this._delay( function() {
|
13542
|
-
this._trigger( "beforefilter", null, { input: search } )
|
13996
|
+
if ( this._trigger( "beforefilter", null, { input: search } ) === false ) {
|
13997
|
+
return false;
|
13998
|
+
}
|
13543
13999
|
|
13544
14000
|
// Change val as lastval for next execution
|
13545
14001
|
search[ 0 ].setAttribute( "data-" + $.mobile.ns + "lastval", val );
|
@@ -13587,7 +14043,8 @@ $.widget( "mobile.filterable", {
|
|
13587
14043
|
// If nothing is hidden, then the decision whether to hide or show the items
|
13588
14044
|
// is based on the "filterReveal" option.
|
13589
14045
|
if ( hide.length === 0 ) {
|
13590
|
-
filterItems[ opts.filterReveal
|
14046
|
+
filterItems[ ( opts.filterReveal && val.length === 0 ) ?
|
14047
|
+
"addClass" : "removeClass" ]( "ui-screen-hidden" );
|
13591
14048
|
} else {
|
13592
14049
|
$( hide ).addClass( "ui-screen-hidden" );
|
13593
14050
|
$( show ).removeClass( "ui-screen-hidden" );
|
@@ -13638,6 +14095,8 @@ $.widget( "mobile.filterable", {
|
|
13638
14095
|
this.document.find( selector );
|
13639
14096
|
|
13640
14097
|
this._on( search, {
|
14098
|
+
keydown: "_onKeyDown",
|
14099
|
+
keypress: "_onKeyPress",
|
13641
14100
|
keyup: "_onKeyUp",
|
13642
14101
|
change: "_onKeyUp",
|
13643
14102
|
input: "_onKeyUp"
|
@@ -13647,6 +14106,21 @@ $.widget( "mobile.filterable", {
|
|
13647
14106
|
this._search = search;
|
13648
14107
|
},
|
13649
14108
|
|
14109
|
+
// Prevent form submission
|
14110
|
+
_onKeyDown: function( event ) {
|
14111
|
+
if ( event.keyCode === $.ui.keyCode.ENTER ) {
|
14112
|
+
event.preventDefault();
|
14113
|
+
this._preventKeyPress = true;
|
14114
|
+
}
|
14115
|
+
},
|
14116
|
+
|
14117
|
+
_onKeyPress: function( event ) {
|
14118
|
+
if ( this._preventKeyPress ) {
|
14119
|
+
event.preventDefault();
|
14120
|
+
this._preventKeyPress = false;
|
14121
|
+
}
|
14122
|
+
},
|
14123
|
+
|
13650
14124
|
_setOptions: function( options ) {
|
13651
14125
|
var refilter = !( ( options.filterReveal === undefined ) &&
|
13652
14126
|
( options.filterCallback === undefined ) &&
|
@@ -13750,7 +14224,9 @@ $.widget( "mobile.filterable", $.mobile.filterable, {
|
|
13750
14224
|
// Also trigger listviewbeforefilter if this widget is also a listview
|
13751
14225
|
this._widget._trigger( "beforefilter", event, data );
|
13752
14226
|
}
|
13753
|
-
|
14227
|
+
|
14228
|
+
// Passing back the response enables calling preventDefault()
|
14229
|
+
return this._super( type, event, data );
|
13754
14230
|
},
|
13755
14231
|
|
13756
14232
|
_setWidget: function( widget ) {
|
@@ -13835,6 +14311,24 @@ $.widget( "mobile.filterable", $.mobile.filterable, {
|
|
13835
14311
|
return ret;
|
13836
14312
|
},
|
13837
14313
|
|
14314
|
+
// The listview implementation accompanying this filterable backcompat layer will call
|
14315
|
+
// filterable.refresh() after it's done refreshing the listview to make sure the filterable
|
14316
|
+
// filters out any new items added. However, when the listview refresh has been initiated by
|
14317
|
+
// the filterable itself, then such filtering has already taken place, and calling the
|
14318
|
+
// filterable's refresh() method will cause an infinite recursion. We stop this by setting a
|
14319
|
+
// flag that will cause the filterable's refresh() method to short-circuit.
|
14320
|
+
_refreshChildWidget: function() {
|
14321
|
+
this._refreshingChildWidget = true;
|
14322
|
+
this._superApply( arguments );
|
14323
|
+
this._refreshingChildWidget = false;
|
14324
|
+
},
|
14325
|
+
|
14326
|
+
refresh: function() {
|
14327
|
+
if ( !this._refreshingChildWidget ) {
|
14328
|
+
this._superApply( arguments );
|
14329
|
+
}
|
14330
|
+
},
|
14331
|
+
|
13838
14332
|
_destroy: function() {
|
13839
14333
|
if ( this._isSearchInternal() ) {
|
13840
14334
|
this._search.remove();
|
@@ -13865,6 +14359,38 @@ $.widget( "mobile.filterable", $.mobile.filterable, {
|
|
13865
14359
|
}
|
13866
14360
|
});
|
13867
14361
|
|
14362
|
+
// Instantiate a filterable on a listview that has the data-filter="true" attribute
|
14363
|
+
// This is not necessary for static content, because the auto-enhance takes care of instantiating
|
14364
|
+
// the filterable upon encountering data-filter="true". However, because of 1.3.x it is expected
|
14365
|
+
// that a listview with data-filter="true" will be filterable even if you just instantiate a
|
14366
|
+
// listview on it. The extension below ensures that this continues to happen in 1.4.x.
|
14367
|
+
$.widget( "mobile.listview", $.mobile.listview, {
|
14368
|
+
options: {
|
14369
|
+
filter: false
|
14370
|
+
},
|
14371
|
+
_create: function() {
|
14372
|
+
if ( this.options.filter === true &&
|
14373
|
+
!this.element.data( "mobile-filterable" ) ) {
|
14374
|
+
this.element.filterable();
|
14375
|
+
}
|
14376
|
+
return this._super();
|
14377
|
+
},
|
14378
|
+
|
14379
|
+
refresh: function() {
|
14380
|
+
var filterable;
|
14381
|
+
|
14382
|
+
this._superApply( arguments );
|
14383
|
+
|
14384
|
+
if ( this.options.filter === true ) {
|
14385
|
+
filterable = this.element.data( "mobile-filterable" );
|
14386
|
+
|
14387
|
+
if ( filterable ) {
|
14388
|
+
filterable.refresh();
|
14389
|
+
}
|
14390
|
+
}
|
14391
|
+
}
|
14392
|
+
});
|
14393
|
+
|
13868
14394
|
})( jQuery );
|
13869
14395
|
|
13870
14396
|
/*!
|
@@ -14799,7 +15325,8 @@ $.widget( "ui.tabs", {
|
|
14799
15325
|
var path = $.mobile.path,
|
14800
15326
|
$pages = $( ":jqmData(role='page'), :jqmData(role='dialog')" ),
|
14801
15327
|
hash = path.stripHash( path.stripQueryParams(path.parseLocation().hash) ),
|
14802
|
-
|
15328
|
+
theLocation = $.mobile.path.parseLocation(),
|
15329
|
+
hashPage = hash ? document.getElementById( hash ) : undefined;
|
14803
15330
|
|
14804
15331
|
// if no pages are found, create one with body's inner html
|
14805
15332
|
if ( !$pages.length ) {
|
@@ -14812,7 +15339,8 @@ $.widget( "ui.tabs", {
|
|
14812
15339
|
|
14813
15340
|
// unless the data url is already set set it to the pathname
|
14814
15341
|
if ( !$this[ 0 ].getAttribute( "data-" + $.mobile.ns + "url" ) ) {
|
14815
|
-
$this.attr( "data-" + $.mobile.ns + "url", $this.attr( "id" ) ||
|
15342
|
+
$this.attr( "data-" + $.mobile.ns + "url", $this.attr( "id" ) ||
|
15343
|
+
path.convertUrlToDataUrl( theLocation.pathname + theLocation.search ) );
|
14816
15344
|
}
|
14817
15345
|
});
|
14818
15346
|
|
@@ -14849,11 +15377,6 @@ $.widget( "ui.tabs", {
|
|
14849
15377
|
$.mobile.path.isPath( hash ) ||
|
14850
15378
|
hash === $.mobile.dialogHashKey ) ) ) {
|
14851
15379
|
|
14852
|
-
// Store the initial destination
|
14853
|
-
if ( $.mobile.path.isHashValid( location.hash ) ) {
|
14854
|
-
$.mobile.navigate.history.initialDst = hash.replace( "#", "" );
|
14855
|
-
}
|
14856
|
-
|
14857
15380
|
// make sure to set initial popstate state if it exists
|
14858
15381
|
// so that navigation back to the initial page works properly
|
14859
15382
|
if ( $.event.special.navigate.isPushStateEnabled() ) {
|