/*! * mobiscroll v2.14.4 * http://mobiscroll.com * * copyright 2010-2014, acid media * licensed under the mit license. * */ //core (function ($, undefined) { function testprops(props) { var i; for (i in props) { if (mod[props[i]] !== undefined) { return true; } } return false; } function testprefix() { var prefixes = ['webkit', 'moz', 'o', 'ms'], p; for (p in prefixes) { if (testprops([prefixes[p] + 'transform'])) { return '-' + prefixes[p].tolowercase() + '-'; } } return ''; } function init(that, options, args) { var ret = that; // init if (typeof options === 'object') { return that.each(function () { if (!this.id) { this.id = 'mobiscroll' + (++id); } if (instances[this.id]) { instances[this.id].destroy(); } new $.mobiscroll.classes[options.component || 'scroller'](this, options); }); } // method call if (typeof options === 'string') { that.each(function () { var r, inst = instances[this.id]; if (inst && inst[options]) { r = inst[options].apply(this, array.prototype.slice.call(args, 1)); if (r !== undefined) { ret = r; return false; } } }); } return ret; } var id = +new date(), instances = {}, extend = $.extend, mod = document.createelement('modernizr').style, has3d = testprops(['perspectiveproperty', 'webkitperspective', 'mozperspective', 'operspective', 'msperspective']), hasflex = testprops(['flex', 'msflex', 'webkitboxdirection']), prefix = testprefix(), pr = prefix.replace(/^\-/, '').replace(/\-$/, '').replace('moz', 'moz'); $.fn.mobiscroll = function (method) { extend(this, $.mobiscroll.components); return init(this, method, arguments); }; $.mobiscroll = $.mobiscroll || { version: '2.14.4', util: { prefix: prefix, jsprefix: pr, has3d: has3d, hasflex: hasflex, testtouch: function (e, elm) { if (e.type == 'touchstart') { $(elm).attr('data-touch', '1'); } else if ($(elm).attr('data-touch')) { $(elm).removeattr('data-touch'); return false; } return true; }, objecttoarray: function (obj) { var arr = [], i; for (i in obj) { arr.push(obj[i]); } return arr; }, arraytoobject: function (arr) { var obj = {}, i; if (arr) { for (i = 0; i < arr.length; i++) { obj[arr[i]] = arr[i]; } } return obj; }, isnumeric: function (a) { return a - parsefloat(a) >= 0; }, isstring: function (s) { return typeof s === 'string'; }, getcoord: function (e, c) { var ev = e.originalevent || e; return ev.changedtouches ? ev.changedtouches[0]['page' + c] : e['page' + c]; }, getposition: function (t, vertical) { var style = window.getcomputedstyle ? getcomputedstyle(t[0]) : t[0].style, matrix, px; if (has3d) { $.each(['t', 'webkitt', 'mozt', 'ot', 'mst'], function (i, v) { if (style[v + 'ransform'] !== undefined) { matrix = style[v + 'ransform']; return false; } }); matrix = matrix.split(')')[0].split(', '); px = vertical ? (matrix[13] || matrix[5]) : (matrix[12] || matrix[4]); } else { px = vertical ? style.top.replace('px', '') : style.left.replace('px', ''); } return px; }, constrain: function (val, min, max) { return math.max(min, math.min(val, max)); } }, tapped: false, presets: { scroller: {}, numpad: {} }, themes: { listview: {}, menustrip: {} }, i18n: {}, instances: instances, classes: {}, components: {}, defaults: { theme: 'mobiscroll', context: 'body' }, userdef: {}, setdefaults: function (o) { extend(this.userdef, o); }, presetshort: function (name, c, p) { this.components[name] = function (s) { return init(this, extend(s, { component: c, preset: p === false ? undefined : name }), arguments); }; } }; })(jquery); //widget (function ($, window, document, undefined) { var $activeelm, preventshow, extend = $.extend, ms = $.mobiscroll, instances = ms.instances, userdef = ms.userdef, util = ms.util, pr = util.jsprefix, has3d = util.has3d, getcoord = util.getcoord, constrain = util.constrain, isstring = util.isstring, isoldandroid = /android [1-3]/i.test(navigator.useragent), animend = 'webkitanimationend animationend', empty = function () { }, prevdef = function (ev) { ev.preventdefault(); }; ms.classes.widget = function (el, settings, inherit) { var $ariadiv, $ctx, $header, $markup, $overlay, $persp, $popup, $wnd, $wrapper, buttons, btn, doanim, hasbuttons, ismodal, lang, modalwidth, modalheight, posevents, preset, preventpos, s, scrolllock, setreadonly, theme, wasreadonly, wndwidth, wndheight, that = this, $elm = $(el), elmlist = [], posdebounce = {}; function onbtnstart(ev) { // can't call preventdefault here, it kills page scroll if (btn) { btn.removeclass('dwb-a'); } btn = $(this); // active button if (!btn.hasclass('dwb-d') && !btn.hasclass('dwb-nhl')) { btn.addclass('dwb-a'); } if (ev.type === 'mousedown') { $(document).on('mouseup', onbtnend); } } function onbtnend(ev) { if (btn) { btn.removeclass('dwb-a'); btn = null; } if (ev.type === 'mouseup') { $(document).off('mouseup', onbtnend); } } function onwndkeydown(ev) { if (ev.keycode == 13) { that.select(); } else if (ev.keycode == 27) { that.cancel(); } } function onshow(prevfocus) { if (!prevfocus) { $popup.focus(); } that.ariamessage(s.ariamessage); } function onhide(prevanim) { var activeel, value, type, focus = s.focusonclose; $markup.remove(); if ($activeelm && !prevanim) { settimeout(function () { if (focus === undefined || focus === true) { preventshow = true; activeel = $activeelm[0]; type = activeel.type; value = activeel.value; try { activeel.type = 'button'; } catch (ex) { } $activeelm.focus(); activeel.type = type; activeel.value = value; } else if (focus) { // if a mobiscroll field is focused, allow show if (instances[$(focus).attr('id')]) { ms.tapped = false; } $(focus).focus(); } }, 200); } that._isvisible = false; event('onhide', []); } function onposition(ev) { cleartimeout(posdebounce[ev.type]); posdebounce[ev.type] = settimeout(function () { var isscroll = ev.type == 'scroll'; if (isscroll && !scrolllock) { return; } that.position(!isscroll); }, 200); } function show(beforeshow) { if (!ms.tapped) { if (beforeshow) { beforeshow(); } // hide virtual keyboard if ($(document.activeelement).is('input,textarea')) { $(document.activeelement).blur(); } $activeelm = $elm; that.show(); } settimeout(function () { preventshow = false; }, 300); // with jquery < 1.9 focus is fired twice in ie } function event(name, args) { var ret; args.push(that); $.each([userdef, theme, preset, settings], function (i, v) { if (v && v[name]) { // call preset event ret = v[name].apply(el, args); } }); return ret; } /** * positions the scroller on the screen. */ that.position = function (check) { var w, l, t, anchor, aw, // anchor width ah, // anchor height ap, // anchor position at, // anchor top al, // anchor left arr, // arrow arrw, // arrow width arrl, // arrow left dh, scroll, sl, // scroll left st, // scroll top totalw = 0, minw = 0, css = {}, nw = math.min($wnd[0].innerwidth || $wnd.innerwidth(), $persp.width()), //$persp.width(), // to get the width without scrollbar nh = $wnd[0].innerheight || $wnd.innerheight(); if ((wndwidth === nw && wndheight === nh && check) || preventpos) { return; } if (that._isfullscreen || /top|bottom/.test(s.display)) { // set width, if document is larger than viewport, needs to be set before onposition (for calendar) $popup.width(nw); } if (event('onposition', [$markup, nw, nh]) === false || !ismodal) { return; } sl = $wnd.scrollleft(); st = $wnd.scrolltop(); anchor = s.anchor === undefined ? $elm : $(s.anchor); // set / unset liquid layout based on screen width, but only if not set explicitly by the user if (that._isliquid && s.layout !== 'liquid') { if (nw < 400) { $markup.addclass('dw-liq'); } else { $markup.removeclass('dw-liq'); } } if (!that._isfullscreen && /modal|bubble/.test(s.display)) { $wrapper.width(''); $('.mbsc-w-p', $markup).each(function () { w = $(this).outerwidth(true); totalw += w; minw = (w > minw) ? w : minw; }); w = totalw > nw ? minw : totalw; $wrapper.width(w).css('white-space', totalw > nw ? '' : 'nowrap'); } modalwidth = that._isfullscreen ? nw : $popup.outerwidth(); modalheight = that._isfullscreen ? nh : $popup.outerheight(true); scrolllock = modalheight <= nh && modalwidth <= nw; that.scrolllock = scrolllock; if (s.display == 'modal') { l = math.max(0, sl + (nw - modalwidth) / 2); t = st + (nh - modalheight) / 2; } else if (s.display == 'bubble') { scroll = true; arr = $('.dw-arrw-i', $markup); ap = anchor.offset(); at = math.abs($ctx.offset().top - ap.top); al = math.abs($ctx.offset().left - ap.left); // horizontal positioning aw = anchor.outerwidth(); ah = anchor.outerheight(); l = constrain(al - ($popup.outerwidth(true) - aw) / 2, sl + 3, sl + nw - modalwidth - 3); // vertical positioning t = at - modalheight; // above the input if ((t < st) || (at > st + nh)) { // if doesn't fit above or the input is out of the screen $popup.removeclass('dw-bubble-top').addclass('dw-bubble-bottom'); t = at + ah; // below the input } else { $popup.removeclass('dw-bubble-bottom').addclass('dw-bubble-top'); } // calculate arrow position arrw = arr.outerwidth(); arrl = constrain(al + aw / 2 - (l + (modalwidth - arrw) / 2), 0, arrw); // limit arrow position $('.dw-arr', $markup).css({ left: arrl }); } else { l = sl; if (s.display == 'top') { t = st; } else if (s.display == 'bottom') { t = st + nh - modalheight; } } t = t < 0 ? 0 : t; css.top = t; css.left = l; $popup.css(css); // if top + modal height > doc height, increase doc height $persp.height(0); dh = math.max(t + modalheight, s.context == 'body' ? $(document).height() : $ctx[0].scrollheight); $persp.css({ height: dh }); // scroll needed if (scroll && ((t + modalheight > st + nh) || (at > st + nh))) { preventpos = true; settimeout(function () { preventpos = false; }, 300); $wnd.scrolltop(math.min(t + modalheight - nh, dh - nh)); } wndwidth = nw; wndheight = nh; }; /** * show mobiscroll on focus and click event of the parameter. * @param {jquery} $elm - events will be attached to this element. * @param {function} [beforeshow=undefined] - optional function to execute before showing mobiscroll. */ that.attachshow = function ($elm, beforeshow) { elmlist.push($elm); if (s.display !== 'inline') { if (setreadonly) { $elm.on('mousedown.dw', function (ev) { // prevent input to get focus on tap (virtual keyboard pops up on some devices) ev.preventdefault(); }); } if (s.showonfocus) { $elm.on('focus.dw', function () { if (!preventshow) { show(beforeshow); } }); } if (s.showontap) { that.tap($elm, function () { show(beforeshow); }); } } }; /** * set button handler. */ that.select = function () { if (!ismodal || that.hide(false, 'set') !== false) { that._fillvalue(); event('onselect', [that._value]); } }; /** * cancel and hide the scroller instance. */ that.cancel = function () { if (!ismodal || that.hide(false, 'cancel') !== false) { event('oncancel', [that._value]); } }; /** * clear button handler. */ that.clear = function () { event('onclear', [$markup]); if (ismodal && !that.live) { that.hide(false, 'clear'); } that.setvalue(null, true); }; /** * enables the scroller and the associated input. */ that.enable = function () { s.disabled = false; if (that._isinput) { $elm.prop('disabled', false); } }; /** * disables the scroller and the associated input. */ that.disable = function () { s.disabled = true; if (that._isinput) { $elm.prop('disabled', true); } }; /** * shows the scroller instance. * @param {boolean} prevanim - prevent animation if true * @param {boolean} prevfocus - prevent focusing if true */ that.show = function (prevanim, prevfocus) { // create wheels var html; if (s.disabled || that._isvisible) { return; } if (doanim !== false) { if (s.display == 'top') { doanim = 'slidedown'; } if (s.display == 'bottom') { doanim = 'slideup'; } } // parse value from input that._readvalue(); event('onbeforeshow', []); // create wheels containers html = '
' + '
' + (ismodal ? '
' : '') + // overlay '' + // popup (s.display === 'bubble' ? '
' : '') + // bubble arrow '
' + // popup content '
' + (s.headertext ? '
' + (isstring(s.headertext) ? s.headertext : '') + '
' : '') + // header '
'; // wheel group container html += that._generatecontent(); html += '
'; if (hasbuttons) { html += '
'; $.each(buttons, function (i, b) { b = isstring(b) ? that.buttons[b] : b; if (b.handler === 'set') { b.parentclass = 'dwb-s'; } if (b.handler === 'cancel') { b.parentclass = 'dwb-c'; } b.handler = isstring(b.handler) ? that.handlers[b.handler] : b.handler; html += '
' + (b.text || '') + '
'; }); html += '
'; } html += '
'; $markup = $(html); $persp = $('.dw-persp', $markup); $overlay = $('.dwo', $markup); $wrapper = $('.dwwr', $markup); $header = $('.dwv', $markup); $popup = $('.dw', $markup); $ariadiv = $('.dw-aria', $markup); that._markup = $markup; that._header = $header; that._isvisible = true; posevents = 'orientationchange resize'; that._markupready(); event('onmarkupready', [$markup]); // show if (ismodal) { // enter / esc $(window).on('keydown', onwndkeydown); // prevent scroll if not specified otherwise if (s.scrolllock) { $markup.on('touchmove mousewheel dommousescroll', function (ev) { if (scrolllock) { ev.preventdefault(); } }); } // disable inputs to prevent bleed through (android bug) if (pr !== 'moz') { $('input,select,button', $ctx).each(function () { if (!this.disabled) { $(this).addclass('dwtd').prop('disabled', true); } }); } posevents += ' scroll'; ms.activeinstance = that; $markup.appendto($ctx); if (has3d && doanim && !prevanim) { $markup.addclass('dw-in dw-trans').on(animend, function () { $markup.off(animend).removeclass('dw-in dw-trans').find('.dw').removeclass('dw-' + doanim); onshow(prevfocus); }).find('.dw').addclass('dw-' + doanim); } } else if ($elm.is('div')) { $elm.html($markup); } else { $markup.insertafter($elm); } event('onmarkupinserted', [$markup]); // set position that.position(); $wnd.on(posevents, onposition); // events $markup .on('selectstart mousedown', prevdef) // prevents blue highlight on android and text selection in ie .on('click', '.dwb-e', prevdef) .on('keydown', '.dwb-e', function (ev) { if (ev.keycode == 32) { // space ev.preventdefault(); ev.stoppropagation(); $(this).click(); } }); settimeout(function () { // init buttons $.each(buttons, function (i, b) { that.tap($('.dwb' + i, $markup), function (ev) { b = isstring(b) ? that.buttons[b] : b; b.handler.call(this, ev, that); }, true); }); if (s.closeonoverlay) { that.tap($overlay, function () { that.cancel(); }); } if (ismodal && !doanim) { onshow(prevfocus); } $markup .on('touchstart mousedown', '.dwb-e', onbtnstart) .on('touchend', '.dwb-e', onbtnend); that._attachevents($markup); }, 300); event('onshow', [$markup, that._tempvalue]); }; /** * hides the scroller instance. */ that.hide = function (prevanim, btn, force) { // if onclose handler returns false, prevent hide if (!that._isvisible || (!force && !that._isvalid && btn == 'set') || (!force && event('onclose', [that._tempvalue, btn]) === false)) { return false; } // hide wheels and overlay if ($markup) { // re-enable temporary disabled fields if (pr !== 'moz') { $('.dwtd', $ctx).each(function () { $(this).prop('disabled', false).removeclass('dwtd'); }); } if (has3d && ismodal && doanim && !prevanim && !$markup.hasclass('dw-trans')) { // if dw-trans class was not removed, means that there was no animation $markup.addclass('dw-out dw-trans').find('.dw').addclass('dw-' + doanim).on(animend, function () { onhide(prevanim); }); } else { onhide(prevanim); } // stop positioning on window resize $wnd.off(posevents, onposition); } if (ismodal) { $(window).off('keydown', onwndkeydown); delete ms.activeinstance; } }; that.ariamessage = function (txt) { $ariadiv.html(''); settimeout(function () { $ariadiv.html(txt); }, 100); }; /** * return true if the scroller is currently visible. */ that.isvisible = function () { return that._isvisible; }; // protected functions to override that.setvalue = empty; that._generatecontent = empty; that._attachevents = empty; that._readvalue = empty; that._fillvalue = empty; that._markupready = empty; that._processsettings = empty; // generic widget functions /** * attach tap event to the given element. */ that.tap = function (el, handler, prevent) { var startx, starty, moved; if (s.tap) { el.on('touchstart.dw', function (ev) { // can't always call preventdefault here, it kills page scroll if (prevent) { ev.preventdefault(); } startx = getcoord(ev, 'x'); starty = getcoord(ev, 'y'); moved = false; }).on('touchmove.dw', function (ev) { // if movement is more than 20px, don't fire the click event handler if (math.abs(getcoord(ev, 'x') - startx) > 20 || math.abs(getcoord(ev, 'y') - starty) > 20) { moved = true; } }).on('touchend.dw', function (ev) { var that = this; if (!moved) { // preventdefault and settimeout are needed by ios ev.preventdefault(); //settimeout(function () { handler.call(that, ev); //}, isoldandroid ? 400 : 10); } // prevent click events to happen ms.tapped = true; settimeout(function () { ms.tapped = false; }, 500); }); } el.on('click.dw', function (ev) { if (!ms.tapped) { // if handler was not called on touchend, call it on click; handler.call(this, ev); } ev.preventdefault(); }); }; /** * sets one ore more options. */ that.option = function (opt, value) { var obj = {}; if (typeof opt === 'object') { obj = opt; } else { obj[opt] = value; } that.init(obj); }; /** * destroys the mobiscroll instance. */ that.destroy = function () { // force hide without animation that.hide(true, false, true); // remove all events from elements $.each(elmlist, function (i, v) { v.off('.dw'); }); // reset original readonly state if (that._isinput && setreadonly) { el.readonly = wasreadonly; } event('ondestroy', []); // delete scroller instance delete instances[el.id]; that = null; }; /** * returns the mobiscroll instance. */ that.getinst = function () { return that; }; /** * triggers a mobiscroll event. */ that.trigger = event; /** * scroller initialization. */ that.init = function (ss) { that.settings = s = {}; // update original user settings extend(settings, ss); extend(s, ms.defaults, that._defaults, userdef, settings); // get theme defaults theme = ms.themes[s.theme] || ms.themes.mobiscroll; // get language defaults lang = ms.i18n[s.lang]; event('onthemeload', [lang, settings]); extend(s, theme, lang, userdef, settings); preset = ms.presets[that._class][s.preset]; // add default buttons s.buttons = s.buttons || (s.display !== 'inline' ? ['set', 'cancel'] : []); // hide header text in inline mode by default s.headertext = s.headertext === undefined ? (s.display !== 'inline' ? '{value}' : false) : s.headertext; if (preset) { preset = preset.call(el, that); extend(s, preset, settings); // load preset settings } if (!ms.themes[s.theme]) { s.theme = 'mobiscroll'; } that._isliquid = (s.layout || (/top|bottom/.test(s.display) ? 'liquid' : '')) === 'liquid'; that._processsettings(); // unbind all events (if re-init) $elm.off('.dw'); doanim = isoldandroid ? false : s.animate; buttons = s.buttons; ismodal = s.display !== 'inline'; setreadonly = s.showonfocus || s.showontap; $wnd = $(s.context == 'body' ? window : s.context); $ctx = $(s.context); that.context = $wnd; that.live = true; // if no set button is found, live mode is activated $.each(buttons, function (i, b) { if (b === 'set' || b.handler === 'set') { that.live = false; return false; } }); that.buttons.set = { text: s.settext, handler: 'set' }; that.buttons.cancel = { text: (that.live) ? s.closetext : s.canceltext, handler: 'cancel' }; that.buttons.clear = { text: s.cleartext, handler: 'clear' }; that._isinput = $elm.is('input'); hasbuttons = buttons.length > 0; if (that._isvisible) { that.hide(true, false, true); } if (ismodal) { that._readvalue(); if (that._isinput && setreadonly) { // set element readonly, save original state if (wasreadonly === undefined) { wasreadonly = el.readonly; } el.readonly = true; } that.attachshow($elm); } else { that.show(); } //if (that._isinput) { $elm.on('change.dw', function () { if (!that._preventchange) { that.setval($elm.val(), true, false); } that._preventchange = false; }); //} event('oninit', []); }; that.buttons = {}; that.handlers = { set: that.select, cancel: that.cancel, clear: that.clear }; that._value = null; that._isvalid = true; that._isvisible = false; // constructor if (!inherit) { instances[el.id] = that; that.init(settings); } }; ms.classes.widget.prototype._defaults = { // localization lang: 'en', settext: 'set', selectedtext: 'selected', closetext: 'close', canceltext: 'cancel', cleartext: 'clear', // options disabled: false, closeonoverlay: true, showonfocus: true, showontap: true, display: 'modal', scrolllock: true, tap: true, btnclass: 'dwb', btnwidth: true, focusonclose: false // temporary for ios8 }; ms.themes.mobiscroll = { rows: 5, showlabel: false, headertext: false, btnwidth: false, selectedlineheight: true, selectedlineborder: 1, dateorder: 'mmddyy', weekdays: 'min', checkicon: 'ion-ios7-checkmark-empty', btnplusclass: 'mbsc-ic mbsc-ic-arrow-down5', btnminusclass: 'mbsc-ic mbsc-ic-arrow-up5', btncalprevclass: 'mbsc-ic mbsc-ic-arrow-left5', btncalnextclass: 'mbsc-ic mbsc-ic-arrow-right5' }; // prevent re-show on window focus $(window).on('focus', function () { if ($activeelm) { preventshow = true; } }); // prevent standard behaviour on body click $(document).on('mouseover mouseup mousedown click', function (ev) { if (ms.tapped) { ev.stoppropagation(); ev.preventdefault(); return false; } }); })(jquery, window, document); //scroller (function ($, window, document, undefined) { var move, ms = $.mobiscroll, classes = ms.classes, instances = ms.instances, util = ms.util, pr = util.jsprefix, has3d = util.has3d, hasflex = util.hasflex, getcoord = util.getcoord, constrain = util.constrain, testtouch = util.testtouch; classes.scroller = function (el, settings, inherit) { var $markup, btn, isscrollable, itemheight, s, trigger, click, moved, start, starttime, stop, p, min, max, target, index, lines, timer, that = this, $elm = $(el), iv = {}, pos = {}, pixels = {}, wheels = []; // event handlers function onstart(ev) { // scroll start if (testtouch(ev, this) && !move && !click && !btn && !isreadonly(this)) { // prevent touch highlight ev.preventdefault(); // better performance if there are tap events on document ev.stoppropagation(); move = true; isscrollable = s.mode != 'clickpick'; target = $('.dw-ul', this); setglobals(target); moved = iv[index] !== undefined; // don't allow tap, if still moving p = moved ? getcurrentposition(target) : pos[index]; start = getcoord(ev, 'y'); starttime = new date(); stop = start; scroll(target, index, p, 0.001); if (isscrollable) { target.closest('.dwwl').addclass('dwa'); } if (ev.type === 'mousedown') { $(document).on('mousemove', onmove).on('mouseup', onend); } } } function onmove(ev) { if (move) { if (isscrollable) { // prevent scroll ev.preventdefault(); ev.stoppropagation(); stop = getcoord(ev, 'y'); if (math.abs(stop - start) > 3 || moved) { scroll(target, index, constrain(p + (start - stop) / itemheight, min - 1, max + 1)); moved = true; } } } } function onend(ev) { if (move) { var time = new date() - starttime, val = constrain(p + (start - stop) / itemheight, min - 1, max + 1), speed, dist, tindex, ttop = target.offset().top; // better performance if there are tap events on document ev.stoppropagation(); if (has3d && time < 300) { speed = (stop - start) / time; dist = (speed * speed) / s.speedunit; if (stop - start < 0) { dist = -dist; } } else { dist = stop - start; } tindex = math.round(p - dist / itemheight); if (!moved) { // this is a "tap" var idx = math.floor((stop - ttop) / itemheight), li = $($('.dw-li', target)[idx]), valid = li.hasclass('dw-v'), hl = isscrollable; if (trigger('onvaluetap', [li]) !== false && valid) { tindex = idx; } else { hl = true; } if (hl && valid) { li.addclass('dw-hl'); // highlight settimeout(function () { li.removeclass('dw-hl'); }, 100); } } if (isscrollable) { calc(target, tindex, 0, true, math.round(val)); } if (ev.type === 'mouseup') { $(document).off('mousemove', onmove).off('mouseup', onend); } move = false; } } function onbtnstart(ev) { btn = $(this); // +/- buttons if (testtouch(ev, this)) { step(ev, btn.closest('.dwwl'), btn.hasclass('dwwbp') ? plus : minus); } if (ev.type === 'mousedown') { $(document).on('mouseup', onbtnend); } } function onbtnend(ev) { btn = null; if (click) { clearinterval(timer); click = false; } if (ev.type === 'mouseup') { $(document).off('mouseup', onbtnend); } } function onkeydown(ev) { if (ev.keycode == 38) { // up step(ev, $(this), minus); } else if (ev.keycode == 40) { // down step(ev, $(this), plus); } } function onkeyup() { if (click) { clearinterval(timer); click = false; } } function onscroll(ev) { if (!isreadonly(this)) { ev.preventdefault(); ev = ev.originalevent || ev; var delta = ev.wheeldelta ? (ev.wheeldelta / 120) : (ev.detail ? (-ev.detail / 3) : 0), t = $('.dw-ul', this); setglobals(t); calc(t, math.round(pos[index] - delta), delta < 0 ? 1 : 2); } } // private functions function step(ev, w, func) { ev.stoppropagation(); ev.preventdefault(); if (!click && !isreadonly(w) && !w.hasclass('dwa')) { click = true; // + button var t = w.find('.dw-ul'); setglobals(t); clearinterval(timer); timer = setinterval(function () { func(t); }, s.delay); func(t); } } function isreadonly(wh) { if ($.isarray(s.readonly)) { var i = $('.dwwl', $markup).index(wh); return s.readonly[i]; } return s.readonly; } function generatewheelitems(i) { var html = '
', w = wheels[i], l = 1, labels = w.labels || [], values = w.values, keys = w.keys || values; $.each(values, function (j, v) { if (l % 20 === 0) { html += '
'; } html += '
' + '
1 ? ' style="line-height:' + math.round(itemheight / lines) + 'px;font-size:' + math.round(itemheight / lines * 0.8) + 'px;"' : '') + '>' + v + '
'; l++; }); html += '
'; return html; } function setglobals(t) { var multiple = t.closest('.dwwl').hasclass('dwwms'); min = $('.dw-li', t).index($(multiple ? '.dw-li' : '.dw-v', t).eq(0)); max = math.max(min, $('.dw-li', t).index($(multiple ? '.dw-li' : '.dw-v', t).eq(-1)) - (multiple ? s.rows - 1 : 0)); index = $('.dw-ul', $markup).index(t); } function formatheader(v) { var t = s.headertext; return t ? (typeof t === 'function' ? t.call(el, v) : t.replace(/\{value\}/i, v)) : ''; } function getcurrentposition(t) { return math.round(-util.getposition(t, true) / itemheight); } function ready(t, i) { cleartimeout(iv[i]); delete iv[i]; t.closest('.dwwl').removeclass('dwa'); } function scroll(t, index, val, time, active) { var px = -val * itemheight, style = t[0].style; if (px == pixels[index] && iv[index]) { return; } //if (time && px != pixels[index]) { // trigger animation start event //trigger('onanimstart', [$markup, index, time]); //} pixels[index] = px; if (has3d) { style[pr + 'transition'] = util.prefix + 'transform ' + (time ? time.tofixed(3) : 0) + 's ease-out'; style[pr + 'transform'] = 'translate3d(0,' + px + 'px,0)'; } else { style.top = px + 'px'; } if (iv[index]) { ready(t, index); } if (time && active) { t.closest('.dwwl').addclass('dwa'); iv[index] = settimeout(function () { ready(t, index); }, time * 1000); } pos[index] = val; } function getvalid(val, t, dir, multiple) { var cell = $('.dw-li[data-val="' + val + '"]', t), cells = $('.dw-li', t), v = cells.index(cell), l = cells.length; if (multiple) { setglobals(t); } else if (!cell.hasclass('dw-v')) { // scroll to a valid cell var cell1 = cell, cell2 = cell, dist1 = 0, dist2 = 0; while (v - dist1 >= 0 && !cell1.hasclass('dw-v')) { dist1++; cell1 = cells.eq(v - dist1); } while (v + dist2 < l && !cell2.hasclass('dw-v')) { dist2++; cell2 = cells.eq(v + dist2); } // if we have direction (+/- or mouse wheel), the distance does not count if (((dist2 < dist1 && dist2 && dir !== 2) || !dist1 || (v - dist1 < 0) || dir == 1) && cell2.hasclass('dw-v')) { cell = cell2; v = v + dist2; } else { cell = cell1; v = v - dist1; } } return { cell: cell, v: multiple ? constrain(v, min, max) : v, val: cell.hasclass('dw-v') ? cell.attr('data-val') : null }; } function scrolltopos(time, index, manual, dir, active) { // call validation event if (trigger('validate', [$markup, index, time, dir]) !== false) { // set scrollers to position $('.dw-ul', $markup).each(function (i) { var t = $(this), multiple = t.closest('.dwwl').hasclass('dwwms'), sc = i == index || index === undefined, res = getvalid(that._tempwheelarray[i], t, dir, multiple), cell = res.cell; if (!(cell.hasclass('dw-sel')) || sc) { // set valid value that._tempwheelarray[i] = res.val; if (!multiple) { $('.dw-sel', t).removeattr('aria-selected'); cell.attr('aria-selected', 'true'); } // add selected class to cell $('.dw-sel', t).removeclass('dw-sel'); cell.addclass('dw-sel'); // scroll to position scroll(t, i, res.v, sc ? time : 0.1, sc ? active : false); } }); trigger('onvalidated', []); // reformat value if validation changed something that._tempvalue = s.formatresult(that._tempwheelarray); if (that.live) { that._hasvalue = manual || that._hasvalue; setvalue(manual, manual, 0, true); } that._header.html(formatheader(that._tempvalue)); if (manual) { trigger('onchange', [that._tempvalue]); } } } function calc(t, val, dir, anim, orig) { val = constrain(val, min, max); var cell = $('.dw-li', t).eq(val), o = orig === undefined ? val : orig, active = orig !== undefined, idx = index, dist = math.abs(val - o), time = anim ? (val == o ? 0.1 : dist * s.timeunit * math.max(0.5, (100 - dist) / 100)) : 0; // set selected scroller value that._tempwheelarray[idx] = cell.attr('data-val'); scroll(t, idx, val, time, active); settimeout(function () { // validate scrolltopos(time, idx, true, dir, active); }, 10); } function plus(t) { var val = pos[index] + 1; calc(t, val > max ? min : val, 1, true); } function minus(t) { var val = pos[index] - 1; calc(t, val < min ? max : val, 2, true); } function setvalue(fill, change, time, noscroll, temp) { if (that._isvisible && !noscroll) { scrolltopos(time); } that._tempvalue = s.formatresult(that._tempwheelarray); if (!temp) { that._wheelarray = that._tempwheelarray.slice(0); that._value = that._hasvalue ? that._tempvalue : null; } if (fill) { trigger('onvaluefill', [that._hasvalue ? that._tempvalue : '', change]); if (that._isinput) { $elm.val(that._hasvalue ? that._tempvalue : ''); } if (change) { that._preventchange = true; $elm.change(); } } } // call the parent constructor classes.widget.call(this, el, settings, true); // public functions /** * gets the selected wheel values, formats it, and set the value of the scroller instance. * if input parameter is true, populates the associated input element. * @param {array} values wheel values. * @param {boolean} [fill=false] also set the value of the associated input element. * @param {number} [time=0] animation time * @param {boolean} [temp=false] if true, then only set the temporary value.(only scroll there but not set the value) * @param {boolean} [change=false] trigger change on the input element */ that.setval = that._setval = function (val, fill, change, temp, time) { that._hasvalue = val !== null && val !== undefined; that._tempwheelarray = $.isarray(val) ? val.slice(0) : s.parsevalue.call(el, val, that) || []; setvalue(fill, change === undefined ? fill : change, time, false, temp); }; /** * returns the selected value */ that.getval = that._getval = function (temp) { var val = that._hasvalue ? that[temp ? '_tempvalue' : '_value'] : null; return util.isnumeric(val) ? +val : val; }; /* * sets the wheel values (passed as an array) */ that.setarrayval = that.setval; /* * returns the selected wheel values as an array */ that.getarrayval = function (temp) { return temp ? that._tempwheelarray : that._wheelarray; }; // @deprecated since 2.14.0, backward compatibility code // --- that.setvalue = function (val, fill, time, temp, change) { that.setval(val, fill, change, temp, time); }; /** * return the selected wheel values. */ that.getvalue = that.getarrayval; // --- /** * changes the values of a wheel, and scrolls to the correct position * @param {array} idx indexes of the wheels to change. * @param {number} [time=0] animation time when scrolling to the selected value on the new wheel. * @param {boolean} [manual=false] indicates that the change was triggered by the user or from code. */ that.changewheel = function (idx, time, manual) { if ($markup) { var i = 0, nr = idx.length; $.each(s.wheels, function (j, wg) { $.each(wg, function (k, w) { if ($.inarray(i, idx) > -1) { wheels[i] = w; $('.dw-ul', $markup).eq(i).html(generatewheelitems(i)); nr--; if (!nr) { that.position(); scrolltopos(time, undefined, manual); return false; } } i++; }); if (!nr) { return false; } }); } }; /** * returns the closest valid cell. */ that.getvalidcell = getvalid; // protected overrides that._generatecontent = function () { var lbl, html = '', l = 0; $.each(s.wheels, function (i, wg) { // wheel groups html += '
' + '
' + (hasflex ? '' : ''); $.each(wg, function (j, w) { // wheels wheels[l] = w; lbl = w.label !== undefined ? w.label : j; html += '<' + (hasflex ? 'div' : 'td') + ' class="dwfl"' + ' style="' + (s.fixedwidth ? ('width:' + (s.fixedwidth[l] || s.fixedwidth) + 'px;') : (s.minwidth ? ('min-width:' + (s.minwidth[l] || s.minwidth) + 'px;') : 'min-width:' + s.width + 'px;') + (s.maxwidth ? ('max-width:' + (s.maxwidth[l] || s.maxwidth) + 'px;') : '')) + '">' + '
' + (s.mode != 'scroller' ? '
+
' + // + button '
' : '') + // - button '
' + lbl + '
' + // wheel label '
' + '
' + '
'; // create wheel values html += generatewheelitems(l) + '
' + (hasflex ? '' : ''); l++; }); html += (hasflex ? '' : '
') + '
'; }); return html; }; that._attachevents = function ($markup) { $markup .on('dommousescroll mousewheel', '.dwwl', onscroll) .on('keydown', '.dwwl', onkeydown) .on('keyup', '.dwwl', onkeyup) .on('touchstart mousedown', '.dwwl', onstart) .on('touchmove', '.dwwl', onmove) .on('touchend', '.dwwl', onend) .on('touchstart mousedown', '.dwwb', onbtnstart) .on('touchend', '.dwwb', onbtnend); }; that._markupready = function () { $markup = that._markup; scrolltopos(); }; that._fillvalue = function () { that._hasvalue = true; setvalue(true, true, 0, true); }; that._readvalue = function () { var v = $elm.val() || ''; that._hasvalue = v !== ''; that._tempwheelarray = that._wheelarray ? that._wheelarray.slice(0) : s.parsevalue(v, that) || []; setvalue(); }; that._processsettings = function () { s = that.settings; trigger = that.trigger; itemheight = s.height; lines = s.multiline; that._isliquid = (s.layout || (/top|bottom/.test(s.display) && s.wheels.length == 1 ? 'liquid' : '')) === 'liquid'; //that._wheelarray = null; //that._tempwheelarray = null; if (lines > 1) { s.cssclass = (s.cssclass || '') + ' dw-ml'; } }; // properties that._selectedvalues = {}; // constructor if (!inherit) { instances[el.id] = that; that.init(settings); } }; // extend defaults classes.scroller.prototype._class = 'scroller'; classes.scroller.prototype._defaults = $.extend({}, classes.widget.prototype._defaults, { // options minwidth: 80, height: 40, rows: 3, multiline: 1, delay: 300, readonly: false, showlabel: true, wheels: [], mode: 'scroller', preset: '', speedunit: 0.0012, timeunit: 0.08, formatresult: function (d) { return d.join(' '); }, parsevalue: function (value, inst) { var val = [], ret = [], i = 0, keys; if (value !== null && value !== undefined) { val = (value + '').split(' '); } $.each(inst.settings.wheels, function (j, wg) { $.each(wg, function (k, w) { keys = w.keys || w.values; if ($.inarray(val[i], keys) !== -1) { ret.push(val[i]); } else { ret.push(keys[0]); } i++; }); }); return ret; } }); })(jquery, window, document);