mobiscroll.js 107 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085
  1. /*!
  2. * Mobiscroll v2.15.1
  3. * http://mobiscroll.com
  4. *
  5. * Copyright 2010-2015, Acid Media
  6. * Licensed under the MIT license.
  7. *
  8. */
  9. (function ($, undefined) {
  10. function testProps(props) {
  11. var i;
  12. for (i in props) {
  13. if (mod[props[i]] !== undefined) {
  14. return true;
  15. }
  16. }
  17. return false;
  18. }
  19. function testPrefix() {
  20. var prefixes = ['Webkit', 'Moz', 'O', 'ms'],
  21. p;
  22. for (p in prefixes) {
  23. if (testProps([prefixes[p] + 'Transform'])) {
  24. return '-' + prefixes[p].toLowerCase() + '-';
  25. }
  26. }
  27. return '';
  28. }
  29. function init(that, options, args) {
  30. var ret = that;
  31. // Init
  32. if (typeof options === 'object') {
  33. return that.each(function () {
  34. if (instances[this.id]) {
  35. instances[this.id].destroy();
  36. }
  37. new $.mobiscroll.classes[options.component || 'Scroller'](this, options);
  38. });
  39. }
  40. // Method call
  41. if (typeof options === 'string') {
  42. that.each(function () {
  43. var r,
  44. inst = instances[this.id];
  45. if (inst && inst[options]) {
  46. r = inst[options].apply(this, Array.prototype.slice.call(args, 1));
  47. if (r !== undefined) {
  48. ret = r;
  49. return false;
  50. }
  51. }
  52. });
  53. }
  54. return ret;
  55. }
  56. var id = +new Date(),
  57. instances = {},
  58. extend = $.extend,
  59. mod = document.createElement('modernizr').style,
  60. has3d = testProps(['perspectiveProperty', 'WebkitPerspective', 'MozPerspective', 'OPerspective', 'msPerspective']),
  61. hasFlex = testProps(['flex', 'msFlex', 'WebkitBoxDirection']),
  62. prefix = testPrefix(),
  63. pr = prefix.replace(/^\-/, '').replace(/\-$/, '').replace('moz', 'Moz');
  64. $.fn.mobiscroll = function (method) {
  65. extend(this, $.mobiscroll.components);
  66. return init(this, method, arguments);
  67. };
  68. $.mobiscroll = $.mobiscroll || {
  69. version: '2.15.1',
  70. util: {
  71. prefix: prefix,
  72. jsPrefix: pr,
  73. has3d: has3d,
  74. hasFlex: hasFlex,
  75. testTouch: function (e, elm) {
  76. if (e.type == 'touchstart') {
  77. $(elm).attr('data-touch', '1');
  78. } else if ($(elm).attr('data-touch')) {
  79. $(elm).removeAttr('data-touch');
  80. return false;
  81. }
  82. return true;
  83. },
  84. objectToArray: function (obj) {
  85. var arr = [],
  86. i;
  87. for (i in obj) {
  88. arr.push(obj[i]);
  89. }
  90. return arr;
  91. },
  92. arrayToObject: function (arr) {
  93. var obj = {},
  94. i;
  95. if (arr) {
  96. for (i = 0; i < arr.length; i++) {
  97. obj[arr[i]] = arr[i];
  98. }
  99. }
  100. return obj;
  101. },
  102. isNumeric: function (a) {
  103. return a - parseFloat(a) >= 0;
  104. },
  105. isString: function (s) {
  106. return typeof s === 'string';
  107. },
  108. getCoord: function (e, c) {
  109. var ev = e.originalEvent || e;
  110. return ev.changedTouches ? ev.changedTouches[0]['page' + c] : e['page' + c];
  111. },
  112. getPosition: function (t, vertical) {
  113. var style = window.getComputedStyle ? getComputedStyle(t[0]) : t[0].style,
  114. matrix,
  115. px;
  116. if (has3d) {
  117. $.each(['t', 'webkitT', 'MozT', 'OT', 'msT'], function (i, v) {
  118. if (style[v + 'ransform'] !== undefined) {
  119. matrix = style[v + 'ransform'];
  120. return false;
  121. }
  122. });
  123. matrix = matrix.split(')')[0].split(', ');
  124. px = vertical ? (matrix[13] || matrix[5]) : (matrix[12] || matrix[4]);
  125. } else {
  126. px = vertical ? style.top.replace('px', '') : style.left.replace('px', '');
  127. }
  128. return px;
  129. },
  130. constrain: function (val, min, max) {
  131. return Math.max(min, Math.min(val, max));
  132. },
  133. vibrate: function (time) {
  134. if ('vibrate' in navigator) {
  135. navigator.vibrate(time || 50);
  136. }
  137. }
  138. },
  139. tapped: false,
  140. autoTheme: 'mobiscroll',
  141. presets: {
  142. scroller: {},
  143. numpad: {},
  144. listview: {},
  145. menustrip: {}
  146. },
  147. themes: {
  148. frame: {},
  149. listview: {},
  150. menustrip: {}
  151. },
  152. i18n: {},
  153. instances: instances,
  154. classes: {},
  155. components: {},
  156. defaults: {
  157. context: 'body',
  158. mousewheel: true,
  159. vibrate: true
  160. },
  161. setDefaults: function (o) {
  162. extend(this.defaults, o);
  163. },
  164. presetShort: function (name, c, p) {
  165. this.components[name] = function (s) {
  166. return init(this, extend(s, { component: c, preset: p === false ? undefined : name }), arguments);
  167. };
  168. }
  169. };
  170. $.mobiscroll.classes.Base = function (el, settings) {
  171. var lang,
  172. preset,
  173. s,
  174. theme,
  175. themeName,
  176. defaults,
  177. ms = $.mobiscroll,
  178. that = this;
  179. that.settings = {};
  180. that._presetLoad = function () {};
  181. that._init = function (ss) {
  182. s = that.settings;
  183. // Update original user settings
  184. extend(settings, ss);
  185. // Load user defaults
  186. if (that._hasDef) {
  187. defaults = ms.defaults;
  188. }
  189. // Create settings object
  190. extend(s, that._defaults, defaults, settings);
  191. // Get theme defaults
  192. if (that._hasTheme) {
  193. themeName = s.theme;
  194. if (themeName == 'auto' || !themeName) {
  195. themeName = ms.autoTheme;
  196. }
  197. if (themeName == 'default') {
  198. themeName = 'mobiscroll';
  199. }
  200. settings.theme = themeName;
  201. theme = ms.themes[that._class][themeName];
  202. }
  203. // Get language defaults
  204. if (that._hasLang) {
  205. lang = ms.i18n[s.lang];
  206. }
  207. if (that._hasTheme) {
  208. that.trigger('onThemeLoad', [lang, settings]);
  209. }
  210. // Update settings object
  211. extend(s, theme, lang, defaults, settings);
  212. // Load preset settings
  213. if (that._hasPreset) {
  214. that._presetLoad(s);
  215. preset = ms.presets[that._class][s.preset];
  216. if (preset) {
  217. preset = preset.call(el, that);
  218. extend(s, preset, settings);
  219. }
  220. }
  221. };
  222. that._destroy = function () {
  223. that.trigger('onDestroy', []);
  224. // Delete scroller instance
  225. delete instances[el.id];
  226. that = null;
  227. };
  228. /**
  229. * Triggers an event
  230. */
  231. that.trigger = function (name, args) {
  232. var ret;
  233. args.push(that);
  234. $.each([defaults, theme, preset, settings], function (i, v) {
  235. if (v && v[name]) { // Call preset event
  236. ret = v[name].apply(el, args);
  237. }
  238. });
  239. return ret;
  240. };
  241. /**
  242. * Sets one ore more options.
  243. */
  244. that.option = function (opt, value) {
  245. var obj = {};
  246. if (typeof opt === 'object') {
  247. obj = opt;
  248. } else {
  249. obj[opt] = value;
  250. }
  251. that.init(obj);
  252. };
  253. /**
  254. * Returns the mobiscroll instance.
  255. */
  256. that.getInst = function () {
  257. return that;
  258. };
  259. settings = settings || {};
  260. // Autogenerate id
  261. if (!el.id) {
  262. el.id = 'mobiscroll' + (++id);
  263. }
  264. // Save instance
  265. instances[el.id] = that;
  266. };
  267. })(jQuery);
  268. //mobiscroll.frame.js
  269. (function ($, window, document, undefined) {
  270. var $activeElm,
  271. preventShow,
  272. ms = $.mobiscroll,
  273. instances = ms.instances,
  274. util = ms.util,
  275. pr = util.jsPrefix,
  276. has3d = util.has3d,
  277. getCoord = util.getCoord,
  278. constrain = util.constrain,
  279. isString = util.isString,
  280. isOldAndroid = /android [1-3]/i.test(navigator.userAgent),
  281. isIOS8 = /(iphone|ipod|ipad).* os 8_/i.test(navigator.userAgent),
  282. animEnd = 'webkitAnimationEnd animationend',
  283. empty = function () { },
  284. prevdef = function (ev) { ev.preventDefault(); };
  285. ms.classes.Frame = function (el, settings, inherit) {
  286. var $ariaDiv,
  287. $ctx,
  288. $header,
  289. $markup,
  290. $overlay,
  291. $persp,
  292. $popup,
  293. $wnd,
  294. $wrapper,
  295. buttons,
  296. btn,
  297. doAnim,
  298. event,
  299. hasButtons,
  300. isModal,
  301. modalWidth,
  302. modalHeight,
  303. posEvents,
  304. preventPos,
  305. s,
  306. scrollLock,
  307. setReadOnly,
  308. wndWidth,
  309. wndHeight,
  310. that = this,
  311. $elm = $(el),
  312. elmList = [],
  313. posDebounce = {};
  314. function onBtnStart(ev) {
  315. // Can't call preventDefault here, it kills page scroll
  316. if (btn) {
  317. btn.removeClass('dwb-a');
  318. }
  319. btn = $(this);
  320. // Active button
  321. if (!btn.hasClass('dwb-d') && !btn.hasClass('dwb-nhl')) {
  322. btn.addClass('dwb-a');
  323. }
  324. if (ev.type === 'mousedown') {
  325. $(document).on('mouseup', onBtnEnd);
  326. }
  327. }
  328. function onBtnEnd(ev) {
  329. if (btn) {
  330. btn.removeClass('dwb-a');
  331. btn = null;
  332. }
  333. if (ev.type === 'mouseup') {
  334. $(document).off('mouseup', onBtnEnd);
  335. }
  336. }
  337. function onWndKeyDown(ev) {
  338. if (ev.keyCode == 13) {
  339. that.select();
  340. } else if (ev.keyCode == 27) {
  341. that.cancel();
  342. }
  343. }
  344. function onShow(prevFocus) {
  345. if (!prevFocus) {
  346. $popup.focus();
  347. }
  348. that.ariaMessage(s.ariaMessage);
  349. }
  350. function onHide(prevAnim) {
  351. var activeEl,
  352. value,
  353. type,
  354. focus = s.focusOnClose;
  355. setTimeout(function(){
  356. $markup.remove();
  357. },500);
  358. if ($activeElm && !prevAnim) {
  359. setTimeout(function () {
  360. if (focus === undefined || focus === true) {
  361. preventShow = true;
  362. activeEl = $activeElm[0];
  363. type = activeEl.type;
  364. value = activeEl.value;
  365. try {
  366. activeEl.type = 'button';
  367. } catch (ex) { }
  368. $activeElm.focus();
  369. activeEl.type = type;
  370. activeEl.value = value;
  371. } else if (focus) {
  372. // If a mobiscroll field is focused, allow show
  373. if (instances[$(focus).attr('id')]) {
  374. ms.tapped = false;
  375. }
  376. $(focus).focus();
  377. }
  378. }, 200);
  379. }
  380. that._isVisible = false;
  381. event('onHide', []);
  382. }
  383. function onPosition(ev) {
  384. clearTimeout(posDebounce[ev.type]);
  385. posDebounce[ev.type] = setTimeout(function () {
  386. var isScroll = ev.type == 'scroll';
  387. if (isScroll && !scrollLock) {
  388. return;
  389. }
  390. that.position(!isScroll);
  391. }, 200);
  392. }
  393. function onFocus(ev) {
  394. if (!$popup[0].contains(ev.target)) {
  395. $popup.focus();
  396. }
  397. }
  398. function show(beforeShow, $elm) {
  399. if (!ms.tapped) {
  400. if (beforeShow) {
  401. beforeShow();
  402. }
  403. // Hide virtual keyboard
  404. if ($(document.activeElement).is('input,textarea')) {
  405. $(document.activeElement).blur();
  406. }
  407. $activeElm = $elm;
  408. that.show();
  409. }
  410. setTimeout(function () {
  411. preventShow = false;
  412. }, 300); // With jQuery < 1.9 focus is fired twice in IE
  413. }
  414. // Call the parent constructor
  415. ms.classes.Base.call(this, el, settings, true);
  416. /**
  417. * Positions the scroller on the screen.
  418. */
  419. that.position = function (check) {
  420. var w,
  421. l,
  422. t,
  423. anchor,
  424. aw, // anchor width
  425. ah, // anchor height
  426. ap, // anchor position
  427. at, // anchor top
  428. al, // anchor left
  429. arr, // arrow
  430. arrw, // arrow width
  431. arrl, // arrow left
  432. dh,
  433. scroll,
  434. sl, // scroll left
  435. st, // scroll top
  436. totalw = 0,
  437. minw = 0,
  438. css = {},
  439. nw = Math.min($wnd[0].innerWidth || $wnd.innerWidth(), $persp.width()), //$persp.width(), // To get the width without scrollbar
  440. nh = $wnd[0].innerHeight || $wnd.innerHeight();
  441. if ((wndWidth === nw && wndHeight === nh && check) || preventPos) {
  442. return;
  443. }
  444. if (that._isFullScreen || /top|bottom/.test(s.display)) {
  445. // Set width, if document is larger than viewport, needs to be set before onPosition (for calendar)
  446. $popup.width(nw);
  447. }
  448. if (event('onPosition', [$markup, nw, nh]) === false || !isModal) {
  449. return;
  450. }
  451. sl = $wnd.scrollLeft();
  452. st = $wnd.scrollTop();
  453. anchor = s.anchor === undefined ? $elm : $(s.anchor);
  454. // Set / unset liquid layout based on screen width, but only if not set explicitly by the user
  455. if (that._isLiquid && s.layout !== 'liquid') {
  456. if (nw < 400) {
  457. $markup.addClass('dw-liq');
  458. } else {
  459. $markup.removeClass('dw-liq');
  460. }
  461. }
  462. if (!that._isFullScreen && /modal|bubble/.test(s.display)) {
  463. $wrapper.width('');
  464. $('.mbsc-w-p', $markup).each(function () {
  465. w = $(this).outerWidth(true);
  466. totalw += w;
  467. minw = (w > minw) ? w : minw;
  468. });
  469. w = totalw > nw ? minw : totalw;
  470. $wrapper.width(w).css('white-space', totalw > nw ? '' : 'nowrap');
  471. }
  472. modalWidth = that._isFullScreen ? nw : $popup.outerWidth();
  473. modalHeight = that._isFullScreen ? nh : $popup.outerHeight(true);
  474. scrollLock = modalHeight <= nh && modalWidth <= nw;
  475. that.scrollLock = scrollLock;
  476. if (s.display == 'modal') {
  477. l = Math.max(0, sl + (nw - modalWidth) / 2);
  478. t = st + (nh - modalHeight) / 2;
  479. } else if (s.display == 'bubble') {
  480. scroll = true;
  481. arr = $('.dw-arrw-i', $markup);
  482. ap = anchor.offset();
  483. at = Math.abs($ctx.offset().top - ap.top);
  484. al = Math.abs($ctx.offset().left - ap.left);
  485. // horizontal positioning
  486. aw = anchor.outerWidth();
  487. ah = anchor.outerHeight();
  488. l = constrain(al - ($popup.outerWidth(true) - aw) / 2, sl + 3, sl + nw - modalWidth - 3);
  489. // vertical positioning
  490. t = at - modalHeight; // above the input
  491. if ((t < st) || (at > st + nh)) { // if doesn't fit above or the input is out of the screen
  492. $popup.removeClass('dw-bubble-top').addClass('dw-bubble-bottom');
  493. t = at + ah; // below the input
  494. } else {
  495. $popup.removeClass('dw-bubble-bottom').addClass('dw-bubble-top');
  496. }
  497. // Calculate Arrow position
  498. arrw = arr.outerWidth();
  499. arrl = constrain(al + aw / 2 - (l + (modalWidth - arrw) / 2), 0, arrw);
  500. // Limit Arrow position
  501. $('.dw-arr', $markup).css({ left: arrl });
  502. } else {
  503. l = sl;
  504. if (s.display == 'top') {
  505. t = st;
  506. } else if (s.display == 'bottom') {
  507. t = st + nh - modalHeight;
  508. }
  509. }
  510. t = t < 0 ? 0 : t;
  511. css.top = t;
  512. css.left = l;
  513. $popup.css(css);
  514. // If top + modal height > doc height, increase doc height
  515. $persp.height(0);
  516. dh = Math.max(t + modalHeight, s.context == 'body' ? $(document).height() : $ctx[0].scrollHeight);
  517. $persp.css({ height: dh });
  518. // Scroll needed
  519. if (scroll && ((t + modalHeight > st + nh) || (at > st + nh))) {
  520. preventPos = true;
  521. setTimeout(function () { preventPos = false; }, 300);
  522. $wnd.scrollTop(Math.min(t + modalHeight - nh, dh - nh));
  523. }
  524. wndWidth = nw;
  525. wndHeight = nh;
  526. };
  527. /**
  528. * Show mobiscroll on focus and click event of the parameter.
  529. * @param {jQuery} $elm - Events will be attached to this element.
  530. * @param {Function} [beforeShow=undefined] - Optional function to execute before showing mobiscroll.
  531. */
  532. that.attachShow = function ($elm, beforeShow) {
  533. elmList.push({ readOnly: $elm.prop('readonly'), el: $elm });
  534. if (s.display !== 'inline') {
  535. if (setReadOnly && $elm.is('input')) {
  536. $elm.prop('readonly', true).on('mousedown.dw', function (ev) {
  537. // Prevent input to get focus on tap (virtual keyboard pops up on some devices)
  538. ev.preventDefault();
  539. });
  540. }
  541. if (s.showOnFocus) {
  542. $elm.on('focus.dw', function () {
  543. if (!preventShow) {
  544. show(beforeShow, $elm);
  545. }
  546. });
  547. }
  548. if (s.showOnTap) {
  549. $elm.on('keydown.dw', function (ev) {
  550. if (ev.keyCode == 32 || ev.keyCode == 13) { // Space or Enter
  551. ev.preventDefault();
  552. ev.stopPropagation();
  553. show(beforeShow, $elm);
  554. }
  555. });
  556. that.tap($elm, function () {
  557. show(beforeShow, $elm);
  558. });
  559. }
  560. }
  561. };
  562. /**
  563. * Set button handler.
  564. */
  565. that.select = function () {
  566. if (!isModal || that.hide(false, 'set') !== false) {
  567. that._fillValue();
  568. event('onSelect', [that._value]);
  569. }
  570. };
  571. /**
  572. * Cancel and hide the scroller instance.
  573. */
  574. that.cancel = function () {
  575. if (!isModal || that.hide(false, 'cancel') !== false) {
  576. event('onCancel', [that._value]);
  577. }
  578. };
  579. /**
  580. * Clear button handler.
  581. */
  582. that.clear = function () {
  583. event('onClear', [$markup]);
  584. if (isModal && !that.live) {
  585. that.hide(false, 'clear');
  586. }
  587. that.setVal(null, true);
  588. };
  589. /**
  590. * Enables the scroller and the associated input.
  591. */
  592. that.enable = function () {
  593. s.disabled = false;
  594. if (that._isInput) {
  595. $elm.prop('disabled', false);
  596. }
  597. };
  598. /**
  599. * Disables the scroller and the associated input.
  600. */
  601. that.disable = function () {
  602. s.disabled = true;
  603. if (that._isInput) {
  604. $elm.prop('disabled', true);
  605. }
  606. };
  607. /**
  608. * Shows the scroller instance.
  609. * @param {Boolean} prevAnim - Prevent animation if true
  610. * @param {Boolean} prevFocus - Prevent focusing if true
  611. */
  612. that.show = function (prevAnim, prevFocus) {
  613. // Create wheels
  614. var html;
  615. if (s.disabled || that._isVisible) {
  616. return;
  617. }
  618. /*if (doAnim !== false) {
  619. if (s.display == 'top') {
  620. doAnim = 'slidedown';
  621. }
  622. if (s.display == 'bottom') {
  623. doAnim = 'slideup';
  624. }
  625. }*/
  626. // Parse value from input
  627. that._readValue();
  628. event('onBeforeShow', []);
  629. // Create wheels containers
  630. html = '<div lang="' + s.lang + '" class="mbsc-' + s.theme + (s.baseTheme ? ' mbsc-' + s.baseTheme : '') + ' dw-' + s.display + ' ' +
  631. (s.cssClass || '') +
  632. (that._isLiquid ? ' dw-liq' : '') +
  633. (isOldAndroid ? ' mbsc-old' : '') +
  634. (hasButtons ? '' : ' dw-nobtn') + '">' +
  635. '<div class="dw-persp">' +
  636. (isModal ? '<div class="dwo"></div>' : '') + // Overlay
  637. '<div' + (isModal ? ' role="dialog" tabindex="-1"' : '') + ' class="dw' + (s.rtl ? ' dw-rtl' : ' dw-ltr') + '">' + // Popup
  638. (s.display === 'bubble' ? '<div class="dw-arrw"><div class="dw-arrw-i"><div class="dw-arr"></div></div></div>' : '') + // Bubble arrow
  639. '<div class="dwwr">' + // Popup content
  640. '<div aria-live="assertive" class="dw-aria dw-hidden"></div>' +
  641. (s.headerText ? '<div class="dwv">' + (isString(s.headerText) ? s.headerText : '') + '</div>' : '') + // Header
  642. '<div class="dwcc">'; // Wheel group container
  643. html += that._generateContent();
  644. html += '</div>';
  645. if (hasButtons) {
  646. html += '<div class="dwbc">';
  647. $.each(buttons, function (i, b) {
  648. b = isString(b) ? that.buttons[b] : b;
  649. if (b.handler === 'set') {
  650. b.parentClass = 'dwb-s';
  651. }
  652. if (b.handler === 'cancel') {
  653. b.parentClass = 'dwb-c';
  654. }
  655. b.handler = isString(b.handler) ? that.handlers[b.handler] : b.handler;
  656. html += '<div' + (s.btnWidth ? ' style="width:' + (100 / buttons.length) + '%"' : '') + ' class="dwbw ' + (b.parentClass || '') + '"><div tabindex="0" role="button" class="dwb' + i + ' dwb-e ' + (b.cssClass === undefined ? s.btnClass : b.cssClass) + (b.icon ? ' mbsc-ic mbsc-ic-' + b.icon : '') + '">' + (b.text || '') + '</div></div>';
  657. });
  658. html += '</div>';
  659. }
  660. html += '</div></div></div></div>';
  661. $markup = $(html);
  662. $persp = $('.dw-persp', $markup);
  663. $overlay = $('.dwo', $markup);
  664. $wrapper = $('.dwwr', $markup);
  665. $header = $('.dwv', $markup);
  666. $popup = $('.dw', $markup);
  667. $ariaDiv = $('.dw-aria', $markup);
  668. that._markup = $markup;
  669. that._header = $header;
  670. that._isVisible = true;
  671. posEvents = 'orientationchange resize';
  672. that._markupReady($markup);
  673. event('onMarkupReady', [$markup]);
  674. // Show
  675. if (isModal) {
  676. // Enter / ESC
  677. $(window).on('keydown', onWndKeyDown);
  678. // Prevent scroll if not specified otherwise
  679. if (s.scrollLock) {
  680. $markup.on('touchmove mousewheel wheel', function (ev) {
  681. if (scrollLock) {
  682. ev.preventDefault();
  683. }
  684. });
  685. }
  686. // Disable inputs to prevent bleed through (Android bug)
  687. if (pr !== 'Moz') {
  688. $('input,select,button', $ctx).each(function () {
  689. if (!this.disabled) {
  690. $(this).addClass('dwtd').prop('disabled', true);
  691. }
  692. });
  693. }
  694. posEvents += ' scroll';
  695. ms.activeInstance = that;
  696. $markup.appendTo($ctx);
  697. if (has3d && doAnim && !prevAnim) {
  698. $markup.addClass('dw-in dw-trans').on(animEnd, function () {
  699. $markup.off(animEnd).removeClass('dw-in dw-trans').find('.dw').removeClass('dw-' + doAnim);
  700. onShow(prevFocus);
  701. }).find('.dw').addClass('dw-' + doAnim);
  702. }
  703. } else if ($elm.is('div') && !that._hasContent) {
  704. $elm.html($markup);
  705. } else {
  706. $markup.insertAfter($elm);
  707. }
  708. event('onMarkupInserted', [$markup]);
  709. // Set position
  710. that.position();
  711. $wnd
  712. .on(posEvents, onPosition)
  713. .on('focusin', onFocus);
  714. // Events
  715. $markup
  716. .on('selectstart mousedown', prevdef) // Prevents blue highlight on Android and text selection in IE
  717. .on('click', '.dwb-e', prevdef)
  718. .on('keydown', '.dwb-e', function (ev) {
  719. if (ev.keyCode == 32) { // Space
  720. ev.preventDefault();
  721. ev.stopPropagation();
  722. $(this).click();
  723. }
  724. })
  725. .on('keydown', function (ev) { // Trap focus inside modal
  726. if (ev.keyCode == 32) { // Space
  727. ev.preventDefault();
  728. } else if (ev.keyCode == 9) { // Tab
  729. var $focusable = $markup.find('[tabindex="0"]').filter(function () {
  730. return this.offsetWidth > 0 || this.offsetHeight > 0;
  731. }),
  732. index = $focusable.index($(':focus', $markup)),
  733. i = $focusable.length - 1,
  734. target = 0;
  735. if (ev.shiftKey) {
  736. i = 0;
  737. target = -1;
  738. }
  739. if (index === i) {
  740. $focusable.eq(target).focus();
  741. ev.preventDefault();
  742. }
  743. }
  744. });
  745. $('input', $markup).on('selectstart mousedown', function (ev) {
  746. ev.stopPropagation();
  747. });
  748. setTimeout(function () {
  749. // Init buttons
  750. $.each(buttons, function (i, b) {
  751. that.tap($('.dwb' + i, $markup), function (ev) {
  752. b = isString(b) ? that.buttons[b] : b;
  753. b.handler.call(this, ev, that);
  754. }, true);
  755. });
  756. if (s.closeOnOverlay) {
  757. that.tap($overlay, function () {
  758. that.cancel();
  759. });
  760. }
  761. if (isModal && !doAnim) {
  762. onShow(prevFocus);
  763. }
  764. $markup
  765. .on('touchstart mousedown', '.dwb-e', onBtnStart)
  766. .on('touchend', '.dwb-e', onBtnEnd);
  767. that._attachEvents($markup);
  768. }, 300);
  769. event('onShow', [$markup, that._tempValue]);
  770. };
  771. /**
  772. * Hides the scroller instance.
  773. */
  774. that.hide = function (prevAnim, btn, force) {
  775. // If onClose handler returns false, prevent hide
  776. if (!that._isVisible || (!force && !that._isValid && btn == 'set') || (!force && event('onClose', [that._tempValue, btn]) === false)) {
  777. return false;
  778. }
  779. // Hide wheels and overlay
  780. if ($markup) {
  781. // Re-enable temporary disabled fields
  782. if (pr !== 'Moz') {
  783. $('.dwtd', $ctx).each(function () {
  784. $(this).prop('disabled', false).removeClass('dwtd');
  785. });
  786. }
  787. if (has3d && isModal && doAnim && !prevAnim && !$markup.hasClass('dw-trans')) { // If dw-trans class was not removed, means that there was no animation
  788. $markup.addClass('dw-out dw-trans').find('.dw').addClass('dw-' + doAnim).on(animEnd, function () {
  789. onHide(prevAnim);
  790. });
  791. } else {
  792. onHide(prevAnim);
  793. }
  794. // Stop positioning on window resize
  795. $wnd
  796. .off(posEvents, onPosition)
  797. .off('focusin', onFocus);
  798. }
  799. if (isModal) {
  800. $(window).off('keydown', onWndKeyDown);
  801. delete ms.activeInstance;
  802. }
  803. };
  804. that.ariaMessage = function (txt) {
  805. $ariaDiv.html('');
  806. setTimeout(function () {
  807. $ariaDiv.html(txt);
  808. }, 100);
  809. };
  810. /**
  811. * Return true if the scroller is currently visible.
  812. */
  813. that.isVisible = function () {
  814. return that._isVisible;
  815. };
  816. // Protected functions to override
  817. that.setVal = empty;
  818. that._generateContent = empty;
  819. that._attachEvents = empty;
  820. that._readValue = empty;
  821. that._fillValue = empty;
  822. that._markupReady = empty;
  823. that._processSettings = empty;
  824. that._presetLoad = function (s) {
  825. // Add default buttons
  826. s.buttons = s.buttons || (s.display !== 'inline' ? ['set', 'cancel'] : []);
  827. // Hide header text in inline mode by default
  828. s.headerText = s.headerText === undefined ? (s.display !== 'inline' ? '{value}' : false) : s.headerText;
  829. };
  830. // Generic frame functions
  831. /**
  832. * Attach tap event to the given element.
  833. */
  834. that.tap = function (el, handler, prevent) {
  835. var startX,
  836. startY,
  837. moved;
  838. if (s.tap) {
  839. el.on('touchstart.dw', function (ev) {
  840. // Can't always call preventDefault here, it kills page scroll
  841. if (prevent) {
  842. ev.preventDefault();
  843. }
  844. startX = getCoord(ev, 'X');
  845. startY = getCoord(ev, 'Y');
  846. moved = false;
  847. }).on('touchmove.dw', function (ev) {
  848. // If movement is more than 20px, don't fire the click event handler
  849. if (Math.abs(getCoord(ev, 'X') - startX) > 20 || Math.abs(getCoord(ev, 'Y') - startY) > 20) {
  850. moved = true;
  851. }
  852. }).on('touchend.dw', function (ev) {
  853. var that = this;
  854. if (!moved) {
  855. // preventDefault and setTimeout are needed by iOS
  856. ev.preventDefault();
  857. //setTimeout(function () {
  858. handler.call(that, ev);
  859. //}, isOldAndroid ? 400 : 10);
  860. }
  861. // Prevent click events to happen
  862. ms.tapped = true;
  863. setTimeout(function () {
  864. ms.tapped = false;
  865. }, 500);
  866. });
  867. }
  868. el.on('click.dw', function (ev) {
  869. if (!ms.tapped) {
  870. // If handler was not called on touchend, call it on click;
  871. handler.call(this, ev);
  872. }
  873. ev.preventDefault();
  874. });
  875. };
  876. /**
  877. * Destroys the mobiscroll instance.
  878. */
  879. that.destroy = function () {
  880. // Force hide without animation
  881. that.hide(true, false, true);
  882. // Remove all events from elements
  883. $.each(elmList, function (i, v) {
  884. v.el.off('.dw').prop('readonly', v.readOnly);
  885. });
  886. that._destroy();
  887. };
  888. /**
  889. * Scroller initialization.
  890. */
  891. that.init = function (ss) {
  892. that._init(ss);
  893. that._isLiquid = (s.layout || (/top|bottom/.test(s.display) ? 'liquid' : '')) === 'liquid';
  894. that._processSettings();
  895. // Unbind all events (if re-init)
  896. $elm.off('.dw');
  897. doAnim = isOldAndroid ? false : s.animate;
  898. buttons = s.buttons || [];
  899. isModal = s.display !== 'inline';
  900. setReadOnly = s.showOnFocus || s.showOnTap;
  901. $wnd = $(s.context == 'body' ? window : s.context);
  902. $ctx = $(s.context);
  903. that.context = $wnd;
  904. that.live = true;
  905. // If no set button is found, live mode is activated
  906. $.each(buttons, function (i, b) {
  907. if (b == 'ok' || b == 'set' || b.handler == 'set') {
  908. that.live = false;
  909. return false;
  910. }
  911. });
  912. that.buttons.set = { text: s.setText, handler: 'set' };
  913. that.buttons.cancel = { text: (that.live) ? s.closeText : s.cancelText, handler: 'cancel' };
  914. that.buttons.clear = { text: s.clearText, handler: 'clear' };
  915. that._isInput = $elm.is('input');
  916. hasButtons = buttons.length > 0;
  917. if (that._isVisible) {
  918. that.hide(true, false, true);
  919. }
  920. event('onInit', []);
  921. if (isModal) {
  922. that._readValue();
  923. if (!that._hasContent) {
  924. that.attachShow($elm);
  925. }
  926. } else {
  927. that.show();
  928. }
  929. $elm.on('change.dw', function () {
  930. if (!that._preventChange) {
  931. that.setVal($elm.val(), true, false);
  932. }
  933. that._preventChange = false;
  934. });
  935. };
  936. that.buttons = {};
  937. that.handlers = {
  938. set: that.select,
  939. cancel: that.cancel,
  940. clear: that.clear
  941. };
  942. that._value = null;
  943. that._isValid = true;
  944. that._isVisible = false;
  945. // Constructor
  946. s = that.settings;
  947. event = that.trigger;
  948. if (!inherit) {
  949. that.init(settings);
  950. }
  951. };
  952. ms.classes.Frame.prototype._defaults = {
  953. // Localization
  954. lang: 'en',
  955. setText: 'Set',
  956. selectedText: 'Selected',
  957. closeText: 'Close',
  958. cancelText: 'Cancel',
  959. clearText: 'Clear',
  960. // Options
  961. disabled: false,
  962. closeOnOverlay: true,
  963. showOnFocus: false,
  964. showOnTap: true,
  965. display: 'bottom',
  966. scrollLock: true,
  967. tap: true,
  968. btnClass: 'dwb',
  969. btnWidth: false,
  970. focusOnClose: !isIOS8 // Temporary for iOS8
  971. };
  972. ms.themes.frame.mobiscroll = {
  973. rows: 5,
  974. showLabel: false,
  975. headerText: false,
  976. btnWidth: false,
  977. selectedLineHeight: true,
  978. selectedLineBorder: 1,
  979. dateOrder: 'MMddyy',
  980. weekDays: 'min',
  981. checkIcon: 'ion-ios7-checkmark-empty',
  982. btnPlusClass: 'mbsc-ic mbsc-ic-arrow-down5',
  983. btnMinusClass: 'mbsc-ic mbsc-ic-arrow-up5',
  984. btnCalPrevClass: 'mbsc-ic mbsc-ic-arrow-left5',
  985. btnCalNextClass: 'mbsc-ic mbsc-ic-arrow-right5'
  986. };
  987. // Prevent re-show on window focus
  988. $(window).on('focus', function () {
  989. if ($activeElm) {
  990. preventShow = true;
  991. }
  992. });
  993. // Prevent standard behaviour on body click
  994. $(document).on('mouseover mouseup mousedown click', function (ev) {
  995. if (ms.tapped) {
  996. ev.stopPropagation();
  997. ev.preventDefault();
  998. return false;
  999. }
  1000. });
  1001. })(jQuery, window, document);
  1002. //mobiscroll.scroller.js
  1003. (function ($, window, document, undefined) {
  1004. var move,
  1005. ms = $.mobiscroll,
  1006. classes = ms.classes,
  1007. util = ms.util,
  1008. pr = util.jsPrefix,
  1009. has3d = util.has3d,
  1010. hasFlex = util.hasFlex,
  1011. getCoord = util.getCoord,
  1012. constrain = util.constrain,
  1013. testTouch = util.testTouch;
  1014. ms.presetShort('scroller', 'Scroller', false);
  1015. classes.Scroller = function (el, settings, inherit) {
  1016. var $markup,
  1017. btn,
  1018. isScrollable,
  1019. itemHeight,
  1020. multiple,
  1021. s,
  1022. scrollDebounce,
  1023. trigger,
  1024. click,
  1025. moved,
  1026. start,
  1027. startTime,
  1028. stop,
  1029. p,
  1030. min,
  1031. max,
  1032. target,
  1033. index,
  1034. lines,
  1035. timer,
  1036. that = this,
  1037. $elm = $(el),
  1038. iv = {},
  1039. pos = {},
  1040. pixels = {},
  1041. wheels = [];
  1042. // Event handlers
  1043. function onStart(ev) {
  1044. // Scroll start
  1045. if (testTouch(ev, this) && !move && !click && !btn && !isReadOnly(this)) {
  1046. // Prevent touch highlight
  1047. ev.preventDefault();
  1048. // Better performance if there are tap events on document
  1049. ev.stopPropagation();
  1050. move = true;
  1051. isScrollable = s.mode != 'clickpick';
  1052. target = $('.dw-ul', this);
  1053. setGlobals(target);
  1054. moved = iv[index] !== undefined; // Don't allow tap, if still moving
  1055. p = moved ? getCurrentPosition(target) : pos[index];
  1056. start = getCoord(ev, 'Y');
  1057. startTime = new Date();
  1058. stop = start;
  1059. scroll(target, index, p, 0.001);
  1060. if (isScrollable) {
  1061. target.closest('.dwwl').addClass('dwa');
  1062. }
  1063. if (ev.type === 'mousedown') {
  1064. $(document).on('mousemove', onMove).on('mouseup', onEnd);
  1065. }
  1066. }
  1067. }
  1068. function onMove(ev) {
  1069. if (move) {
  1070. if (isScrollable) {
  1071. // Prevent scroll
  1072. ev.preventDefault();
  1073. ev.stopPropagation();
  1074. stop = getCoord(ev, 'Y');
  1075. if (Math.abs(stop - start) > 3 || moved) {
  1076. scroll(target, index, constrain(p + (start - stop) / itemHeight, min - 1, max + 1));
  1077. moved = true;
  1078. }
  1079. }
  1080. }
  1081. }
  1082. function onEnd(ev) {
  1083. if (move) {
  1084. var time = new Date() - startTime,
  1085. curr = constrain(Math.round(p + (start - stop) / itemHeight), min - 1, max + 1),
  1086. val = curr,
  1087. speed,
  1088. dist,
  1089. ttop = target.offset().top;
  1090. // Better performance if there are tap events on document
  1091. ev.stopPropagation();
  1092. move = false;
  1093. if (ev.type === 'mouseup') {
  1094. $(document).off('mousemove', onMove).off('mouseup', onEnd);
  1095. }
  1096. if (has3d && time < 300) {
  1097. speed = (stop - start) / time;
  1098. dist = (speed * speed) / s.speedUnit;
  1099. if (stop - start < 0) {
  1100. dist = -dist;
  1101. }
  1102. } else {
  1103. dist = stop - start;
  1104. }
  1105. if (!moved) { // this is a "tap"
  1106. var idx = Math.floor((stop - ttop) / itemHeight),
  1107. li = $($('.dw-li', target)[idx]),
  1108. valid = li.hasClass('dw-v'),
  1109. hl = isScrollable;
  1110. time = 0.1;
  1111. if (trigger('onValueTap', [li]) !== false && valid) {
  1112. val = idx;
  1113. } else {
  1114. hl = true;
  1115. }
  1116. if (hl && valid) {
  1117. li.addClass('dw-hl'); // Highlight
  1118. setTimeout(function () {
  1119. li.removeClass('dw-hl');
  1120. }, 100);
  1121. }
  1122. if (!multiple && (s.confirmOnTap === true || s.confirmOnTap[index]) && li.hasClass('dw-sel')) {
  1123. that.select();
  1124. return;
  1125. }
  1126. } else {
  1127. val = constrain(Math.round(p - dist / itemHeight), min, max);
  1128. time = speed ? Math.max(0.1, Math.abs((val - curr) / speed) * s.timeUnit) : 0.1;
  1129. }
  1130. if (isScrollable) {
  1131. calc(target, index, val, 0, time, true);
  1132. }
  1133. }
  1134. }
  1135. function onBtnStart(ev) {
  1136. btn = $(this);
  1137. // +/- buttons
  1138. if (testTouch(ev, this)) {
  1139. step(ev, btn.closest('.dwwl'), btn.hasClass('dwwbp') ? plus : minus);
  1140. }
  1141. if (ev.type === 'mousedown') {
  1142. $(document).on('mouseup', onBtnEnd);
  1143. }
  1144. }
  1145. function onBtnEnd(ev) {
  1146. btn = null;
  1147. if (click) {
  1148. clearInterval(timer);
  1149. click = false;
  1150. }
  1151. if (ev.type === 'mouseup') {
  1152. $(document).off('mouseup', onBtnEnd);
  1153. }
  1154. }
  1155. function onKeyDown(ev) {
  1156. if (ev.keyCode == 38) { // up
  1157. step(ev, $(this), minus);
  1158. } else if (ev.keyCode == 40) { // down
  1159. step(ev, $(this), plus);
  1160. }
  1161. }
  1162. function onKeyUp() {
  1163. if (click) {
  1164. clearInterval(timer);
  1165. click = false;
  1166. }
  1167. }
  1168. function onScroll(ev) {
  1169. if (!isReadOnly(this)) {
  1170. ev.preventDefault();
  1171. ev = ev.originalEvent || ev;
  1172. var delta = ev.deltaY || ev.wheelDelta || ev.detail,
  1173. t = $('.dw-ul', this);
  1174. setGlobals(t);
  1175. scroll(t, index, constrain(((delta < 0 ? -20 : 20) - pixels[index]) / itemHeight, min - 1, max + 1));
  1176. clearTimeout(scrollDebounce);
  1177. scrollDebounce = setTimeout(function () {
  1178. calc(t, index, Math.round(pos[index]), delta > 0 ? 1 : 2, 0.1);
  1179. }, 200);
  1180. }
  1181. }
  1182. // Private functions
  1183. function step(ev, w, func) {
  1184. ev.stopPropagation();
  1185. ev.preventDefault();
  1186. if (!click && !isReadOnly(w) && !w.hasClass('dwa')) {
  1187. click = true;
  1188. // + Button
  1189. var t = w.find('.dw-ul');
  1190. setGlobals(t);
  1191. clearInterval(timer);
  1192. timer = setInterval(function () { func(t); }, s.delay);
  1193. func(t);
  1194. }
  1195. }
  1196. function isReadOnly(wh) {
  1197. if ($.isArray(s.readonly)) {
  1198. var i = $('.dwwl', $markup).index(wh);
  1199. return s.readonly[i];
  1200. }
  1201. return s.readonly;
  1202. }
  1203. function generateWheelItems(i) {
  1204. var html = '<div class="dw-bf">',
  1205. w = wheels[i],
  1206. l = 1,
  1207. labels = w.labels || [],
  1208. values = w.values || [],
  1209. keys = w.keys || values;
  1210. $.each(values, function (j, v) {
  1211. if (l % 20 === 0) {
  1212. html += '</div><div class="dw-bf">';
  1213. }
  1214. if(s.customWheels){
  1215. var keysHtml="{keys:\'" + keys[j] + "\',values:\'"+ values[j] +"\'}";
  1216. }else{
  1217. var keysHtml=keys[j];
  1218. }
  1219. html += '<div role="option" aria-selected="false" class="dw-li dw-v" data-val="' + keysHtml + '"' + (labels[j] ? ' aria-label="' + labels[j] + '"' : '') + ' style="height:' + itemHeight + 'px;line-height:' + itemHeight + 'px;">' +
  1220. '<div class="dw-i"' + (lines > 1 ? ' style="line-height:' + Math.round(itemHeight / lines) + 'px;font-size:' + Math.round(itemHeight / lines * 0.8) + 'px;"' : '') + '>' + v + '</div></div>';
  1221. l++;
  1222. });
  1223. html += '</div>';
  1224. return html;
  1225. }
  1226. function setGlobals(t) {
  1227. multiple = t.closest('.dwwl').hasClass('dwwms');
  1228. min = $('.dw-li', t).index($(multiple ? '.dw-li' : '.dw-v', t).eq(0));
  1229. max = Math.max(min, $('.dw-li', t).index($(multiple ? '.dw-li' : '.dw-v', t).eq(-1)) - (multiple ? s.rows - (s.mode == 'scroller' ? 1 : 3) : 0));
  1230. index = $('.dw-ul', $markup).index(t);
  1231. }
  1232. function formatHeader(v) {
  1233. var t = s.headerText;
  1234. return t ? (typeof t === 'function' ? t.call(el, v) : t.replace(/\{value\}/i, v)) : '';
  1235. }
  1236. function getCurrentPosition(t) {
  1237. return Math.round(-util.getPosition(t, true) / itemHeight);
  1238. }
  1239. function ready(t, i) {
  1240. clearTimeout(iv[i]);
  1241. delete iv[i];
  1242. t.closest('.dwwl').removeClass('dwa');
  1243. }
  1244. function scroll(t, index, val, time, active) {
  1245. var px = -val * itemHeight,
  1246. style = t[0].style;
  1247. if (px == pixels[index] && iv[index]) {
  1248. return;
  1249. }
  1250. //if (time && px != pixels[index]) {
  1251. // Trigger animation start event
  1252. //trigger('onAnimStart', [$markup, index, time]);
  1253. //}
  1254. pixels[index] = px;
  1255. if (has3d) {
  1256. style[pr + 'Transition'] = util.prefix + 'transform ' + (time ? time.toFixed(3) : 0) + 's ease-out';
  1257. style[pr + 'Transform'] = 'translate3d(0,' + px + 'px,0)';
  1258. } else {
  1259. style.top = px + 'px';
  1260. }
  1261. if (iv[index]) {
  1262. ready(t, index);
  1263. }
  1264. if (time && active) {
  1265. t.closest('.dwwl').addClass('dwa');
  1266. iv[index] = setTimeout(function () {
  1267. ready(t, index);
  1268. }, time * 1000);
  1269. }
  1270. pos[index] = val;
  1271. }
  1272. function getValid(val, t, dir, multiple, select) {
  1273. var selected,
  1274. cell = $('.dw-li[data-val="' + val + '"]', t),
  1275. cells = $('.dw-li', t),
  1276. v = cells.index(cell),
  1277. l = cells.length;
  1278. if (multiple) {
  1279. setGlobals(t);
  1280. } else if (!cell.hasClass('dw-v')) { // Scroll to a valid cell
  1281. var cell1 = cell,
  1282. cell2 = cell,
  1283. dist1 = 0,
  1284. dist2 = 0;
  1285. while (v - dist1 >= 0 && !cell1.hasClass('dw-v')) {
  1286. dist1++;
  1287. cell1 = cells.eq(v - dist1);
  1288. }
  1289. while (v + dist2 < l && !cell2.hasClass('dw-v')) {
  1290. dist2++;
  1291. cell2 = cells.eq(v + dist2);
  1292. }
  1293. // If we have direction (+/- or mouse wheel), the distance does not count
  1294. if (((dist2 < dist1 && dist2 && dir !== 2) || !dist1 || (v - dist1 < 0) || dir == 1) && cell2.hasClass('dw-v')) {
  1295. cell = cell2;
  1296. v = v + dist2;
  1297. } else {
  1298. cell = cell1;
  1299. v = v - dist1;
  1300. }
  1301. }
  1302. selected = cell.hasClass('dw-sel');
  1303. if (select) {
  1304. if (!multiple) {
  1305. $('.dw-sel', t).removeAttr('aria-selected');
  1306. cell.attr('aria-selected', 'true');
  1307. }
  1308. // Add selected class to cell
  1309. $('.dw-sel', t).removeClass('dw-sel');
  1310. cell.addClass('dw-sel');
  1311. }
  1312. return {
  1313. selected: selected,
  1314. v: multiple ? constrain(v, min, max) : v,
  1315. val: cell.hasClass('dw-v') ? cell.attr('data-val') : null
  1316. };
  1317. }
  1318. function scrollToPos(time, index, manual, dir, active) {
  1319. // Call validation event
  1320. if (trigger('validate', [$markup, index, time, dir]) !== false) {
  1321. // Set scrollers to position
  1322. $('.dw-ul', $markup).each(function (i) {
  1323. var t = $(this),
  1324. multiple = t.closest('.dwwl').hasClass('dwwms'),
  1325. sc = i == index || index === undefined,
  1326. res = getValid(that._tempWheelArray[i], t, dir, multiple, true),
  1327. selected = res.selected;
  1328. if (!selected || sc) {
  1329. // Set valid value
  1330. that._tempWheelArray[i] = res.val;
  1331. // Scroll to position
  1332. scroll(t, i, res.v, sc ? time : 0.1, sc ? active : false);
  1333. }
  1334. });
  1335. trigger('onValidated', []);
  1336. // Reformat value if validation changed something
  1337. that._tempValue = s.formatValue(that._tempWheelArray, that);
  1338. if (that.live) {
  1339. that._hasValue = manual || that._hasValue;
  1340. setValue(manual, manual, 0, true);
  1341. }
  1342. that._header.html(formatHeader(that._tempValue));
  1343. if (manual) {
  1344. trigger('onChange', [that._tempValue]);
  1345. }
  1346. }
  1347. }
  1348. function calc(t, idx, val, dir, time, active) {
  1349. //val = constrain(val, min, max);
  1350. // Set selected scroller value
  1351. that._tempWheelArray[idx] = $('.dw-li', t).eq(val).attr('data-val');
  1352. //scroll(t, idx, val, time, active);
  1353. setTimeout(function () {
  1354. // Validate
  1355. scrollToPos(time, idx, true, dir, active);
  1356. }, 10);
  1357. }
  1358. function plus(t) {
  1359. var val = pos[index] + 1;
  1360. calc(t, index, val > max ? min : val, 1, 0.1);
  1361. }
  1362. function minus(t) {
  1363. var val = pos[index] - 1;
  1364. calc(t, index, val < min ? max : val, 2, 0.1);
  1365. }
  1366. function setValue(fill, change, time, noscroll, temp) {
  1367. if (that._isVisible && !noscroll) {
  1368. scrollToPos(time);
  1369. }
  1370. that._tempValue = s.formatValue(that._tempWheelArray, that);
  1371. if (!temp) {
  1372. that._wheelArray = that._tempWheelArray.slice(0);
  1373. that._value = that._hasValue ? that._tempValue : null;
  1374. }
  1375. if (fill) {
  1376. trigger('onValueFill', [that._hasValue ? that._tempValue : '', change]);
  1377. if (that._isInput) {
  1378. $elm.val(that._hasValue ? that._tempValue : '');
  1379. }
  1380. if (change) {
  1381. that._preventChange = true;
  1382. $elm.change();
  1383. }
  1384. }
  1385. }
  1386. // Call the parent constructor
  1387. classes.Frame.call(this, el, settings, true);
  1388. // Public functions
  1389. /**
  1390. * Gets the selected wheel values, formats it, and set the value of the scroller instance.
  1391. * If input parameter is true, populates the associated input element.
  1392. * @param {Array} values Wheel values.
  1393. * @param {Boolean} [fill=false] Also set the value of the associated input element.
  1394. * @param {Number} [time=0] Animation time
  1395. * @param {Boolean} [temp=false] If true, then only set the temporary value.(only scroll there but not set the value)
  1396. * @param {Boolean} [change=false] Trigger change on the input element
  1397. */
  1398. that.setVal = that._setVal = function (val, fill, change, temp, time) {
  1399. that._hasValue = val !== null && val !== undefined;
  1400. that._tempWheelArray = $.isArray(val) ? val.slice(0) : s.parseValue.call(el, val, that) || [];
  1401. setValue(fill, change === undefined ? fill : change, time, false, temp);
  1402. };
  1403. /**
  1404. * Returns the selected value
  1405. */
  1406. that.getVal = that._getVal = function (temp) {
  1407. var val = that._hasValue || temp ? that[temp ? '_tempValue' : '_value'] : null;
  1408. return util.isNumeric(val) ? +val : val;
  1409. };
  1410. /*
  1411. * Sets the wheel values (passed as an array)
  1412. */
  1413. that.setArrayVal = that.setVal;
  1414. /*
  1415. * Returns the selected wheel values as an array
  1416. */
  1417. that.getArrayVal = function (temp) {
  1418. return temp ? that._tempWheelArray : that._wheelArray;
  1419. };
  1420. // @deprecated since 2.14.0, backward compatibility code
  1421. // ---
  1422. that.setValue = function (val, fill, time, temp, change) {
  1423. that.setVal(val, fill, change, temp, time);
  1424. };
  1425. /**
  1426. * Return the selected wheel values.
  1427. */
  1428. that.getValue = that.getArrayVal;
  1429. // ---
  1430. /**
  1431. * Changes the values of a wheel, and scrolls to the correct position
  1432. * @param {Array} idx Indexes of the wheels to change.
  1433. * @param {Number} [time=0] Animation time when scrolling to the selected value on the new wheel.
  1434. * @param {Boolean} [manual=false] Indicates that the change was triggered by the user or from code.
  1435. */
  1436. that.changeWheel = function (idx, time, manual) {
  1437. if ($markup) {
  1438. var i = 0,
  1439. nr = idx.length;
  1440. $.each(s.wheels, function (j, wg) {
  1441. $.each(wg, function (k, w) {
  1442. if ($.inArray(i, idx) > -1) {
  1443. wheels[i] = w;
  1444. $('.dw-ul', $markup).eq(i).html(generateWheelItems(i));
  1445. nr--;
  1446. if (!nr) {
  1447. that.position();
  1448. scrollToPos(time, undefined, manual);
  1449. return false;
  1450. }
  1451. }
  1452. i++;
  1453. });
  1454. if (!nr) {
  1455. return false;
  1456. }
  1457. });
  1458. }
  1459. };
  1460. that.selectWheel = function (keyVal, time, manual) {
  1461. $.each(s.wheels, function (j, wg) {
  1462. $.each(wg, function (k, w) {
  1463. $.each(w.keys,function(l,d){
  1464. if(keyVal[k]==d){
  1465. var $el=$('.dwfl',that._markup).eq(k);
  1466. calc($el, k, l, 1, 0.1);
  1467. }
  1468. });
  1469. });
  1470. });
  1471. };
  1472. /**
  1473. * Returns the closest valid cell.
  1474. */
  1475. that.getValidCell = getValid;
  1476. that.scroll = scroll;
  1477. // Protected overrides
  1478. that._generateContent = function () {
  1479. var lbl,
  1480. html = '',
  1481. l = 0;
  1482. $.each(s.wheels, function (i, wg) { // Wheel groups
  1483. html += '<div class="mbsc-w-p dwc' + (s.mode != 'scroller' ? ' dwpm' : ' dwsc') + (s.showLabel ? '' : ' dwhl') + '">' +
  1484. '<div class="dwwc"' + (s.maxWidth ? '' : ' style="max-width:600px;"') + '>' +
  1485. (hasFlex ? '' : '<table class="dw-tbl" cellpadding="0" cellspacing="0"><tr>');
  1486. $.each(wg, function (j, w) { // Wheels
  1487. wheels[l] = w;
  1488. lbl = w.label !== undefined ? w.label : j;
  1489. html += '<' + (hasFlex ? 'div' : 'td') + ' class="dwfl"' + ' style="' +
  1490. (s.fixedWidth ? ('width:' + (s.fixedWidth[l] || s.fixedWidth) + 'px;') :
  1491. (s.minWidth ? ('min-width:' + (s.minWidth[l] || s.minWidth) + 'px;') : 'min-width:' + s.width + 'px;') +
  1492. (s.maxWidth ? ('max-width:' + (s.maxWidth[l] || s.maxWidth) + 'px;') : '')) + '">' +
  1493. '<div class="dwwl dwwl' + l + (w.multiple ? ' dwwms' : '') + '">' +
  1494. (s.mode != 'scroller' ?
  1495. '<div class="dwb-e dwwb dwwbp ' + (s.btnPlusClass || '') + '" style="height:' + itemHeight + 'px;line-height:' + itemHeight + 'px;"><span>+</span></div>' + // + button
  1496. '<div class="dwb-e dwwb dwwbm ' + (s.btnMinusClass || '') + '" style="height:' + itemHeight + 'px;line-height:' + itemHeight + 'px;"><span>&ndash;</span></div>' : '') + // - button
  1497. '<div class="dwl">' + lbl + '</div>' + // Wheel label
  1498. '<div tabindex="0" aria-live="off" aria-label="' + lbl + '" role="listbox" class="dwww">' +
  1499. '<div class="dww" style="height:' + (s.rows * itemHeight) + 'px;">' +
  1500. '<div class="dw-ul" style="margin-top:' + (w.multiple ? (s.mode == 'scroller' ? 0 : itemHeight) : s.rows / 2 * itemHeight - itemHeight / 2) + 'px;">';
  1501. // Create wheel values
  1502. html += generateWheelItems(l) +
  1503. '</div></div><div class="dwwo"></div></div><div class="dwwol"' +
  1504. (s.selectedLineHeight ? ' style="height:' + itemHeight + 'px;margin-top:-' + (itemHeight / 2 + (s.selectedLineBorder || 0)) + 'px;"' : '') + '></div></div>' +
  1505. (hasFlex ? '</div>' : '</td>');
  1506. l++;
  1507. });
  1508. html += (hasFlex ? '' : '</tr></table>') + '</div></div>';
  1509. });
  1510. return html;
  1511. };
  1512. that._attachEvents = function ($markup) {
  1513. $markup
  1514. .on('keydown', '.dwwl', onKeyDown)
  1515. .on('keyup', '.dwwl', onKeyUp)
  1516. .on('touchstart mousedown', '.dwwl', onStart)
  1517. .on('touchmove', '.dwwl', onMove)
  1518. .on('touchend', '.dwwl', onEnd)
  1519. .on('touchstart mousedown', '.dwwb', onBtnStart)
  1520. .on('touchend', '.dwwb', onBtnEnd);
  1521. if (s.mousewheel) {
  1522. $markup.on('wheel mousewheel', '.dwwl', onScroll);
  1523. }
  1524. };
  1525. that._markupReady = function ($m) {
  1526. $markup = $m;
  1527. scrollToPos();
  1528. };
  1529. that._fillValue = function () {
  1530. that._hasValue = true;
  1531. setValue(true, true, 0, true);
  1532. };
  1533. that._readValue = function () {
  1534. var v = $elm.val() || '';
  1535. if (v !== '') {
  1536. that._hasValue = true;
  1537. }
  1538. that._tempWheelArray = that._hasValue && that._wheelArray ? that._wheelArray.slice(0) : s.parseValue.call(el, v, that) || [];
  1539. setValue();
  1540. };
  1541. that._processSettings = function () {
  1542. s = that.settings;
  1543. trigger = that.trigger;
  1544. itemHeight = s.height;
  1545. lines = s.multiline;
  1546. that._isLiquid = (s.layout || (/top|bottom/.test(s.display) && s.wheels.length == 1 ? 'liquid' : '')) === 'liquid';
  1547. // @deprecated since 2.15.0, backward compatibility code
  1548. // ---
  1549. if (s.formatResult) {
  1550. s.formatValue = s.formatResult;
  1551. }
  1552. // ---
  1553. if (lines > 1) {
  1554. s.cssClass = (s.cssClass || '') + ' dw-ml';
  1555. }
  1556. // Ensure a minimum number of 3 items if clickpick buttons present
  1557. if (s.mode != 'scroller') {
  1558. s.rows = Math.max(3, s.rows);
  1559. }
  1560. };
  1561. // Properties
  1562. that._selectedValues = {};
  1563. // Constructor
  1564. if (!inherit) {
  1565. that.init(settings);
  1566. }
  1567. };
  1568. // Extend defaults
  1569. classes.Scroller.prototype = {
  1570. _hasDef: true,
  1571. _hasTheme: true,
  1572. _hasLang: true,
  1573. _hasPreset: true,
  1574. _class: 'scroller',
  1575. _defaults: $.extend({}, classes.Frame.prototype._defaults, {
  1576. // Options
  1577. minWidth: 80,
  1578. height: 40,
  1579. rows: 3,
  1580. multiline: 1,
  1581. delay: 300,
  1582. readonly: false,
  1583. showLabel: false,
  1584. confirmOnTap: true,
  1585. wheels: [],
  1586. mode: 'scroller',
  1587. preset: '',
  1588. speedUnit: 0.0012,
  1589. timeUnit: 0.08,
  1590. formatValue: function (d) {
  1591. return d.join(' ');
  1592. },
  1593. parseValue: function (value, inst) {
  1594. var val = [],
  1595. ret = [],
  1596. i = 0,
  1597. found,
  1598. keys;
  1599. if (value !== null && value !== undefined) {
  1600. val = (value + '').split(' ');
  1601. }
  1602. $.each(inst.settings.wheels, function (j, wg) {
  1603. $.each(wg, function (k, w) {
  1604. keys = w.keys || w.values;
  1605. found = keys[0]; // Default to first wheel value if not found
  1606. $.each(keys, function (l, key) {
  1607. if (val[i] == key) { // Don't do strict comparison
  1608. found = key;
  1609. return false;
  1610. }
  1611. });
  1612. ret.push(found);
  1613. i++;
  1614. });
  1615. });
  1616. return ret;
  1617. }
  1618. })
  1619. };
  1620. ms.themes.scroller = ms.themes.frame;
  1621. })(jQuery, window, document);
  1622. //mobiscroll.util.datetime.js
  1623. (function ($, undefined) {
  1624. var ms = $.mobiscroll;
  1625. ms.datetime = {
  1626. defaults: {
  1627. shortYearCutoff: '+10',
  1628. monthNames: ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'],
  1629. monthNamesShort: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
  1630. dayNames: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'],
  1631. dayNamesShort: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
  1632. dayNamesMin: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
  1633. amText: 'am',
  1634. pmText: 'pm',
  1635. getYear: function (d) { return d.getFullYear(); },
  1636. getMonth: function (d) { return d.getMonth(); },
  1637. getDay: function (d) { return d.getDate(); },
  1638. getDate: function (y, m, d, h, i, s, u) { return new Date(y, m, d, h || 0, i || 0, s || 0, u || 0); },
  1639. getMaxDayOfMonth: function (y, m) { return 32 - new Date(y, m, 32).getDate(); },
  1640. getWeekNumber: function (d) {
  1641. // Copy date so don't modify original
  1642. d = new Date(d);
  1643. d.setHours(0, 0, 0);
  1644. // Set to nearest Thursday: current date + 4 - current day number
  1645. // Make Sunday's day number 7
  1646. d.setDate(d.getDate() + 4 - (d.getDay() || 7));
  1647. // Get first day of year
  1648. var yearStart = new Date(d.getFullYear(), 0, 1);
  1649. // Calculate full weeks to nearest Thursday
  1650. return Math.ceil((((d - yearStart) / 86400000) + 1) / 7);
  1651. }
  1652. },
  1653. /**
  1654. * Format a date into a string value with a specified format.
  1655. * @param {String} format Output format.
  1656. * @param {Date} date Date to format.
  1657. * @param {Object} [settings={}] Settings.
  1658. * @return {String} Returns the formatted date string.
  1659. */
  1660. formatDate: function (format, date, settings) {
  1661. if (!date) {
  1662. return null;
  1663. }
  1664. var s = $.extend({}, ms.datetime.defaults, settings),
  1665. look = function (m) { // Check whether a format character is doubled
  1666. var n = 0;
  1667. while (i + 1 < format.length && format.charAt(i + 1) == m) {
  1668. n++;
  1669. i++;
  1670. }
  1671. return n;
  1672. },
  1673. f1 = function (m, val, len) { // Format a number, with leading zero if necessary
  1674. var n = '' + val;
  1675. if (look(m)) {
  1676. while (n.length < len) {
  1677. n = '0' + n;
  1678. }
  1679. }
  1680. return n;
  1681. },
  1682. f2 = function (m, val, s, l) { // Format a name, short or long as requested
  1683. return (look(m) ? l[val] : s[val]);
  1684. },
  1685. i,
  1686. year,
  1687. output = '',
  1688. literal = false;
  1689. for (i = 0; i < format.length; i++) {
  1690. if (literal) {
  1691. if (format.charAt(i) == "'" && !look("'")) {
  1692. literal = false;
  1693. } else {
  1694. output += format.charAt(i);
  1695. }
  1696. } else {
  1697. switch (format.charAt(i)) {
  1698. case 'd':
  1699. output += f1('d', s.getDay(date), 2);
  1700. break;
  1701. case 'D':
  1702. output += f2('D', date.getDay(), s.dayNamesShort, s.dayNames);
  1703. break;
  1704. case 'o':
  1705. output += f1('o', (date.getTime() - new Date(date.getFullYear(), 0, 0).getTime()) / 86400000, 3);
  1706. break;
  1707. case 'm':
  1708. output += f1('m', s.getMonth(date) + 1, 2);
  1709. break;
  1710. case 'M':
  1711. output += f2('M', s.getMonth(date), s.monthNamesShort, s.monthNames);
  1712. break;
  1713. case 'y':
  1714. year = s.getYear(date);
  1715. output += (look('y') ? year : (year % 100 < 10 ? '0' : '') + year % 100);
  1716. //output += (look('y') ? date.getFullYear() : (date.getYear() % 100 < 10 ? '0' : '') + date.getYear() % 100);
  1717. break;
  1718. case 'h':
  1719. var h = date.getHours();
  1720. output += f1('h', (h > 12 ? (h - 12) : (h === 0 ? 12 : h)), 2);
  1721. break;
  1722. case 'H':
  1723. output += f1('H', date.getHours(), 2);
  1724. break;
  1725. case 'i':
  1726. output += f1('i', date.getMinutes(), 2);
  1727. break;
  1728. case 's':
  1729. output += f1('s', date.getSeconds(), 2);
  1730. break;
  1731. case 'a':
  1732. output += date.getHours() > 11 ? s.pmText : s.amText;
  1733. break;
  1734. case 'A':
  1735. output += date.getHours() > 11 ? s.pmText.toUpperCase() : s.amText.toUpperCase();
  1736. break;
  1737. case "'":
  1738. if (look("'")) {
  1739. output += "'";
  1740. } else {
  1741. literal = true;
  1742. }
  1743. break;
  1744. default:
  1745. output += format.charAt(i);
  1746. }
  1747. }
  1748. }
  1749. return output;
  1750. },
  1751. /**
  1752. * Extract a date from a string value with a specified format.
  1753. * @param {String} format Input format.
  1754. * @param {String} value String to parse.
  1755. * @param {Object} [settings={}] Settings.
  1756. * @return {Date} Returns the extracted date.
  1757. */
  1758. parseDate: function (format, value, settings) {
  1759. var s = $.extend({}, ms.datetime.defaults, settings),
  1760. def = s.defaultValue || new Date();
  1761. if (!format || !value) {
  1762. return def;
  1763. }
  1764. // If already a date object
  1765. if (value.getTime) {
  1766. return value;
  1767. }
  1768. value = (typeof value == 'object' ? value.toString() : value + '');
  1769. var shortYearCutoff = s.shortYearCutoff,
  1770. year = s.getYear(def),
  1771. month = s.getMonth(def) + 1,
  1772. day = s.getDay(def),
  1773. doy = -1,
  1774. hours = def.getHours(),
  1775. minutes = def.getMinutes(),
  1776. seconds = 0, //def.getSeconds(),
  1777. ampm = -1,
  1778. literal = false, // Check whether a format character is doubled
  1779. lookAhead = function (match) {
  1780. var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) == match);
  1781. if (matches) {
  1782. iFormat++;
  1783. }
  1784. return matches;
  1785. },
  1786. getNumber = function (match) { // Extract a number from the string value
  1787. lookAhead(match);
  1788. var size = (match == '@' ? 14 : (match == '!' ? 20 : (match == 'y' ? 4 : (match == 'o' ? 3 : 2)))),
  1789. digits = new RegExp('^\\d{1,' + size + '}'),
  1790. num = value.substr(iValue).match(digits);
  1791. if (!num) {
  1792. return 0;
  1793. }
  1794. iValue += num[0].length;
  1795. return parseInt(num[0], 10);
  1796. },
  1797. getName = function (match, s, l) { // Extract a name from the string value and convert to an index
  1798. var names = (lookAhead(match) ? l : s),
  1799. i;
  1800. for (i = 0; i < names.length; i++) {
  1801. if (value.substr(iValue, names[i].length).toLowerCase() == names[i].toLowerCase()) {
  1802. iValue += names[i].length;
  1803. return i + 1;
  1804. }
  1805. }
  1806. return 0;
  1807. },
  1808. checkLiteral = function () {
  1809. iValue++;
  1810. },
  1811. iValue = 0,
  1812. iFormat;
  1813. for (iFormat = 0; iFormat < format.length; iFormat++) {
  1814. if (literal) {
  1815. if (format.charAt(iFormat) == "'" && !lookAhead("'")) {
  1816. literal = false;
  1817. } else {
  1818. checkLiteral();
  1819. }
  1820. } else {
  1821. switch (format.charAt(iFormat)) {
  1822. case 'd':
  1823. day = getNumber('d');
  1824. break;
  1825. case 'D':
  1826. getName('D', s.dayNamesShort, s.dayNames);
  1827. break;
  1828. case 'o':
  1829. doy = getNumber('o');
  1830. break;
  1831. case 'm':
  1832. month = getNumber('m');
  1833. break;
  1834. case 'M':
  1835. month = getName('M', s.monthNamesShort, s.monthNames);
  1836. break;
  1837. case 'y':
  1838. year = getNumber('y');
  1839. break;
  1840. case 'H':
  1841. hours = getNumber('H');
  1842. break;
  1843. case 'h':
  1844. hours = getNumber('h');
  1845. break;
  1846. case 'i':
  1847. minutes = getNumber('i');
  1848. break;
  1849. case 's':
  1850. seconds = getNumber('s');
  1851. break;
  1852. case 'a':
  1853. ampm = getName('a', [s.amText, s.pmText], [s.amText, s.pmText]) - 1;
  1854. break;
  1855. case 'A':
  1856. ampm = getName('A', [s.amText, s.pmText], [s.amText, s.pmText]) - 1;
  1857. break;
  1858. case "'":
  1859. if (lookAhead("'")) {
  1860. checkLiteral();
  1861. } else {
  1862. literal = true;
  1863. }
  1864. break;
  1865. default:
  1866. checkLiteral();
  1867. }
  1868. }
  1869. }
  1870. if (year < 100) {
  1871. year += new Date().getFullYear() - new Date().getFullYear() % 100 +
  1872. (year <= (typeof shortYearCutoff != 'string' ? shortYearCutoff : new Date().getFullYear() % 100 + parseInt(shortYearCutoff, 10)) ? 0 : -100);
  1873. }
  1874. if (doy > -1) {
  1875. month = 1;
  1876. day = doy;
  1877. do {
  1878. var dim = 32 - new Date(year, month - 1, 32).getDate();
  1879. if (day <= dim) {
  1880. break;
  1881. }
  1882. month++;
  1883. day -= dim;
  1884. } while (true);
  1885. }
  1886. hours = (ampm == -1) ? hours : ((ampm && hours < 12) ? (hours + 12) : (!ampm && hours == 12 ? 0 : hours));
  1887. var date = s.getDate(year, month - 1, day, hours, minutes, seconds);
  1888. if (s.getYear(date) != year || s.getMonth(date) + 1 != month || s.getDay(date) != day) {
  1889. return def; // Invalid date
  1890. }
  1891. return date;
  1892. }
  1893. };
  1894. // @deprecated since 2.11.0, backward compatibility code
  1895. // ---
  1896. ms.formatDate = ms.datetime.formatDate;
  1897. ms.parseDate = ms.datetime.parseDate;
  1898. // ---
  1899. })(jQuery);
  1900. //mobiscroll.datetimebase.js
  1901. (function ($, undefined) {
  1902. var ms = $.mobiscroll,
  1903. datetime = ms.datetime,
  1904. date = new Date(),
  1905. defaults = {
  1906. startYear: date.getFullYear() - 100,
  1907. endYear: date.getFullYear() + 1,
  1908. separator: ' ',
  1909. // Localization
  1910. dateFormat: 'yy-mm-dd',
  1911. dateOrder: 'yymmdd',
  1912. timeWheels: 'hhiiA',
  1913. timeFormat: 'hh:ii A',
  1914. dayText: 'Day',
  1915. monthText: 'Month',
  1916. yearText: 'Year',
  1917. hourText: 'Hours',
  1918. minuteText: 'Minutes',
  1919. ampmText: '&nbsp;',
  1920. secText: 'Seconds',
  1921. nowText: 'Now'
  1922. },
  1923. /**
  1924. * @class Mobiscroll.datetime
  1925. * @extends Mobiscroll
  1926. * Mobiscroll Datetime component
  1927. */
  1928. preset = function (inst) {
  1929. var that = $(this),
  1930. html5def = {},
  1931. format;
  1932. // Force format for html5 date inputs (experimental)
  1933. if (that.is('input')) {
  1934. switch (that.attr('type')) {
  1935. case 'date':
  1936. format = 'yy-mm-dd';
  1937. break;
  1938. case 'datetime':
  1939. format = 'yy-mm-ddTHH:ii:ssZ';
  1940. break;
  1941. case 'datetime-local':
  1942. format = 'yy-mm-ddTHH:ii:ss';
  1943. break;
  1944. case 'month':
  1945. format = 'yy-mm';
  1946. html5def.dateOrder = 'mmyy';
  1947. break;
  1948. case 'time':
  1949. format = 'HH:ii:ss';
  1950. break;
  1951. }
  1952. // Check for min/max attributes
  1953. var min = that.attr('min'),
  1954. max = that.attr('max');
  1955. if (min) {
  1956. html5def.minDate = datetime.parseDate(format, min);
  1957. }
  1958. if (max) {
  1959. html5def.maxDate = datetime.parseDate(format, max);
  1960. }
  1961. }
  1962. // Set year-month-day order
  1963. var i,
  1964. k,
  1965. keys,
  1966. values,
  1967. wg,
  1968. start,
  1969. end,
  1970. hasTime,
  1971. mins,
  1972. maxs,
  1973. orig = $.extend({}, inst.settings),
  1974. s = $.extend(inst.settings, ms.datetime.defaults, defaults, html5def, orig),
  1975. offset = 0,
  1976. validValues = [],
  1977. wheels = [],
  1978. ord = [],
  1979. o = {},
  1980. innerValues = {},
  1981. f = { y: getYear, m: getMonth, d: getDay, h: getHour, i: getMinute, s: getSecond, u: getMillisecond, a: getAmPm },
  1982. invalid = s.invalid,
  1983. valid = s.valid,
  1984. p = s.preset,
  1985. dord = s.dateOrder,
  1986. tord = s.timeWheels,
  1987. regen = dord.match(/D/),
  1988. ampm = tord.match(/a/i),
  1989. hampm = tord.match(/h/),
  1990. hformat = p == 'datetime' ? s.dateFormat + s.separator + s.timeFormat : p == 'time' ? s.timeFormat : s.dateFormat,
  1991. defd = new Date(),
  1992. steps = s.steps || {},
  1993. stepH = steps.hour || s.stepHour || 1,
  1994. stepM = steps.minute || s.stepMinute || 1,
  1995. stepS = steps.second || s.stepSecond || 1,
  1996. zeroBased = steps.zeroBased,
  1997. mind = s.minDate || new Date(s.startYear, 0, 1),
  1998. maxd = s.maxDate || new Date(s.endYear, 11, 31, 23, 59, 59),
  1999. minH = zeroBased ? 0 : mind.getHours() % stepH,
  2000. minM = zeroBased ? 0 : mind.getMinutes() % stepM,
  2001. minS = zeroBased ? 0 : mind.getSeconds() % stepS,
  2002. maxH = getMax(stepH, minH, (hampm ? 11 : 23)),
  2003. maxM = getMax(stepM, minM, 59),
  2004. maxS = getMax(stepM, minM, 59);
  2005. format = format || hformat;
  2006. if (p.match(/date/i)) {
  2007. // Determine the order of year, month, day wheels
  2008. $.each(['y', 'm', 'd'], function (j, v) {
  2009. i = dord.search(new RegExp(v, 'i'));
  2010. if (i > -1) {
  2011. ord.push({ o: i, v: v });
  2012. }
  2013. });
  2014. ord.sort(function (a, b) { return a.o > b.o ? 1 : -1; });
  2015. $.each(ord, function (i, v) {
  2016. o[v.v] = i;
  2017. });
  2018. wg = [];
  2019. for (k = 0; k < 3; k++) {
  2020. if (k == o.y) {
  2021. offset++;
  2022. values = [];
  2023. keys = [];
  2024. start = s.getYear(mind);
  2025. end = s.getYear(maxd);
  2026. for (i = start; i <= end; i++) {
  2027. keys.push(i);
  2028. values.push((dord.match(/yy/i) ? i : (i + '').substr(2, 2)) + (s.yearSuffix || ''));
  2029. }
  2030. addWheel(wg, keys, values, s.yearText);
  2031. } else if (k == o.m) {
  2032. offset++;
  2033. values = [];
  2034. keys = [];
  2035. for (i = 0; i < 12; i++) {
  2036. var str = dord.replace(/[dy]/gi, '').replace(/mm/, (i < 9 ? '0' + (i + 1) : i + 1) + (s.monthSuffix || '')).replace(/m/, i + 1 + (s.monthSuffix || ''));
  2037. keys.push(i);
  2038. values.push(str.match(/MM/) ? str.replace(/MM/, '<span class="dw-mon">' + s.monthNames[i] + '</span>') : str.replace(/M/, '<span class="dw-mon">' + s.monthNamesShort[i] + '</span>'));
  2039. }
  2040. addWheel(wg, keys, values, s.monthText);
  2041. } else if (k == o.d) {
  2042. offset++;
  2043. values = [];
  2044. keys = [];
  2045. for (i = 1; i < 32; i++) {
  2046. keys.push(i);
  2047. values.push((dord.match(/dd/i) && i < 10 ? '0' + i : i) + (s.daySuffix || ''));
  2048. }
  2049. addWheel(wg, keys, values, s.dayText);
  2050. }
  2051. }
  2052. wheels.push(wg);
  2053. }
  2054. if (p.match(/time/i)) {
  2055. hasTime = true;
  2056. // Determine the order of hours, minutes, seconds wheels
  2057. ord = [];
  2058. $.each(['h', 'i', 's', 'a'], function (i, v) {
  2059. i = tord.search(new RegExp(v, 'i'));
  2060. if (i > -1) {
  2061. ord.push({ o: i, v: v });
  2062. }
  2063. });
  2064. ord.sort(function (a, b) {
  2065. return a.o > b.o ? 1 : -1;
  2066. });
  2067. $.each(ord, function (i, v) {
  2068. o[v.v] = offset + i;
  2069. });
  2070. wg = [];
  2071. for (k = offset; k < offset + 4; k++) {
  2072. if (k == o.h) {
  2073. offset++;
  2074. values = [];
  2075. keys = [];
  2076. for (i = minH; i < (hampm ? 12 : 24); i += stepH) {
  2077. keys.push(i);
  2078. values.push(hampm && i === 0 ? 12 : tord.match(/hh/i) && i < 10 ? '0' + i : i);
  2079. }
  2080. addWheel(wg, keys, values, s.hourText);
  2081. } else if (k == o.i) {
  2082. offset++;
  2083. values = [];
  2084. keys = [];
  2085. for (i = minM; i < 60; i += stepM) {
  2086. keys.push(i);
  2087. values.push(tord.match(/ii/) && i < 10 ? '0' + i : i);
  2088. }
  2089. addWheel(wg, keys, values, s.minuteText);
  2090. } else if (k == o.s) {
  2091. offset++;
  2092. values = [];
  2093. keys = [];
  2094. for (i = minS; i < 60; i += stepS) {
  2095. keys.push(i);
  2096. values.push(tord.match(/ss/) && i < 10 ? '0' + i : i);
  2097. }
  2098. addWheel(wg, keys, values, s.secText);
  2099. } else if (k == o.a) {
  2100. offset++;
  2101. var upper = tord.match(/A/);
  2102. addWheel(wg, [0, 1], upper ? [s.amText.toUpperCase(), s.pmText.toUpperCase()] : [s.amText, s.pmText], s.ampmText);
  2103. }
  2104. }
  2105. wheels.push(wg);
  2106. }
  2107. function get(d, i, def) {
  2108. if (o[i] !== undefined) {
  2109. return +d[o[i]];
  2110. }
  2111. if (innerValues[i] !== undefined) {
  2112. return innerValues[i];
  2113. }
  2114. if (def !== undefined) {
  2115. return def;
  2116. }
  2117. return f[i](defd);
  2118. }
  2119. function addWheel(wg, k, v, lbl) {
  2120. wg.push({
  2121. values: v,
  2122. keys: k,
  2123. label: lbl
  2124. });
  2125. }
  2126. function step(v, st, min, max) {
  2127. return Math.min(max, Math.floor(v / st) * st + min);
  2128. }
  2129. function getYear(d) {
  2130. return s.getYear(d);
  2131. }
  2132. function getMonth(d) {
  2133. return s.getMonth(d);
  2134. }
  2135. function getDay(d) {
  2136. return s.getDay(d);
  2137. }
  2138. function getHour(d) {
  2139. var hour = d.getHours();
  2140. hour = hampm && hour >= 12 ? hour - 12 : hour;
  2141. return step(hour, stepH, minH, maxH);
  2142. }
  2143. function getMinute(d) {
  2144. return step(d.getMinutes(), stepM, minM, maxM);
  2145. }
  2146. function getSecond(d) {
  2147. return step(d.getSeconds(), stepS, minS, maxS);
  2148. }
  2149. function getMillisecond(d) {
  2150. return d.getMilliseconds();
  2151. }
  2152. function getAmPm(d) {
  2153. return ampm && d.getHours() > 11 ? 1 : 0;
  2154. }
  2155. function getDate(d) {
  2156. if (d === null) {
  2157. return d;
  2158. }
  2159. var year = get(d, 'y'),
  2160. month = get(d, 'm'),
  2161. day = Math.min(get(d, 'd', 1), s.getMaxDayOfMonth(year, month)),
  2162. hour = get(d, 'h', 0);
  2163. return s.getDate(year, month, day, get(d, 'a', 0) ? hour + 12 : hour, get(d, 'i', 0), get(d, 's', 0), get(d, 'u', 0));
  2164. }
  2165. function getMax(step, min, max) {
  2166. return Math.floor((max - min) / step) * step + min;
  2167. }
  2168. function getClosestValidDate(d, dir) {
  2169. var next,
  2170. prev,
  2171. nextValid = false,
  2172. prevValid = false,
  2173. up = 0,
  2174. down = 0;
  2175. // Normalize min and max dates for comparing later (set default values where there are no values from wheels)
  2176. mind = getDate(getArray(mind));
  2177. maxd = getDate(getArray(maxd));
  2178. if (isValid(d)) {
  2179. return d;
  2180. }
  2181. if (d < mind) {
  2182. d = mind;
  2183. }
  2184. if (d > maxd) {
  2185. d = maxd;
  2186. }
  2187. next = d;
  2188. prev = d;
  2189. if (dir !== 2) {
  2190. nextValid = isValid(next);
  2191. while (!nextValid && next < maxd) {
  2192. next = new Date(next.getTime() + 1000 * 60 * 60 * 24);
  2193. nextValid = isValid(next);
  2194. up++;
  2195. }
  2196. }
  2197. if (dir !== 1) {
  2198. prevValid = isValid(prev);
  2199. while (!prevValid && prev > mind) {
  2200. prev = new Date(prev.getTime() - 1000 * 60 * 60 * 24);
  2201. prevValid = isValid(prev);
  2202. down++;
  2203. }
  2204. }
  2205. if (dir === 1 && nextValid) {
  2206. return next;
  2207. }
  2208. if (dir === 2 && prevValid) {
  2209. return prev;
  2210. }
  2211. return down <= up && prevValid ? prev : next;
  2212. }
  2213. function isValid(d) {
  2214. if (d < mind) {
  2215. return false;
  2216. }
  2217. if (d > maxd) {
  2218. return false;
  2219. }
  2220. if (isInObj(d, valid)) {
  2221. return true;
  2222. }
  2223. if (isInObj(d, invalid)) {
  2224. return false;
  2225. }
  2226. return true;
  2227. }
  2228. function isInObj(d, obj) {
  2229. var curr,
  2230. j,
  2231. v;
  2232. if (obj) {
  2233. for (j = 0; j < obj.length; j++) {
  2234. curr = obj[j];
  2235. v = curr + '';
  2236. if (!curr.start) {
  2237. if (curr.getTime) { // Exact date
  2238. if (d.getFullYear() == curr.getFullYear() && d.getMonth() == curr.getMonth() && d.getDate() == curr.getDate()) {
  2239. return true;
  2240. }
  2241. } else if (!v.match(/w/i)) { // Day of month
  2242. v = v.split('/');
  2243. if (v[1]) {
  2244. if ((v[0] - 1) == d.getMonth() && v[1] == d.getDate()) {
  2245. return true;
  2246. }
  2247. } else if (v[0] == d.getDate()) {
  2248. return true;
  2249. }
  2250. } else { // Day of week
  2251. v = +v.replace('w', '');
  2252. if (v == d.getDay()) {
  2253. return true;
  2254. }
  2255. }
  2256. }
  2257. }
  2258. }
  2259. return false;
  2260. }
  2261. function validateDates(obj, y, m, first, maxdays, idx, val) {
  2262. var j, d, v;
  2263. if (obj) {
  2264. for (j = 0; j < obj.length; j++) {
  2265. d = obj[j];
  2266. v = d + '';
  2267. if (!d.start) {
  2268. if (d.getTime) { // Exact date
  2269. if (s.getYear(d) == y && s.getMonth(d) == m) {
  2270. idx[s.getDay(d) - 1] = val;
  2271. }
  2272. } else if (!v.match(/w/i)) { // Day of month
  2273. v = v.split('/');
  2274. if (v[1]) {
  2275. if (v[0] - 1 == m) {
  2276. idx[v[1] - 1] = val;
  2277. }
  2278. } else {
  2279. idx[v[0] - 1] = val;
  2280. }
  2281. } else { // Day of week
  2282. v = +v.replace('w', '');
  2283. for (k = v - first; k < maxdays; k += 7) {
  2284. if (k >= 0) {
  2285. idx[k] = val;
  2286. }
  2287. }
  2288. }
  2289. }
  2290. }
  2291. }
  2292. }
  2293. function validateTimes(vobj, i, v, temp, y, m, d, target, valid) {
  2294. var dd, ss, str, parts1, parts2, prop1, prop2, v1, v2, j, i1, i2, add, remove, all, hours1, hours2, hours3,
  2295. spec = {},
  2296. steps = { h: stepH, i: stepM, s: stepS, a: 1 },
  2297. day = s.getDate(y, m, d),
  2298. w = ['a', 'h', 'i', 's'];
  2299. if (vobj) {
  2300. $.each(vobj, function (i, obj) {
  2301. if (obj.start) {
  2302. obj.apply = false;
  2303. dd = obj.d;
  2304. ss = dd + '';
  2305. str = ss.split('/');
  2306. if (dd && ((dd.getTime && y == s.getYear(dd) && m == s.getMonth(dd) && d == s.getDay(dd)) || // Exact date
  2307. (!ss.match(/w/i) && ((str[1] && d == str[1] && m == str[0] - 1) || (!str[1] && d == str[0]))) || // Day of month
  2308. (ss.match(/w/i) && day.getDay() == +ss.replace('w', '')) // Day of week
  2309. )) {
  2310. obj.apply = true;
  2311. spec[day] = true; // Prevent applying generic rule on day, if specific exists
  2312. }
  2313. }
  2314. });
  2315. $.each(vobj, function (x, obj) {
  2316. add = 0;
  2317. remove = 0;
  2318. i1 = 0;
  2319. i2 = undefined;
  2320. prop1 = true;
  2321. prop2 = true;
  2322. all = false;
  2323. if (obj.start && (obj.apply || (!obj.d && !spec[day]))) {
  2324. // Define time parts
  2325. parts1 = obj.start.split(':');
  2326. parts2 = obj.end.split(':');
  2327. for (j = 0; j < 3; j++) {
  2328. if (parts1[j] === undefined) {
  2329. parts1[j] = 0;
  2330. }
  2331. if (parts2[j] === undefined) {
  2332. parts2[j] = 59;
  2333. }
  2334. parts1[j] = +parts1[j];
  2335. parts2[j] = +parts2[j];
  2336. }
  2337. parts1.unshift(parts1[0] > 11 ? 1 : 0);
  2338. parts2.unshift(parts2[0] > 11 ? 1 : 0);
  2339. if (hampm) {
  2340. if (parts1[1] >= 12) {
  2341. parts1[1] = parts1[1] - 12;
  2342. }
  2343. if (parts2[1] >= 12) {
  2344. parts2[1] = parts2[1] - 12;
  2345. }
  2346. }
  2347. // Look behind
  2348. for (j = 0; j < i; j++) {
  2349. if (validValues[j] !== undefined) {
  2350. v1 = step(parts1[j], steps[w[j]], mins[w[j]], maxs[w[j]]);
  2351. v2 = step(parts2[j], steps[w[j]], mins[w[j]], maxs[w[j]]);
  2352. hours1 = 0;
  2353. hours2 = 0;
  2354. hours3 = 0;
  2355. if (hampm && j == 1) {
  2356. hours1 = parts1[0] ? 12 : 0;
  2357. hours2 = parts2[0] ? 12 : 0;
  2358. hours3 = validValues[0] ? 12 : 0;
  2359. }
  2360. if (!prop1) {
  2361. v1 = 0;
  2362. }
  2363. if (!prop2) {
  2364. v2 = maxs[w[j]];
  2365. }
  2366. if ((prop1 || prop2) && (v1 + hours1 < validValues[j] + hours3 && validValues[j] + hours3 < v2 + hours2)) {
  2367. all = true;
  2368. }
  2369. if (validValues[j] != v1) {
  2370. prop1 = false;
  2371. }
  2372. if (validValues[j] != v2) {
  2373. prop2 = false;
  2374. }
  2375. }
  2376. }
  2377. // Look ahead
  2378. if (!valid) {
  2379. for (j = i + 1; j < 4; j++) {
  2380. if (parts1[j] > 0) {
  2381. add = steps[v];
  2382. }
  2383. if (parts2[j] < maxs[w[j]]) {
  2384. remove = steps[v];
  2385. }
  2386. }
  2387. }
  2388. if (!all) {
  2389. // Calculate min and max values
  2390. v1 = step(parts1[i], steps[v], mins[v], maxs[v]) + add;
  2391. v2 = step(parts2[i], steps[v], mins[v], maxs[v]) - remove;
  2392. if (prop1) {
  2393. i1 = getValidIndex(target, v1, maxs[v], 0);
  2394. }
  2395. if (prop2) {
  2396. i2 = getValidIndex(target, v2, maxs[v], 1);
  2397. }
  2398. }
  2399. // Disable values
  2400. if (prop1 || prop2 || all) {
  2401. if (valid) {
  2402. $('.dw-li', target).slice(i1, i2).addClass('dw-v');
  2403. } else {
  2404. $('.dw-li', target).slice(i1, i2).removeClass('dw-v');
  2405. }
  2406. }
  2407. }
  2408. });
  2409. }
  2410. }
  2411. function getIndex(t, v) {
  2412. return $('.dw-li', t).index($('.dw-li[data-val="' + v + '"]', t));
  2413. }
  2414. function getValidIndex(t, v, max, add) {
  2415. if (v < 0) {
  2416. return 0;
  2417. }
  2418. if (v > max) {
  2419. return $('.dw-li', t).length;
  2420. }
  2421. return getIndex(t, v) + add;
  2422. }
  2423. function getArray(d, fillInner) {
  2424. var ret = [];
  2425. if (d === null || d === undefined) {
  2426. return d;
  2427. }
  2428. $.each(['y', 'm', 'd', 'a', 'h', 'i', 's', 'u'], function (x, i) {
  2429. if (o[i] !== undefined) {
  2430. ret[o[i]] = f[i](d);
  2431. }
  2432. if (fillInner) {
  2433. innerValues[i] = f[i](d);
  2434. }
  2435. });
  2436. return ret;
  2437. }
  2438. function convertRanges(arr) {
  2439. var i, v, start,
  2440. ret = [];
  2441. if (arr) {
  2442. for (i = 0; i < arr.length; i++) {
  2443. v = arr[i];
  2444. if (v.start && v.start.getTime) {
  2445. start = new Date(v.start);
  2446. while (start <= v.end) {
  2447. ret.push(new Date(start.getFullYear(), start.getMonth(), start.getDate()));
  2448. start.setDate(start.getDate() + 1);
  2449. }
  2450. } else {
  2451. ret.push(v);
  2452. }
  2453. }
  2454. return ret;
  2455. }
  2456. return arr;
  2457. }
  2458. // Extended methods
  2459. // ---
  2460. inst.getVal = function (temp) {
  2461. return inst._hasValue || temp ? getDate(inst.getArrayVal(temp)) : null;
  2462. };
  2463. /**
  2464. * Sets the selected date
  2465. *
  2466. * @param {Date} d Date to select.
  2467. * @param {Boolean} [fill=false] Also set the value of the associated input element. Default is true.
  2468. * @param {Number} [time=0] Animation time to scroll to the selected date.
  2469. * @param {Boolean} [temp=false] Set temporary value only.
  2470. * @param {Boolean} [change=fill] Trigger change on input element.
  2471. */
  2472. inst.setDate = function (d, fill, time, temp, change) {
  2473. inst.setArrayVal(getArray(d), fill, change, temp, time);
  2474. };
  2475. /**
  2476. * Returns the selected date.
  2477. *
  2478. * @param {Boolean} [temp=false] If true, return the currently shown date on the picker, otherwise the last selected one.
  2479. * @return {Date}
  2480. */
  2481. inst.getDate = inst.getVal;
  2482. // ---
  2483. // Initializations
  2484. // ---
  2485. inst.format = hformat;
  2486. inst.order = o;
  2487. inst.handlers.now = function () { inst.setDate(new Date(), false, 0.3, true, true); };
  2488. inst.buttons.now = { text: s.nowText, handler: 'now' };
  2489. invalid = convertRanges(invalid);
  2490. valid = convertRanges(valid);
  2491. mins = { y: mind.getFullYear(), m: 0, d: 1, h: minH, i: minM, s: minS, a: 0 };
  2492. maxs = { y: maxd.getFullYear(), m: 11, d: 31, h: maxH, i: maxM, s: maxS, a: 1 };
  2493. // ---
  2494. return {
  2495. wheels: wheels,
  2496. headerText: s.headerText ? function () {
  2497. return datetime.formatDate(hformat, getDate(inst.getArrayVal(true)), s);
  2498. } : false,
  2499. formatValue: function (d) {
  2500. return datetime.formatDate(format, getDate(d), s);
  2501. },
  2502. parseValue: function (val) {
  2503. if (!val) {
  2504. innerValues = {};
  2505. }
  2506. return getArray(val ? datetime.parseDate(format, val, s) : (s.defaultValue || new Date()), !!val && !!val.getTime);
  2507. },
  2508. validate: function (dw, i, time, dir) {
  2509. var validated = getClosestValidDate(getDate(inst.getArrayVal(true)), dir),
  2510. temp = getArray(validated),
  2511. y = get(temp, 'y'),
  2512. m = get(temp, 'm'),
  2513. minprop = true,
  2514. maxprop = true;
  2515. $.each(['y', 'm', 'd', 'a', 'h', 'i', 's'], function (x, i) {
  2516. if (o[i] !== undefined) {
  2517. var min = mins[i],
  2518. max = maxs[i],
  2519. maxdays = 31,
  2520. val = get(temp, i),
  2521. t = $('.dw-ul', dw).eq(o[i]);
  2522. if (i == 'd') {
  2523. maxdays = s.getMaxDayOfMonth(y, m);
  2524. max = maxdays;
  2525. if (regen) {
  2526. $('.dw-li', t).each(function () {
  2527. var that = $(this),
  2528. d = that.data('val'),
  2529. w = s.getDate(y, m, d).getDay(),
  2530. str = dord.replace(/[my]/gi, '').replace(/dd/, (d < 10 ? '0' + d : d) + (s.daySuffix || '')).replace(/d/, d + (s.daySuffix || ''));
  2531. $('.dw-i', that).html(str.match(/DD/) ? str.replace(/DD/, '<span class="dw-day">' + s.dayNames[w] + '</span>') : str.replace(/D/, '<span class="dw-day">' + s.dayNamesShort[w] + '</span>'));
  2532. });
  2533. }
  2534. }
  2535. if (minprop && mind) {
  2536. min = f[i](mind);
  2537. }
  2538. if (maxprop && maxd) {
  2539. max = f[i](maxd);
  2540. }
  2541. if (i != 'y') {
  2542. var i1 = getIndex(t, min),
  2543. i2 = getIndex(t, max);
  2544. $('.dw-li', t).removeClass('dw-v').slice(i1, i2 + 1).addClass('dw-v');
  2545. if (i == 'd') { // Hide days not in month
  2546. $('.dw-li', t).removeClass('dw-h').slice(maxdays).addClass('dw-h');
  2547. }
  2548. }
  2549. if (val < min) {
  2550. val = min;
  2551. }
  2552. if (val > max) {
  2553. val = max;
  2554. }
  2555. if (minprop) {
  2556. minprop = val == min;
  2557. }
  2558. if (maxprop) {
  2559. maxprop = val == max;
  2560. }
  2561. // Disable some days
  2562. if (i == 'd') {
  2563. var first = s.getDate(y, m, 1).getDay(),
  2564. idx = {};
  2565. // Set invalid indexes
  2566. validateDates(invalid, y, m, first, maxdays, idx, 1);
  2567. // Delete indexes which are valid
  2568. validateDates(valid, y, m, first, maxdays, idx, 0);
  2569. $.each(idx, function (i, v) {
  2570. if (v) {
  2571. $('.dw-li', t).eq(i).removeClass('dw-v');
  2572. }
  2573. });
  2574. }
  2575. }
  2576. });
  2577. // Invalid times
  2578. if (hasTime) {
  2579. $.each(['a', 'h', 'i', 's'], function (i, v) {
  2580. var val = get(temp, v),
  2581. d = get(temp, 'd'),
  2582. t = $('.dw-ul', dw).eq(o[v]);
  2583. if (o[v] !== undefined) {
  2584. validateTimes(invalid, i, v, temp, y, m, d, t, 0);
  2585. validateTimes(valid, i, v, temp, y, m, d, t, 1);
  2586. // Get valid value
  2587. validValues[i] = +inst.getValidCell(val, t, dir).val;
  2588. }
  2589. });
  2590. }
  2591. inst._tempWheelArray = temp;
  2592. }
  2593. };
  2594. };
  2595. $.each(['date', 'time', 'datetime'], function (i, v) {
  2596. ms.presets.scroller[v] = preset;
  2597. });
  2598. })(jQuery);
  2599. //mobiscroll.i18n.zh.js
  2600. (function ($) {
  2601. $.mobiscroll.i18n.zh = $.extend($.mobiscroll.i18n.zh, {
  2602. // Core
  2603. setText: '确定',
  2604. cancelText: '取消',
  2605. clearText: '明确',
  2606. selectedText: '选',
  2607. // Datetime component
  2608. dateFormat: 'yy-mm-dd',
  2609. dateOrder: 'yymmdd',
  2610. dayNames: ['周日', '周一', '周二', '周三', '周四', '周五', '周六'],
  2611. dayNamesShort: ['日', '一', '二', '三', '四', '五', '六'],
  2612. dayNamesMin: ['日', '一', '二', '三', '四', '五', '六'],
  2613. dayText: '日',
  2614. hourText: '时',
  2615. minuteText: '分',
  2616. monthNames: ['1月', '2月', '3月', '4月', '5月', '6月', '7月', '8月', '9月', '10月', '11月', '12月'],
  2617. monthNamesShort: ['一', '二', '三', '四', '五', '六', '七', '八', '九', '十', '十一', '十二'],
  2618. monthText: '月',
  2619. secText: '秒',
  2620. timeFormat: 'HH:ii',
  2621. timeWheels: 'HHii',
  2622. yearText: '年',
  2623. nowText: '当前',
  2624. pmText: '下午',
  2625. amText: '上午',
  2626. // Calendar component
  2627. dateText: '日',
  2628. timeText: '时间',
  2629. calendarText: '日历',
  2630. closeText: '关闭',
  2631. // Daterange component
  2632. fromText: '开始时间',
  2633. toText: '结束时间',
  2634. // Measurement components
  2635. wholeText: '合计',
  2636. fractionText: '分数',
  2637. unitText: '单位',
  2638. // Time / Timespan component
  2639. labels: ['年', '月', '日', '小时', '分钟', '秒', ''],
  2640. labelsShort: ['年', '月', '日', '点', '分', '秒', ''],
  2641. // Timer component
  2642. startText: '开始',
  2643. stopText: '停止',
  2644. resetText: '重置',
  2645. lapText: '圈',
  2646. hideText: '隐藏',
  2647. // Listview
  2648. backText: '背部',
  2649. undoText: '复原'
  2650. });
  2651. })(jQuery);