UNPKG

meetyou-gulp

Version:

This is a gulp task collection for MeetYou.

1,434 lines (1,265 loc) 67.7 kB
/*jslint eqeq: true, plusplus: true, undef: true, sloppy: true, vars: true, forin: true */ /*! * jQuery MobiScroll v2.5.1 * http://mobiscroll.com * * Copyright 2010-2013, Acid Media * Licensed under the MIT license. * */ (function($) { function Scroller(elem, settings) { var m, hi, v, dw, ww, // Window width wh, // Window height rwh, mw, // Modal width mh, // Modal height anim, debounce, that = this, ms = $.mobiscroll, e = elem, elm = $(e), theme, lang, s = extend({}, defaults), pres = {}, warr = [], iv = {}, pixels = {}, input = elm.is('input'), visible = false; // Private functions function isReadOnly(wh) { if ($.isArray(s.readonly)) { var i = $('.dwwl', dw).index(wh); return s.readonly[i]; } return s.readonly; } function generateWheelItems(i) { var html = '<div class="dw-bf">', l = 1, j; for (j in warr[i]) { if (l % 20 == 0) { html += '</div><div class="dw-bf">'; } html += '<div class="dw-li dw-v" data-val="' + j + '" style="height:' + hi + 'px;line-height:' + hi + 'px;"><div class="dw-i">' + warr[i][j] + '</div></div>'; l++; } html += '</div>'; return html; } function setGlobals(t) { min = $('.dw-li', t).index($('.dw-v', t).eq(0)); max = $('.dw-li', t).index($('.dw-v', t).eq(-1)); index = $('.dw-ul', dw).index(t); h = hi; inst = that; } function read() { that.temp = ((input && that.val !== null && that.val != elm.val()) || that.values === null) ? s.parseValue(elm.val() || '', that) : that.values.slice(0); that.setValue(true); } function scrollToPos(time, index, manual, dir, orig) { // Call validation event if (event('validate', [dw, index, time]) !== false) { // Set scrollers to position $('.dw-ul', dw).each(function(i) { var t = $(this), cell = $('.dw-li[data-val="' + that.temp[i] + '"]', t), cells = $('.dw-li', t), v = cells.index(cell), l = cells.length, sc = i == index || index === undefined; // Scroll to a valid cell if (!cell.hasClass('dw-v')) { 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; } } if (!(cell.hasClass('dw-sel')) || sc) { // Set valid value that.temp[i] = cell.attr('data-val'); // Add selected class to cell $('.dw-sel', t).removeClass('dw-sel'); cell.addClass('dw-sel'); // Scroll to position //that.scroll(t, i, v, time); that.scroll(t, i, v, sc ? time : 0.1, sc ? orig : undefined); } }); // Reformat value if validation changed something that.change(manual); } } function position(check) { if (s.display == 'inline' || (ww === $(window).width() && rwh === $(window).height() && check)) { return; } var w, l, t, aw, // anchor width ah, // anchor height ap, // anchor position at, // anchor top al, // anchor left arr, // arrow arrw, // arrow width arrl, // arrow left scroll, totalw = 0, minw = 0, st = $(window).scrollTop(), wr = $('.dwwr', dw), d = $('.dw', dw), css = {}, anchor = s.anchor === undefined ? elm : s.anchor; ww = $(window).width(); rwh = $(window).height(); wh = window.innerHeight; // on iOS we need innerHeight wh = wh || rwh; if (/modal|bubble/.test(s.display)) { /* $('.dwc', dw).each(function () { w = $(this).outerWidth(true); totalw += w; minw = (w > minw) ? w : minw; }); w = totalw > ww ? minw : totalw; wr.width(w);*/ wr.width(100 + '%'); } mw = d.outerWidth(); mh = d.outerHeight(true); if (s.display == 'modal') { l = 0; t = 0; //l = (ww - mw) / 2; //t = st + (wh - mh) / 2; } else if (s.display == 'bubble') { scroll = true; arr = $('.dw-arrw-i', dw); ap = anchor.offset(); at = ap.top; al = ap.left; // horizontal positioning aw = anchor.outerWidth(); ah = anchor.outerHeight(); l = al - (d.outerWidth(true) - aw) / 2; l = l > (ww - mw) ? (ww - (mw + 20)) : l; l = l >= 0 ? l : 20; // vertical positioning t = at - mh; //(mh + 3); // above the input if ((t < st) || (at > st + wh)) { // if doesn't fit above or the input is out of the screen d.removeClass('dw-bubble-top').addClass('dw-bubble-bottom'); t = at + ah; // + 3; // below the input } else { d.removeClass('dw-bubble-bottom').addClass('dw-bubble-top'); } //t = t >= st ? t : st; // Calculate Arrow position arrw = arr.outerWidth(); arrl = al + aw / 2 - (l + (mw - arrw) / 2); // Limit Arrow position to [0, pocw.width] intervall $('.dw-arr', dw).css({ left: arrl > arrw ? arrw : arrl }); } else { css.width = '100%'; if (s.display == 'top') { t = st; } else if (s.display == 'bottom') { t = st + wh - mh; } } css.bottom = t < 0 ? 0 : t; css.left = l; d.css(css); // If top + modal height > doc height, increase doc height $('.dw-persp', dw).height(0).height(t + mh > $(document).height() ? t + mh : $(document).height()); // Scroll needed if (scroll && ((t + mh > st + wh) || (at > st + wh))) { $(window).scrollTop(t + mh - wh); } } function testTouch(e) { if (e.type === 'touchstart') { touch = true; setTimeout(function() { touch = false; // Reset if mouse event was not fired }, 500); } else if (touch) { touch = false; return false; } return true; } function event(name, args) { var ret; args.push(that); $.each([theme.defaults, pres, settings], function(i, v) { if (v[name]) { // Call preset event ret = v[name].apply(e, args); } }); return ret; } function plus(t) { var p = +t.data('pos'), val = p + 1; calc(t, val > max ? min : val, 1, true); } function minus(t) { var p = +t.data('pos'), val = p - 1; calc(t, val < min ? max : val, 2, true); } // Public functions /** * Enables the scroller and the associated input. */ that.enable = function() { s.disabled = false; if (input) { elm.prop('disabled', false); } }; /** * Disables the scroller and the associated input. */ that.disable = function() { s.disabled = true; if (input) { elm.prop('disabled', true); } }; /** * Scrolls target to the specified position * @param {Object} t - Target wheel jQuery object. * @param {Number} index - Index of the changed wheel. * @param {Number} val - Value. * @param {Number} time - Duration of the animation, optional. * @param {Number} orig - Original value. */ that.scroll = function(t, index, val, time, orig) { function getVal(t, b, c, d) { return c * Math.sin(t / d * (Math.PI / 2)) + b; } function ready() { clearInterval(iv[index]); delete iv[index]; t.data('pos', val).closest('.dwwl').removeClass('dwa'); } var px = (m - val) * hi, i; if (px == pixels[index] && iv[index]) { return; } if (time && px != pixels[index]) { // Trigger animation start event event('onAnimStart', [dw, index, time]); } pixels[index] = px; t.attr('style', (prefix + '-transition:all ' + (time ? time.toFixed(3) : 0) + 's ease-out;') + (has3d ? (prefix + '-transform:translate3d(0,' + px + 'px,0);') : ('top:' + px + 'px;'))); if (iv[index]) { ready(); } if (time && orig !== undefined) { i = 0; t.closest('.dwwl').addClass('dwa'); iv[index] = setInterval(function() { i += 0.1; t.data('pos', Math.round(getVal(i, orig, val - orig, time))); if (i >= time) { ready(); } }, 100); } else { t.data('pos', val); } }; /** * 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 {Boolean} sc - Scroll the wheel in position. * @param {Boolean} fill - Also set the value of the associated input element. Default is true. * @param {Number} time - Animation time * @param {Boolean} temp - If true, then only set the temporary value.(only scroll there but not set the value) */ that.setValue = function(sc, fill, time, temp) { if (!$.isArray(that.temp)) { that.temp = s.parseValue(that.temp + '', that); } if (visible && sc) { scrollToPos(time); } v = s.formatResult(that.temp); if (!temp) { that.values = that.temp.slice(0); that.val = v; } if (fill) { if (input) { elm.val(v).trigger('change'); } } }; that.getValues = function() { var ret = [], i; for (i in that._selectedValues) { ret.push(that._selectedValues[i]); } return ret; }; /** * Checks if the current selected values are valid together. * In case of date presets it checks the number of days in a month. * @param {Number} time - Animation time * @param {Number} orig - Original value * @param {Number} i - Currently changed wheel index, -1 if initial validation. * @param {Number} dir - Scroll direction */ that.validate = function(i, dir, time, orig) { scrollToPos(time, i, true, dir, orig); }; /** * */ that.change = function(manual) { v = s.formatResult(that.temp); // if (s.display == 'inline') { that.setValue(false, manual); // } else { // $('.dwv', dw).html(formatHeader(v)); // } if (manual) { event('onChange', [v]); } }; /** * Changes the values of a wheel, and scrolls to the correct position */ that.changeWheel = function(idx, time) { if (dw) { var i = 0, j, k, nr = idx.length; for (j in s.wheels) { for (k in s.wheels[j]) { if ($.inArray(i, idx) > -1) { warr[i] = s.wheels[j][k]; $('.dw-ul', dw).eq(i).html(generateWheelItems(i)); nr--; if (!nr) { position(); scrollToPos(time, undefined, true); return; } } i++; } } } }; /** * Return true if the scroller is currently visible. */ that.isVisible = function() { return visible; }; /** * */ that.tap = function(el, handler) { var startX, startY; if (s.tap) { el.bind('touchstart', function(e) { e.preventDefault(); startX = getCoord(e, 'X'); startY = getCoord(e, 'Y'); }).bind('touchend', function(e) { // If movement is less than 20px, fire the click event handler if (Math.abs(getCoord(e, 'X') - startX) < 20 && Math.abs(getCoord(e, 'Y') - startY) < 20) { handler.call(this, e); } tap = true; setTimeout(function() { tap = false; }, 300); }); } el.bind('click', function(e) { if (!tap) { // If handler was not called on touchend, call it on click; handler.call(this, e); } }); }; /** * Shows the scroller instance. * @param {Boolean} prevAnim - Prevent animation if true */ that.show = function(prevAnim) { if (s.disabled || visible) { return false; } if (s.display == 'top') { anim = 'slideup'; } if (s.display == 'bottom') { anim = 'slidedown'; } // Parse value from input read(); event('onBeforeShow', [dw]); // Create wheels var l = 0, i, label, mAnim = ''; if (anim && !prevAnim) { mAnim = 'dw-' + anim + ' dw-in'; } // Create wheels containers var html = '<div class="dw-trans ' + s.theme + ' dw-' + s.display + '">' + (s.display == 'inline' ? '<div class="dw dwbg dwi"><div class="dwwr">' : '<div class="dw-persp">' + '<div class="dwo"></div><div class="dw dwbg ' + mAnim + '"><div class="dw-arrw"><div class="dw-arrw-i"><div class="dw-arr"></div></div></div><div class="dwwr">'); html += (s.display != 'inline' ? '<div class="dwbc' + (s.button3 ? ' dwbc-p' : '') + '"><span class="dwbw dwb-c"><span class="dwb">' + s.cancelText + '</span></span>' + (s.button3 ? '<span class="dwbw dwb-n"><span class="dwb">' + s.button3Text + '</span></span>' : '') + '<span class="dwbw dwb-s"><span class="dwb">' + s.setText + '</span></span></div></div>' : '<div class="dwcc"></div>'); for (i = 0; i < s.wheels.length; i++) { html += '<div class="dwc' + (s.mode != 'scroller' ? ' dwpm' : ' dwsc') + (s.showLabel ? '' : ' dwhl') + '"><div class="dwwc dwrc"><table cellpadding="0" cellspacing="0"><tr>'; // Create wheels for (label in s.wheels[i]) { warr[l] = s.wheels[i][label]; html += '<td><div class="dwwl dwrc dwwl' + l + '">' + (s.mode != 'scroller' ? '<div class="dwwb dwwbp" style="height:' + hi + 'px;line-height:' + hi + 'px;"><span>+</span></div><div class="dwwb dwwbm" style="height:' + hi + 'px;line-height:' + hi + 'px;"><span>&ndash;</span></div>' : '') + '<div class="dww" style="height:' + (s.rows * hi) + 'px;min-width:' + s.width + 'px;"><div class="dw-ul">'; // Create wheel values html += generateWheelItems(l); html += '</div><div class="dwwo"></div></div><div class="dwwol"></div></div></td>'; l++; } html += '</tr></table></div></div>'; } html += '</div></div></div>'; dw = $(html); scrollToPos(); event('onMarkupReady', [dw]); // Show if (s.display != 'inline') { dw.appendTo('body'); // Remove animation class setTimeout(function() { dw.removeClass('dw-trans').find('.dw').removeClass(mAnim); }, 350); } else if (elm.is('div')) { elm.html(dw); } else { dw.insertAfter(elm); } event('onMarkupInserted', [dw]); visible = true; // Theme init theme.init(dw, that); if (s.display != 'inline') { // Init buttons that.tap($('.dwb-s span', dw), function() { if (that.hide(false, 'set') !== false) { that.setValue(false, true); event('onSelect', [that.val]); } }); that.tap($('.dwb-c span', dw), function() { that.cancel(); }); if (s.button3) { that.tap($('.dwb-n span', dw), s.button3); } // prevent scrolling if not specified otherwise if (s.scrollLock) { dw.bind('touchmove', function(e) { if (mh <= wh && mw <= ww) { e.preventDefault(); } }); } // Disable inputs to prevent bleed through (Android bug) $('input,select,button').each(function() { if (!$(this).prop('disabled')) { $(this).addClass('dwtd').prop('disabled', true); } }); // Set position position(); $(window).bind('resize.dw', function() { // Sometimes scrollTop is not correctly set, so we wait a little clearTimeout(debounce); debounce = setTimeout(function() { position(true); }, 100); }); } // Events dw.delegate('.dwwl', 'DOMMouseScroll mousewheel', function(e) { if (!isReadOnly(this)) { e.preventDefault(); e = e.originalEvent; var delta = e.wheelDelta ? (e.wheelDelta / 120) : (e.detail ? (-e.detail / 3) : 0), t = $('.dw-ul', this), p = +t.data('pos'), val = Math.round(p - delta); setGlobals(t); calc(t, val, delta < 0 ? 1 : 2); } }).delegate('.dwb, .dwwb', START_EVENT, function(e) { // Active button $(this).addClass('dwb-a'); }).delegate('.dwwb', START_EVENT, function(e) { e.stopPropagation(); e.preventDefault(); var w = $(this).closest('.dwwl'); if (testTouch(e) && !isReadOnly(w) && !w.hasClass('dwa')) { click = true; // + Button var t = w.find('.dw-ul'), func = $(this).hasClass('dwwbp') ? plus : minus; setGlobals(t); clearInterval(timer); timer = setInterval(function() { func(t); }, s.delay); func(t); } }).delegate('.dwwl', START_EVENT, function(e) { // Prevent scroll e.preventDefault(); // Scroll start if (testTouch(e) && !move && !isReadOnly(this) && !click) { move = true; $(document).bind(MOVE_EVENT, onMove); target = $('.dw-ul', this); scrollable = s.mode != 'clickpick'; pos = +target.data('pos'); setGlobals(target); moved = iv[index] !== undefined; // Don't allow tap, if still moving start = getCoord(e, 'Y'); startTime = new Date(); stop = start; that.scroll(target, index, pos, 0.001); if (scrollable) { target.closest('.dwwl').addClass('dwa'); } } }); event('onShow', [dw, v]); }; /** * Hides the scroller instance. */ that.hide = function(prevAnim, btn) { // If onClose handler returns false, prevent hide if (!visible || event('onClose', [v, btn]) === false) { return false; } // Re-enable temporary disabled fields $('.dwtd').prop('disabled', false).removeClass('dwtd'); elm.blur(); // Hide wheels and overlay if (dw) { if (s.display != 'inline' && anim && !prevAnim) { dw.addClass('dw-trans').find('.dw').addClass('dw-' + anim + ' dw-out'); setTimeout(function() { dw.remove(); dw = null; }, 350); } else { dw.remove(); dw = null; } visible = false; pixels = {}; // Stop positioning on window resize $(window).unbind('.dw'); } }; /** * Cancel and hide the scroller instance. */ that.cancel = function() { if (that.hide(false, 'cancel') !== false) { event('onCancel', [that.val]); } }; /** * Scroller initialization. */ that.init = function(ss) { // Get theme defaults theme = extend({ defaults: {}, init: empty }, ms.themes[ss.theme || s.theme]); // Get language defaults lang = ms.i18n[ss.lang || s.lang]; extend(settings, ss); // Update original user settings extend(s, theme.defaults, lang, settings); that.settings = s; // Unbind all events (if re-init) elm.unbind('.dw'); var preset = ms.presets[s.preset]; if (preset) { pres = preset.call(e, that); extend(s, pres, settings); // Load preset settings extend(methods, pres.methods); // Extend core methods } // Set private members m = Math.floor(s.rows / 2); hi = s.height; anim = s.animate; if (elm.data('dwro') !== undefined) { e.readOnly = bool(elm.data('dwro')); } if (visible) { that.hide(); } if (s.display == 'inline') { that.show(); } else { read(); if (input && s.showOnFocus) { // Set element readonly, save original state elm.data('dwro', e.readOnly); e.readOnly = true; // Init show datewheel elm.bind('focus.dw', function() { that.show(); }); } } }; that.trigger = function(name, params) { return event(name, params); }; that.values = null; that.val = null; that.temp = null; that._selectedValues = {}; // []; that.init(settings); } 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 getInst(e) { return scrollers[e.id]; } function getCoord(e, c) { var org = e.originalEvent, ct = e.changedTouches; return ct || (org && org.changedTouches) ? (org ? org.changedTouches[0]['page' + c] : ct[0]['page' + c]) : e['page' + c]; } function bool(v) { return (v === true || v == 'true'); } function constrain(val, min, max) { val = val > max ? max : val; val = val < min ? min : val; return val; } function calc(t, val, dir, anim, orig) { val = constrain(val, min, max); var cell = $('.dw-li', t).eq(val), o = orig === undefined ? val : orig, idx = index, time = anim ? (val == o ? 0.1 : Math.abs((val - o) * 0.1)) : 0; // Set selected scroller value inst.temp[idx] = cell.attr('data-val'); inst.scroll(t, idx, val, time, orig); setTimeout(function() { // Validate inst.validate(idx, dir, time, orig); }, 10); } function init(that, method, args) { if (methods[method]) { return methods[method].apply(that, Array.prototype.slice.call(args, 1)); } if (typeof method === 'object') { return methods.init.call(that, method); } return that; } var scrollers = {}, timer, empty = function() {}, h, min, max, inst, // Current instance date = new Date(), uuid = date.getTime(), move, click, target, index, start, stop, startTime, pos, moved, scrollable, mod = document.createElement('modernizr').style, has3d = testProps(['perspectiveProperty', 'WebkitPerspective', 'MozPerspective', 'OPerspective', 'msPerspective']), prefix = testPrefix(), extend = $.extend, tap, touch, START_EVENT = 'touchstart mousedown', MOVE_EVENT = 'touchmove mousemove', END_EVENT = 'touchend mouseup', onMove = function(e) { if (scrollable) { e.preventDefault(); stop = getCoord(e, 'Y'); inst.scroll(target, index, constrain(pos + (start - stop) / h, min - 1, max + 1)); } moved = true; }, defaults = { // Options width: 70, height: 40, rows: 3, delay: 300, disabled: false, readonly: false, showOnFocus: true, showLabel: true, wheels: [], theme: '', display: 'modal', mode: 'scroller', preset: '', lang: 'en-US', setText: 'Set', cancelText: 'Cancel', scrollLock: true, tap: true, formatResult: function(d) { return d.join(' '); }, parseValue: function(value, inst) { var w = inst.settings.wheels, val = value.split(' '), ret = [], j = 0, i, l, v; for (i = 0; i < w.length; i++) { for (l in w[i]) { if (w[i][l][val[j]] !== undefined) { ret.push(val[j]); } else { for (v in w[i][l]) { // Select first value from wheel ret.push(v); break; } } j++; } } return ret; } }, methods = { init: function(options) { if (options === undefined) { options = {}; } return this.each(function() { if (!this.id) { uuid += 1; this.id = 'scoller' + uuid; } scrollers[this.id] = new Scroller(this, options); }); }, enable: function() { return this.each(function() { var inst = getInst(this); if (inst) { inst.enable(); } }); }, disable: function() { return this.each(function() { var inst = getInst(this); if (inst) { inst.disable(); } }); }, isDisabled: function() { var inst = getInst(this[0]); if (inst) { return inst.settings.disabled; } }, isVisible: function() { var inst = getInst(this[0]); if (inst) { return inst.isVisible(); } }, option: function(option, value) { return this.each(function() { var inst = getInst(this); if (inst) { var obj = {}; if (typeof option === 'object') { obj = option; } else { obj[option] = value; } inst.init(obj); } }); }, setValue: function(d, fill, time, temp) { return this.each(function() { var inst = getInst(this); if (inst) { inst.temp = d; inst.setValue(true, fill, time, temp); } }); }, getInst: function() { return getInst(this[0]); }, getValue: function() { var inst = getInst(this[0]); if (inst) { return inst.values; } }, getValues: function() { var inst = getInst(this[0]); if (inst) { return inst.getValues(); } }, show: function() { var inst = getInst(this[0]); if (inst) { return inst.show(); } }, hide: function() { return this.each(function() { var inst = getInst(this); if (inst) { inst.hide(); } }); }, destroy: function() { return this.each(function() { var inst = getInst(this); if (inst) { inst.hide(); $(this).unbind('.dw'); delete scrollers[this.id]; if ($(this).is('input')) { this.readOnly = bool($(this).data('dwro')); } } }); } }; $(document).bind(END_EVENT, function(e) { if (move) { var time = new Date() - startTime, val = constrain(pos + (start - stop) / h, min - 1, max + 1), speed, dist, tindex, ttop = target.offset().top; if (time < 300) { speed = (stop - start) / time; dist = (speed * speed) / (2 * 0.0006); if (stop - start < 0) { dist = -dist; } } else { dist = stop - start; } tindex = Math.round(pos - dist / h); if (!dist && !moved) { // this is a "tap" var idx = Math.floor((stop - ttop) / h), li = $('.dw-li', target).eq(idx), hl = scrollable; if (inst.trigger('onValueTap', [li]) !== false) { tindex = idx; } else { hl = true; } if (hl) { li.addClass('dw-hl'); // Highlight setTimeout(function() { li.removeClass('dw-hl'); }, 200); } } if (scrollable) { calc(target, tindex, 0, true, Math.round(val)); } move = false; target = null; $(document).unbind(MOVE_EVENT, onMove); } if (click) { clearInterval(timer); click = false; } $('.dwb-a').removeClass('dwb-a'); }).bind('mouseover mouseup mousedown click', function(e) { // Prevent standard behaviour on body click if (tap) { e.stopPropagation(); e.preventDefault(); return false; } }); $.fn.mobiscroll = function(method) { extend(this, $.mobiscroll.shorts); return init(this, method, arguments); }; $.mobiscroll = $.mobiscroll || { /** * Set settings for all instances. * @param {Object} o - New default settings. */ setDefaults: function(o) { extend(defaults, o); }, presetShort: function(name) { this.shorts[name] = function(method) { return init(this, extend(method, { preset: name }), arguments); }; }, shorts: {}, presets: {}, themes: {}, i18n: {} }; $.scroller = $.scroller || $.mobiscroll; $.fn.scroller = $.fn.scroller || $.fn.mobiscroll; })(jQuery); /*jslint eqeq: true, plusplus: true, undef: true, sloppy: true, vars: true, forin: true */ (function($) { var ms = $.mobiscroll, date = new Date(), defaults = { dateFormat: 'mm/dd/yy', dateOrder: 'mmddy', timeWheels: 'hhiiA', timeFormat: 'hh:ii A', startYear: date.getFullYear() - 100, endYear: date.getFullYear() + 1, monthNames: ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'], monthNamesShort: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'], dayNames: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'], dayNamesShort: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'], shortYearCutoff: '+10', monthText: 'Month', dayText: 'Day', yearText: 'Year', hourText: 'Hours', minuteText: 'Minutes', secText: 'Seconds', ampmText: '&nbsp;', nowText: 'Now', showNow: false, stepHour: 1, stepMinute: 1, stepSecond: 1, separator: ' ' }, preset = function(inst) { var that = $(this), html5def = {}, format; // Force format for html5 date inputs (experimental) if (that.is('input')) { switch (that.attr('type')) { case 'date': format = 'yy-mm-dd'; break; case 'datetime': format = 'yy-mm-ddTHH:ii:ssZ'; break; case 'datetime-local': format = 'yy-mm-ddTHH:ii:ss'; break; case 'month': format = 'yy-mm'; html5def.dateOrder = 'mmyy'; break; case 'time': format = 'HH:ii:ss'; break; } // Check for min/max attributes var min = that.attr('min'), max = that.attr('max'); if (min) { html5def.minDate = ms.parseDate(format, min); } if (max) { html5def.maxDate = ms.parseDate(format, max); } } // Set year-month-day order var s = $.extend({}, defaults, html5def, inst.settings), offset = 0, wheels = [], ord = [], o = {}, i, k, f = { y: 'getFullYear', m: 'getMonth', d: 'getDate', h: getHour, i: getMinute, s: getSecond, a: getAmPm }, p = s.preset, dord = s.dateOrder, tord = s.timeWheels, regen = dord.match(/D/), ampm = tord.match(/a/i), hampm = tord.match(/h/), hformat = p == 'datetime' ? s.dateFormat + s.separator + s.timeFormat : p == 'time' ? s.timeFormat : s.dateFormat, defd = new Date(), stepH = s.stepHour, stepM = s.stepMinute, stepS = s.stepSecond, mind = s.minDate || new Date(s.startYear, 0, 1), maxd = s.maxDate || new Date(s.endYear, 11, 31, 23, 59, 59); inst.settings = s; format = format || hformat; if (p.match(/date/i)) { // Determine the order of year, month, day wheels $.each(['y', 'm', 'd'], function(j, v) { i = dord.search(new RegExp(v, 'i')); if (i > -1) { ord.push({ o: i, v: v }); } }); ord.sort(function(a, b) { return a.o > b.o ? 1 : -1; }); $.each(ord, function(i, v) { o[v.v] = i; }); var w = {}; for (k = 0; k < 3; k++) { if (k == o.y) { offset++; w[s.yearText] = {}; var start = mind.getFullYear(), end = maxd.getFullYear(); for (i = start; i <= end; i++) { w[s.yearText][i] = dord.match(/yy/i) ? i + '年' : (i + '').substr(2, 2) + '年'; } } else if (k == o.m) { offset++; w[s.monthText] = {}; for (i = 0; i < 12; i++) { var str = dord.replace(/[dy]/gi, '').replace(/mm/, i < 9 ? '' + (i + 1) + '月' : i + 1 + '月').replace(/m/, (i + 1)); w[s.monthText][i] = 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>'); } } else if (k == o.d) { offset++; w[s.dayText] = {}; for (i = 1; i < 32; i++) { w[s.dayText][i] = dord.match(/dd/i) && i < 10 ? '' + i + '日' : i + '日'; } } } wheels.push(w); } if (p.match(/time/i)) { // Determine the order of hours, minutes, seconds wheels ord = []; $.each(['h', 'i', 's', 'a'], function(i, v) { i = tord.search(new RegExp(v, 'i')); if (i > -1) { ord.push({ o: i, v: v }); } }); ord.sort(function(a, b) { return a.o > b.o ? 1 : -1; }); $.each(ord, function(i, v) { o[v.v] = offset + i; }); w = {}; for (k = offset; k < offset + 4; k++) { if (k == o.h) { offset++; w[s.hourText] = {}; for (i = 0; i < (hampm ? 12 : 24); i += stepH) { w[s.hourText][i] = hampm && i == 0 ? 12 : tord.match(/hh/i) && i < 10 ? '0' + i : i; } } else if (k == o.i) { offset++; w[s.minuteText] = {}; for (i = 0; i < 60; i += stepM) { w[s.minuteText][i] = tord.match(/ii/) && i < 10 ? '0' + i : i; } } else if (k == o.s) { offset++; w[s.secText] = {}; for (i = 0; i < 60; i += stepS) { w[s.secText][i] = tord.match(/ss/) && i < 10 ? '0' + i : i; } } else if (k == o.a) { offset++; var upper = tord.match(/A/); w[s.ampmText] = { 0: upper ? 'AM' : 'am', 1: upper ? 'PM' : 'pm' }; } } wheels.push(w); } function get(d, i, def) { if (o[i] !== undefined) { return +d[o[i]]; } if (def !== undefined) { return def; } return defd[f[i]] ? defd[f[i]]() : f[i](defd); } function step(v, st) { return Math.floor(v / st) * st; } function getHour(d) { var hour = d.getHours(); hour = hampm && hour >= 12 ? hour - 12 : hour; return step(hour, stepH); } function getMinute(d) { return step(d.getMinutes(), stepM); } function getSecond(d) { return step(d.getSeconds(), stepS); } function getAmPm(d) { return ampm && d.getHours() > 11 ? 1 : 0; } function getDate(d) { var hour = get(d, 'h', 0); return new Date(get(d, 'y'), get(d, 'm'), get(d, 'd', 1), get(d, 'a') ? hour + 12 : hour, get(d, 'i', 0), get(d, 's', 0)); } inst.setDate = function(d, fill, time, temp) { var i; // Set wheels for (i in o) { this.temp[o[i]] = d[f[i]] ? d[f[i]]() : f[i](d); } this.setValue(true, fill, time, temp); }; inst.getDate = function(d) { return getDate(d); }; return { button3Text: s.showNow ? s.nowText : undefined, button3: s.showNow ? function() { inst.setDate(new Date(), false, 0.3, true); } : undefined, wheels: wheels, /** * Builds a date object from the wheel selections and formats it to the given date/time format * @param {Array} d - An array containing the selected wheel values * @return {String} - The formatted date string */ formatResult: function(d) { return ms.formatDate(format, getDate(d), s); }, /** * Builds a date object from the input value and returns an array to set wheel values * @return {Array} - An array containing the wheel values to set */ parseValue: function(val) { var d = new Date(), i, result = []; try { d = ms.parseDate(format, val, s); } catch (e) {} // Set wheels for (i in o) { result[o[i]] = d[f[i]] ? d[f[i]]() : f[i](d); } return result; }, /** * Validates the selected date to be in the minDate / maxDate range and sets unselectable values to disabled * @param {Object} dw - jQuery object containing the generated html * @param {Integer} [i] - Index of the changed wheel, not set for initial validation */ validate: function(dw, i) {