UNPKG

persiandate-picker

Version:
1,747 lines (1,550 loc) 116 kB
/* persiandate-picker - v0.5.1 https://persiandate.github.io */ ( function () {(function ($) { $.fn.persianDatepicker = $.fn.pDatepicker = function (options) { var args = Array.prototype.slice.call(arguments), output = this; if (!this) { $.error("Invalid selector"); } $(this).each(function () { // encapsulation Args var emptyArr = new Array, tempArg = args.concat(emptyArr), dp = $(this).data("datepicker"); if (dp && typeof tempArg[0] == "string") { var funcName = tempArg[0], funcArgs = tempArg.splice(0, 1); output = dp[funcName](tempArg[0]); } else { this.pDatePicker = new Datepicker(this, options); } }); return output; }; })(jQuery); var ClassConfig = { /** * @memberOf ClassDatepicker.ClassConfig * @description if true all digit convert to persian digit. * @type {boolean} * @default true */ persianDigit: true, /** * @memberOf ClassDatepicker.ClassConfig * @description Acceptable value : day,month,year * @property viewMode * @type {string} * @default day */ viewMode: false, /** * @memberOf ClassDatepicker.ClassConfig * @description [x,y] , define a position of datepicker relative to input element. * @property position * @type {string|Array} * @default auto */ position: "auto", /** * @memberOf ClassDatepicker.ClassConfig * @description If true picker close When Select day * @property autoClose * @type {boolean} * @default false */ autoClose: false, /** * @memberOf ClassDatepicker.ClassConfig * @description the date format, combination of d, dd, m, mm, yy, yyy. * {@link https://persiandate.github.io/PersianWebToolkit/doc/persiandate/0.1.8/#/displaying/format/} * @desc format * @type {boolean} * @default false */ format: false, /** * @memberOf ClassDatepicker.ClassConfig * @desc observer * @type {boolean} * @default false */ observer: false, /** * @memberOf ClassDatepicker.ClassConfig * @desc inputDelay * @type {number} * @default 800 */ inputDelay: 800, /** * @memberOf ClassDatepicker.ClassConfig * @desc format value of input * @param unixDate * @returns {*} */ formatter: function (unixDate) { var self = this; var pdate = new persianDate(unixDate); pdate.formatPersian = false; return pdate.format(self.format); }, /** * @memberOf ClassDatepicker.ClassConfig * @description An input element that is to be updated with the selected date from the datepicker. Use the altFormat option to change the format of the date within this field. Leave as blank for no alternate field. acceptable value: : '#elementId','.element-class' * @desc altField * @type {boolean} * @default false */ altField: false, /** * @memberOf ClassDatepicker.ClassConfig * @description the date format, combination of d, dd, m, mm, yy, yyy. * {@link https://persiandate.github.io/PersianWebToolkit/doc/persiandate/0.1.8/#/displaying/format/} * @desc altField * @type {string} * @default unix */ altFormat: 'unix', /** * @memberOf ClassDatepicker.ClassConfig * @desc format value of 'altField' input * @param unixDate * @returns {*} */ altFieldFormatter: function (unixDate) { var self = this; var thisAltFormat = self.altFormat.toLowerCase(); if (thisAltFormat === "gregorian" | thisAltFormat === "g") { return new Date(unixDate); } if (thisAltFormat === "unix" | thisAltFormat === "u") { return unixDate; } else { return new persianDate(unixDate).format(self.altFormat); } }, /** * @memberOf ClassDatepicker.ClassConfig * @desc Open the date picker. * @method * @returns {ClassConfig} */ show: function () { this.view.fixPosition(this); this.element.main.show(); this.onShow(this); this._viewed = true; return this; }, /** * @memberOf ClassDatepicker.ClassConfig * @desc Hide the date picker * @method * @returns {ClassConfig} */ hide: function () { if (this._viewed) { this.element.main.hide(); this.onHide(this); this._viewed = false; } return this; }, /** * @memberOf ClassDatepicker.ClassConfig * @desc Removes the datepicker functionality completely. * @method * @param self */ destroy: function () { this.inputElem.removeClass(self.cssClass); this.element.main.remove(); }, /** * @memberOf ClassDatepicker.ClassConfig * @desc A function that takes current datepicker instance. It is called just before the datepicker is displayed. * @event * @param self */ onShow: function (self) { }, /** * @memberOf ClassDatepicker.ClassConfig * @desc A function that takes current datepicker instance. It is called just before the datepicker Hide. * @event * @param self */ onHide: function (self) { }, /** * @memberOf ClassDatepicker.ClassConfig * @desc A function that takes current datepicker unixDate. It is called When Day Select. * @event * @param unixDate */ onSelect: function (unixDate) { return this; }, /** * @see ClassNavigator * @memberOf ClassDatepicker.ClassConfig * @desc navigator config object * @property navigator * @type {object} * @default true */ navigator: { /** * @desc Enable or Disable dayPicker */ enabled: true, /** * @desc navigator text config object */ text: { /** * @desc text of next btn */ btnNextText: "<", /** * @desc text of prev btn */ btnPrevText: ">" }, /** * @desc Trigger When Next button clicked * @event * @param navigator */ onNext: function (navigator) { //log("navigator next "); }, /** * @desc Trigger When Prev button clicked * @event * @param navigator */ onPrev: function (navigator) { //log("navigator prev "); }, /** * @desc Trigger When Switch view button clicked * @event * @param navigator */ onSwitch: function (state) { // console.log("navigator switch "); } }, /** * @see ClassToolbox * @memberOf ClassDatepicker.ClassConfig * @desc toolbox config object * @property toolbox * @type {object} * @default true * @deprecated 0.2.3 */ toolbox: { enabled: true, text: { btnToday: "امروز" }, onToday: function (toolbox) { //log("toolbox today btn"); } }, /** * @see ClassTimePicker * @memberOf ClassDatepicker.ClassConfig * @desc timepicker config object * @property timePicker * @type {object} */ timePicker: { enabled: false, showSeconds: true, showMeridian: true, secondStep: 1, minuteStep: 1, hourStep: 1, scrollEnabled: true, /** * @deprecated 0.3.5 */ changeOnScroll: true }, /** * @see ClassDayPicker * @memberOf ClassDatepicker.ClassConfig * @desc dayPicker config object * @property dayPicker * @type {object} */ dayPicker: { enabled: true, scrollEnabled: true, titleFormat: 'YYYY MMMM', titleFormatter: function (year, month) { if (this.datepicker.persianDigit == false) { window.formatPersian = false; } var titleStr = new persianDate([year, month]).format(this.titleFormat); window.formatPersian = true; return titleStr }, onSelect: function (selectedDayUnix) { //log("daypicker month day :" + selectedDayUnix); } }, /** * @see ClassMonthPicker * @memberOf ClassDatepicker.ClassConfig * @desc monthPicker config object * @property monthPicker * @type {object} */ monthPicker: { enabled: true, scrollEnabled: true, titleFormat: 'YYYY', titleFormatter: function (unix) { if (this.datepicker.persianDigit == false) { window.formatPersian = false; } var titleStr = new persianDate(unix).format(this.titleFormat); window.formatPersian = true; return titleStr; }, onSelect: function (monthIndex) { //log("daypicker select day :" + monthIndex); } }, /** * @see ClassYearPicker * @memberOf ClassDatepicker.ClassConfig * @desc yearPicker config object * @property yearPicker * @type {object} */ yearPicker: { enabled: true, scrollEnabled: true, titleFormat: 'YYYY', titleFormatter: function (year) { var remaining = parseInt(year / 12) * 12; return remaining + "-" + (remaining + 11); }, onSelect: function (monthIndex) { //log("daypicker select Year :" + monthIndex); } }, /** * @memberOf ClassDatepicker.ClassConfig * @desc if true all pickers hide and just shpw timepicker * @property justSelectOnDate * @type {boolean} */ onlyTimePicker: false, /** * @memberOf ClassDatepicker.ClassConfig * @desc if true date select just by click on day in month grid * @property justSelectOnDate * @type {boolean} */ justSelectOnDate: true, /** * @memberOf ClassDatepicker.ClassConfig * @desc set min date on datepicker * @property minDate * @type {boolean} */ minDate: false, /** * @memberOf ClassDatepicker.ClassConfig * @desc set max date on datepicker * @property maxDate * @type {boolean} */ maxDate: false, /** * @memberOf ClassDatepicker.ClassConfig * @desc check date avalibility * @property unix * @type {function} */ checkDate: function (unix) { return true; }, /** * @memberOf ClassDatepicker.ClassConfig * @desc check month avalibility * @property month index * @type {function} */ checkMonth: function (month) { return true; }, /** * @memberOf ClassDatepicker.ClassConfig * @desc check year avalibility * @property year * @type {function} */ checkYear: function (year) { return true; } } var ClassDateRange = { /** * @property monthRange */ monthRange: { 1: { name: { fa: "فروردین" }, abbr: { fa: "فرو" } }, 2: { name: { fa: "اردیبهشت" }, abbr: { fa: "ارد" } }, 3: { name: { fa: "خرداد" }, abbr: { fa: "خرد" } }, 4: { name: { fa: "تیر" }, abbr: { fa: "تیر" } }, 5: { name: { fa: "مرداد" }, abbr: { fa: "مرد" } }, 6: { name: { fa: "شهریور" }, abbr: { fa: "شهر" } }, 7: { name: { fa: "مهر" }, abbr: { fa: "مهر" } }, 8: { name: { fa: "آبان" }, abbr: { fa: "آبا" } }, 9: { name: { fa: "آذر" }, abbr: { fa: "آذر" } }, 10: { name: { fa: "دی" }, abbr: { fa: "دی" } }, 11: { name: { fa: "بهمن" }, abbr: { fa: "بهم" } }, 12: { name: { fa: "اسفند" }, abbr: { fa: "اسف" } } }, /** * @property weekRange */ weekRange: { 0: { name: { fa: "شنبه" }, abbr: { fa: "ش" } }, 1: { name: { fa: "یکشنبه" }, abbr: { fa: "ی" } }, 2: { name: { fa: "دوشنبه" }, abbr: { fa: "د" } }, 3: { name: { fa: "سه شنبه" }, abbr: { fa: "س" } }, 4: { name: { fa: "چهار شنبه" }, abbr: { fa: "چ" } }, 5: { name: { fa: "پنج شنبه" }, abbr: { fa: "پ" } }, 6: { name: { fa: "جمعه" }, abbr: { fa: "ج" } } }, /** * @property persianDaysName */ persianDaysName: ["اورمزد", "بهمن", "اوردیبهشت", "شهریور", "سپندارمذ", "خورداد", "امرداد", "دی به آذز", "آذز", "آبان", "خورشید", "ماه", "تیر", "گوش", "دی به مهر", "مهر", "سروش", "رشن", "فروردین", "بهرام", "رام", "باد", "دی به دین", "دین", "ارد", "اشتاد", "آسمان", "زامیاد", "مانتره سپند", "انارام", "زیادی"] }; var TEMPLATE = { /** * @desc datepicker */ datepciker: "<div class='{{css.datePickerPlotArea}}' >" + // "<div class='{{css.navigator}}' ></div>" +// " <div class='{{css.dayView}}' ></div>" + // "<div class='{{css.monthView}}' ></div>" + // "<div class='{{css.yearView}}' ></div>" + // "<div class='{{css.timeView}}' ></div>" + // "<div class='{{css.toolbox}}' ></div>" + // "</div>", /** * @desc navigator */ navigator: "<div class='{{css.datpickerHeader}}' >" + // "<div class='{{css.btnNext}}' >{{btnNextText}}</div>" + // "<div class='{{css.btnSwitch}}' >{{btnSwitchText}}</div>" + // "<div class='{{css.btnPrev}}' >{{btnPrevText}}</div>" + // "</div>", /** * @desc timepicker */ timepicker: "<div class='hour time-segment' data-time-key='hour' >" + // "<div class='up-btn' >&#9650;</div>" + // "<input type='text' placeholder='hour' class='hour-input' />" + // "<div class='down-btn' >&#9660;</div>" + // "</div>" + // "<div class='divider' >:</div>" + // "<div class='minute time-segment' data-time-key='minute' >" + // "<div class='up-btn' >&#9650;</div>" + // "<input type='text' placeholder='minute' class='minute-input' />" + // "<div class='down-btn' >&#9660;</div>" + // "</div>" + // "<div class='divider second-divider' >:</div>" + // "<div class='second time-segment' data-time-key='second' >" + // "<div class='up-btn' >&#9650;</div>" + // "<input type='text' placeholder='second' class='second-input' />" + // "<div class='down-btn' >&#9660;</div>" + // "</div>" + // "<div class='divider meridian-divider' ></div>" + // "<div class='divider meridian-divider' ></div>" + // "<div class='meridian time-segment' data-time-key='meridian' >" + // "<div class='up-btn' >&#9650;</div>" + // "<input type='text' placeholder='meridian&' class='meridian-input' />" + // "<div class='down-btn' >&#9660;</div>" + // "</div>", /** * @desc Month Grid */ monthGrid: "<div class='{{css.main}}' >" + // "<div class='{{css.header}}' >" + // "<div class='{{css.headerTitle}}' ></div>" + // "<div class='{{css.headerRow}}' ></div>" + // "</div>" + // "<table cellspacing='0' class='{{css.daysTable}}' ><tbody><tr><td /><td/><td/><td/><td/><td/><td/></tr><tr><td/><td/><td/><td/><td/><td/><td/></tr><tr><td/><td/><td/><td/><td/><td/><td/></tr><tr><td/><td/><td/><td/><td/><td/><td/></tr><tr><td/><td/><td/><td/><td/><td/><td/></tr><tr><td/><td/><td/><td/><td/><td/><td/></tr></tbody></table>" + // "</div>" } 'use strict'; /** * @class ClassBase * @abstract * @type {{init: init, publishInDic: publishInDic, callOfDict: callOfDict, isSameDay: isSameDay, isValidGreguranDate: isValidGreguranDate, validatePersianDateString: validatePersianDateString, fullHeight: fullHeight, attachEvent: attachEvent, dettachEvent: dettachEvent, clearEvent: clearEvent, raiseEvent: raiseEvent, events: {init: null}}} */ var ClassBase = { /** * @desc initilize {@link ClassBase} * @private */ init: function () { this.isInstance = true; this.raiseEvent('init'); }, /** * * @param {Array} objectList * @param {string} methodName * @returns {*} */ publishInDic: function (objectList, methodName) { $.each(objectList, function (key, item) { item[methodName](); }); return objectList; }, /** * * @param {Array} objectList * @param {string} key * @param {string} methodName */ callOfDict: function (objectList, key, methodName) { }, /** * * @param {Numer} unix1 * @param {Numer} unix2 * @returns {pDate|boolean} */ isSameDay: function (unix1, unix2) { var d1 = new pDate(unix1); var d2 = new pDate(unix2); return d1 && d2 && d1.year() === d2.year() && d1.month() === d2.month() && d1.date() === d2.date(); }, /** * @param {string} inputDate * @returns {*|boolean} */ isValidGreguranDate: function (inputDate) { return inputDate && new Date(inputDate) != "Invalid Date" && new Date(inputDate) != "undefined"; }, /** * * @param {string} pasted * @returns {*} */ validatePersianDateString: function (pasted) { var newDate = new Date(pasted); var inputArray = pasted.split("/"); if (inputArray.length === 3) { var trueYear = inputArray[0].toString().length <= 4 && inputArray[0].toString().length >= 1; var trueMonth = inputArray[1].toString().length <= 2 && inputArray[1].toString().length >= 1; var trueDay = inputArray[2].toString().length <= 2 && inputArray[2].toString().length >= 1; } $.each(inputArray, function (index, key) { inputArray[index] = parseInt(key); }); if (trueYear && trueMonth && trueDay && newDate !== "Invalid Date") { return inputArray; } else { return null; } }, /** * * @param {object} element * @returns {*} */ fullHeight: function (element) { return $(element).height() + parseInt($(element).css("padding-top")) + parseInt($(element).css("padding-bottom")) + parseInt($(element).css("borderTopWidth")) + parseInt($(element).css("borderBottomWidth")); }, /** * * @param {string} eventName * @param {Function} func * @returns {Class_Base} */ attachEvent: function (eventName, func) { if (!this.events[eventName]) { this.events[eventName] = []; } var f; for (f in this.events[eventName]) { if (this.events[eventName][f].toString() == func.toString()) { $.error("The function {0} was already added to event's chain.".format(func.toString)); } } this.events[eventName].push(func) return this; }, /** * * @param {string} eventName * @param {Function} func * @returns {Class_Base} */ dettachEvent: function (eventName, func) { if (!this.events[eventName]) { $.error("The event's chain is empty."); } var f; for (f in this.events[eventName]) { if (this.events[eventName][f].toString() == func.toString()) { delete this.events[eventName][f]; } } return this; }, /** * @param {string} eventName * @returns {Class_Base} */ clearEvent: function (eventName) { this.events[eventName] = null; return this; }, /** * @param eventName * @param args * @returns {Class_Base} */ raiseEvent: function (eventName, args) { if (!eventName || !this.events) { return; } if (args) { } else { args = []; } var currentObject = this.events[eventName]; if (!currentObject) { return; } else if (typeof currentObject === 'function') { currentObject.apply(this, args); } else { var e; for (e in currentObject) { currentObject[e].apply(this, args); } } return this; } }; /** * @class ClassSprite * @abstract * @type {{defaultView: string, events: {init: init, render: null}, views: {default: {render: render}}, element: {main: null}, createElementByClass: createElementByClass, render: render, tmpl: {}}} */ var ClassSprite = { /** * @desc defaultView */ defaultView: "default", /** * @desc events */ events: { init: function () { this.render(); }, render: null }, /** * @desc views */ views: { 'default': { render: function () { } } }, /** * @desc element */ element: { main: null// Root Element Of Sprite }, /** * @desc createElementByClass * @param {string} className string of class * @returns {*} */ createElementByClass: function (className) { return this.element.find('.' + className); }, /** * @desc render * @param {string} viewName * @returns {*} */ render: function (viewName) { if (!viewName) { viewName = 'default'; } this.raiseEvent('render'); this.view = this.views[viewName]; return this.view.render(this); } }; var ClassCompat = { /** * @memberOf ClassDatepicker.ClassCompat * @returns {ClassDatepicker} */ compatConfig: function () { if (this.viewMode === false) { if (this.yearPicker.enabled) { this.viewMode = 'year'; } if (this.monthPicker.enabled) { this.viewMode = 'month'; } if (this.dayPicker.enabled) { this.viewMode = 'day'; } else { this.justSelectOnDate = false; } } if (this.minDate | this.maxDate) { this.state.setFilterDate('unix', this.minDate, this.maxDate); this.state._filetredDate = true; } else { this.state._filetredDate = false; } return this; } }; 'use strict'; /** * Extend javascript Object * @type {Function} */ Object.keys = Object.keys || (function () { var hasOwnProperty = Object.prototype.hasOwnProperty, hasDontEnumBug = !{ toString: null }.propertyIsEnumerable("toString"), DontEnums = ['toString', 'toLocaleString', 'valueOf', 'hasOwnProperty', 'isPrototypeOf', 'propertyIsEnumerable', 'constructor'], DontEnumsLength = DontEnums.length; return function (o) { if (typeof o !== "object" && typeof o !== "function" || o === null) throw new TypeError("Object.keys called on a non-object"); var result = []; for (var name in o) { if (hasOwnProperty.call(o, name)) result.push(name); } if (hasDontEnumBug) { for (var i = 0; i < DontEnumsLength; i++) { if (hasOwnProperty.call(o, DontEnums[i])) result.push(DontEnums[i]); } } return result; }; })(); /** * Extend javascript Event * @type {{setup: setup, teardown: teardown, handler: handler, delayedHandler: delayedHandler, triggerIfChanged: triggerIfChanged, saveLastValue: saveLastValue}} */ $.event.special.textchange = { setup: function (data, namespaces) { $.event.special.textchange.saveLastValue(this); $(this).bind('keyup.textchange', $.event.special.textchange.handler); $(this).bind('cut.textchange paste.textchange input.textchange', $.event.special.textchange.delayedHandler); }, teardown: function (namespaces) { $(this).unbind('.textchange'); }, handler: function (event) { $.event.special.textchange.triggerIfChanged($(this)); }, delayedHandler: function (event) { var element = $(this); setTimeout(function () { $.event.special.textchange.triggerIfChanged(element); }, 25); }, triggerIfChanged: function (element) { var current = element[0].contentEditable === 'true' ? element.html() : element.val(); if (current !== element.data('lastValue')) { element.trigger('textchange', element.data('lastValue')); // element.data('lastValue', current); } }, saveLastValue: function (element) { $(element).data('lastValue', element.contentEditable === 'true' ? $(element).html() : $(element).val()); } }; $.event.special.hastext = { setup: function (data, namespaces) { $(this).bind('textchange', $.event.special.hastext.handler); }, teardown: function (namespaces) { $(this).unbind('textchange', $.event.special.hastext.handler); }, handler: function (event, lastValue) { if ((lastValue === '') && lastValue !== $(this).val()) { $(this).trigger('hastext'); } } }; $.event.special.notext = { setup: function (data, namespaces) { $(this).bind('textchange', $.event.special.notext.handler); }, teardown: function (namespaces) { $(this).unbind('textchange', $.event.special.notext.handler); }, handler: function (event, lastValue) { if ($(this).val() === '' && $(this).val() !== lastValue) { $(this).trigger('notext'); } } }; // Enhance val() so that this plugin is aware of programmatic changes to // text using val(). var origValFn = $.fn.val; $.fn.val = function () { var returnValue = origValFn.apply(this, arguments); if (arguments.length) { this.each(function () { $.event.special.textchange.triggerIfChanged($(this)); }); } return returnValue; }; /** * Micro Mustcahe Template * @param input * @param dict * @returns {*|jQuery|HTMLElement} */ $.tmplMustache = function (input, dict) { // Micro Mustache Template engine String.prototype.format = function string_format(arrayInput) { function replacer(key) { var keyArr = key.slice(2, -2).split("."), firstKey = keyArr[0], SecondKey = keyArr[1]; if (arrayInput[firstKey] instanceof Object) { return arrayInput[firstKey][SecondKey]; } else { return arrayInput[firstKey]; } } return this.replace(/{{\s*[\w\.]+\s*}}/g, replacer); }; return $(input.format(dict)); }; /** * Extend String Proto with toPersianDigit & toEnglishDigit * @param a * @returns {string} */ String.prototype.toPersianDigit = function (a) { return this.replace(/\d+/g, function (digit) { var enDigitArr = [], peDigitArr = []; for (var i = 0; i < digit.length; i++) { enDigitArr.push(digit.charCodeAt(i)); } for (var j = 0; j < enDigitArr.length; j++) { peDigitArr.push(String.fromCharCode(enDigitArr[j] + ((!!a && a == true) ? 1584 : 1728))); } return peDigitArr.join(''); }); }; /** * * @param a * @returns {string} */ String.prototype.toEngilshDigit = function (a) { return this.replace(/\d+/g, function (digit) { var enDigitArr = [], peDigitArr = []; for (var i = 0; i < digit.length; i++) { enDigitArr.push(digit.charCodeAt(i)); } for (var j = 0; j < enDigitArr.length; j++) { peDigitArr.push(String.fromCharCode(enDigitArr[j] - ((!!a && a == true) ? 1584 : 1728))); } return enDigitArr.join(''); }); }; /** * Helper Methuds * @param callback * @param ms */ var delay = function (callback, ms) { clearTimeout(window.datepickerTimer); window.datepickerTimer = setTimeout(callback, ms); }; /** * * @param input */ var log = function (input) { console.log(input); }; /** * * @param e * @returns {Array} */ var range = function (e) { var r = []; var i = 0; while (i <= e - 1) { r.push(i); i++; } return r; }; /** * * @param self * @param baseClasses * @returns {*} */ var inherit = function (self, baseClasses) { var copyObject = function (o) { return $.extend(true, {}, o); } var args = [true, self, copyObject(ClassBase)]; var events = []; for (var index in baseClasses) { var cls = copyObject(baseClasses[index]); if (!cls) { continue; } if (cls['events'] && Object.keys(cls['events']).length > 0) { events.push(cls['events']); } cls.events = {}; args.push(cls); } $.extend.apply(self, args); for (var index in events) { var eventsObject = events[index]; var eventKeys = Object.keys(eventsObject) for (var keyIndex in eventKeys) { var key = eventKeys[keyIndex] var val = eventsObject[key]; if (key && val) { self.attachEvent(key, val); } } } self.init(); return self; } /** * * @param ua * @returns {{browser: (*|string), version: (*|string)}} */ jQuery.uaMatch = function (ua) { ua = ua.toLowerCase(); var match = /(chrome)[ \/]([\w.]+)/.exec(ua) || /(webkit)[ \/]([\w.]+)/.exec(ua) || /(opera)(?:.*version|)[ \/]([\w.]+)/.exec(ua) || /(msie) ([\w.]+)/.exec(ua) || ua.indexOf("compatible") < 0 && /(mozilla)(?:.*? rv:([\w.]+)|)/.exec(ua) || []; return { browser: match[ 1 ] || "", version: match[ 2 ] || "0" }; }; // cDon't clobber any existing jQuery.browser in case it's different if (!jQuery.browser) { var matched = jQuery.uaMatch(window.navigator.userAgent); var browser = {}; if (matched.browser) { browser[ matched.browser ] = true; browser.version = matched.version; } // Chrome is Webkit, but Webkit is also Safari. if (browser.chrome) { browser.webkit = true; } else if (browser.webkit) { browser.safari = true; } jQuery.browser = browser; } var ClassMonthGrid = { /** * @memberOf ClassDayPicker.ClassMonthGrid * @desc state * @prop year * @prop month * @prop date * @prop firstWeekDayOfMonth * @prop daysCount */ state: { year: null, month: null, date: null, firstWeekDayOfMonth: null, daysCount: null }, /** * @memberOf ClassDayPicker.ClassMonthGrid * @desc perisnaDigit */ persianDigit: true, /** * @memberOf ClassDayPicker.ClassMonthGrid * @desc _formatDigit * @param digit * @returns {*} * @private */ _formatDigit: function (digit) { if (this.persianDigit) { return digit.toString().toPersianDigit(); } else { return digit; } }, /** * @memberOf ClassDayPicker.ClassMonthGrid * @desc evenets * @prop init * @prop render * @prop reRender * @prop selectDay */ events: { init: function () { }, render: function () { this.state.month = this.month; this.state.year = this.year; }, reRender: function () { this._markToday(); }, selectDay: function (x) { } }, /** * @memberOf ClassDayPicker.ClassMonthGrid * @desc _markToday * @returns {Class_MonthGrid} * @private */ _markToday: function () { var self = this; var todate = new persianDate(); $(self.element).removeClass(self.cssClass.today); $.each(self.daysList, function (index, value) { var htmlItemDay = $(this).data().day; var htmlItemMonth = $(this).data().month; var htmlItemYear = $(this).data().year; if (htmlItemDay == todate.date() && htmlItemMonth == todate.month() && htmlItemYear == todate.year()) { $(this).addClass(self.cssClass.today); $(self.element).addClass(self.cssClass.today); } }); return this; }, /** * @memberOf ClassDayPicker.ClassMonthGrid * @desc _updateState * @returns {Class_MonthGrid} * @private * @todo : must remove */ _updateState: function () { var self = this; var t = new persianDate(); self.daysCount = t.daysInMonth(self.state.year, self.state.month); self.firstWeekDayOfMonth = t.getFirstWeekDayOfMonth(self.state.year, self.state.month); return this; }, /** * @memberOf ClassDayPicker.ClassMonthGrid * @desc selectDate * @param unixDate * @returns {Class_MonthGrid} */ selectDate: function (unixDate) { var self = this, reRenderFlag; var sDate = new persianDate(unixDate); if (self.state.year == sDate.year() && self.state.month == sDate.month()) { reRenderFlag = false; } else { reRenderFlag = true; } self.state.year = sDate.year(); self.state.month = sDate.month(); self.state.date = sDate.date(); if (reRenderFlag) { self.view.renderDays(self); } self.markSelectedDate(unixDate); return this; }, /** * @memberOf ClassDayPicker.ClassMonthGrid * @desc markSelectedDate * @param unixDate */ markSelectedDate: function (unixDate) { var self = this; $.each(self.daysList, function (index, value) { var viewItemUnix = parseInt($(value).attr("unixDate")); if (self.isSameDay(viewItemUnix, unixDate)) { $(this).addClass(self.cssClass.selected); } else { $(this).removeClass(self.cssClass.selected); } }); }, /** * @memberOf ClassDayPicker.ClassMonthGrid * @desc updateAs * @param year * @param month * @returns {Class_MonthGrid} */ updateAs: function (year, month) { var self = this; self.state.year = year; self.state.month = month; self.view.renderDays(self); return this; }, /** * @memberOf ClassDayPicker.ClassMonthGrid * @desc goToNextMonth * @returns {boolean} */ goToNextMonth: function () { var self = this; if (self.state.month === 12) { self.state.month = 1; self.state.viewYear += 1; } else { self.state.month += 1; } self.updateAs(self.state.year, self.state.month) return false; }, /** * @memberOf ClassDayPicker.ClassMonthGrid * @desc goTOPrevMonth */ goToPrevMonth: function () { }, /** * @memberOf ClassDayPicker.ClassMonthGrid * @desc goToYear * @param year */ goToYear: function (year) { this.updateAs(year, this.state.month); }, /** * @memberOf ClassDayPicker.ClassMonthGrid * @desc applyStory */ applyStory: function () { //this.view.applyStory(this); } }; MonthGrid = function (options) { // Change !! //this.pcal = options.parent.pcal; inherit(this, [ClassSprite, ViewsMonthGrid, ClassDateRange, ClassMonthGrid, options]); return this; } 'use strict'; /** * @desc Instantiate in {@link ClassMonthGrid} * @class ViewsMonthGrid * @memberOf ClassMonthGrid * @type {{cssClass: {main: string, header: string, headerTitle: string, headerRow: string, headerRowCell: string, daysTable: string, currentMonth: string, today: string, selected: string}, views: {default: {render: render, renderDays: renderDays}}}} */ var ViewsMonthGrid = { /** * @memberOf ClassMonthGrid.ViewsMonthGrid * @desc cssClass {string} * @prop main {string} * @prop header {string} * @prop headerTitle {string} * @prop headerRow {string} * @prop headerRowCell {string} * @prop daysTable {string} * @prop currentMonth {string} * @prop today {string} * @prop selected {string} * @prop disbaled {string} */ cssClass: { main: "month-grid-box", header: "header", headerTitle: "title", headerRow: "header-row", headerRowCell: "header-row-cell", daysTable: "table-days", currentMonth: "current-month", today: "today", selected: 'selected', disbaled: 'disabled' }, /** * @memberOf ClassMonthGrid.ViewsMonthGrid * @desc views */ views: { "default": { /** * * @param self */ render: function (self) { self.viewData = { css: self.cssClass }; self.element = $.tmplMustache(TEMPLATE.monthGrid, self.viewData).appendTo(self.container); self.header = self.createElementByClass(self.cssClass.header); self.headerRow = self.createElementByClass(self.cssClass.headerRow); var weekDay; for (weekDay in self.weekRange) { $("<div/>").text(self.weekRange[weekDay].abbr.fa).addClass(self.cssClass.headerRowCell).appendTo(self.headerRow)[0]; } ; self.daysBox = self.createElementByClass(self.cssClass.daysTable); this.renderDays(self); }, /** * * @param self */ renderDays: function (self) { self._updateState(); self.daysList = []; var addSpan = function (day, month, year, cssClass) { var dayPartUnixTime = new persianDate([year, month, day]).valueOf(); var span = $("<span/>") .text(self._formatDigit(day)) .attr("unixDate", dayPartUnixTime) .data({ day: day, month: month, year: year, unixDate: dayPartUnixTime}) .addClass(cssClass) .appendTo($(this))[0]; self.daysList.push(span); } var t = new persianDate(); self.daysCount = t.daysInMonth(self.state.year, self.state.month); self.firstWeekDayOfMonth = t.getFirstWeekDayOfMonth(self.state.year, self.state.month); var currentMonthIndex = 1; var nextMonthIndex = 1; $(self.daysBox).find("td").each(function (index) { $(this).empty(); if (self.firstWeekDayOfMonth > 1 && index + 1 < self.firstWeekDayOfMonth) { if (self.state.month === 1) { var prevMonth = 12; var prevYear = parseInt(self.state.year) - 1; } else { var prevMonth = parseInt(self.state.month) - 1; var prevYear = parseInt(self.state.year); } var prevMonthDaysCount = t.daysInMonth(prevYear, prevMonth); var day = parseInt((prevMonthDaysCount - self.firstWeekDayOfMonth) + (index + 2)); addSpan.apply(this, [day, prevMonth, prevYear, "other-month"]) } else if (index + 2 === (currentMonthIndex + self.firstWeekDayOfMonth) && currentMonthIndex <= self.daysCount) { var day = currentMonthIndex; addSpan.apply(this, [day, parseInt(self.state.month), parseInt(self.state.year)]) currentMonthIndex++; } else { if (self.state.month === 12) { var nextMonth = 1; var nextYear = parseInt(self.state.year) + 1; } else { var nextMonth = parseInt(self.state.month) + 1; var nextYear = self.state.year; } var day = nextMonthIndex; addSpan.apply(this, [day, nextMonth, nextYear, "other-month"]); nextMonthIndex += 1; } var thisUnix = $(this).children("span").data("unixDate"); if (self.datepicker.state._filetredDate) { if (self.minDate && self.maxDate) { if (thisUnix >= self.minDate && thisUnix <= self.maxDate) { $(this).addClass(self.cssClass.disbaled); } else { $(this).removeClass(self.cssClass.disbaled); } } else if (self.minDate) { if (thisUnix >= self.minDate) { $(this).addClass(self.cssClass.disbaled); } } else if (self.maxDate) { if (thisUnix <= self.maxDate) { $(this).removeClass(self.cssClass.disbaled); } } } else { if (self.datepicker.checkDate(thisUnix)) { $(this).removeClass(self.cssClass.disbaled); } else { $(this).addClass(self.cssClass.disbaled); } } }); $(self.daysBox).find("td").not('.disabled').children("span").click(function () { var $thisUnixDate = $(this).data("unixDate"); self.raiseEvent("selectDay", [$thisUnixDate]); return false; }); $(self.daysBox).find('td.disabled').children("span").click(function () { return false; }); self.raiseEvent("reRender"); } } } }; 'use strict'; /** * @desc Instantiate in {@link ClassDatepicker} * @class ViewsDatePicker * @memberOf ClassDatepicker * @type {{cssClass: {datePickerPlotArea: string, yearView: string, monthView: string, dayView: string, timeView: string, navigator: string, toolbox: string}, container: {}, views: {default: {render: render, fixPosition: fixPosition}}}} */ var ViewsDatePicker = { /** * @memberOf ClassDatepicker.ViewsDatePicker * @desc cssClass {string} * @prop datePickerPlotArea {string} * @prop yearView {string} * @prop monthView {string} * @prop dayView {string} * @prop timeView {string} * @prop navigator {string} * @prop toolbox {string} */ cssClass: { datePickerPlotArea: "datepicker-plot-area", yearView: "datepicker-year-view", monthView: "datepicker-month-view", dayView: "datepicker-day-view", timeView: "datepicker-time-view", navigator: "navigator", toolbox: "toolbox " }, /** * @memberOf ClassDatepicker.ViewsDatePicker * @desc conatiner */ container: {}, /** * @memberOf ClassDatepicker.ViewsDatePicker * @desc views * @prop default {object} */ views: { /** * @memberOf ClassDatepicker.ViewsDatePicker.views * @prop render {function} * @prop fixPosition {function} */ "default": { /** * * @param self * @returns {ViewsDatePicker} */ render: function (self) { var viewData = { css: self.cssClass }; self.element = {}; /** * @memberOf ViewsDatePicker */ self.element.main = $.tmplMustache(TEMPLATE.datepciker, viewData).appendTo(self.$container); if (!self._inlineView) { self.element.main.hide(); } else { self.element.main.addClass('datepicker-plot-area-inline-view'); self.element.main.show(); } self.view.fixPosition(self); self.container.navigator = $(self.element.main).children('.' + self.cssClass.navigator); self.container.dayView = $(self.element.main).children('.' + self.cssClass.dayView); self.container.monthView = $(self.element.main).children('.' + self.cssClass.monthView); self.container.yearView = $(self.element.main).children('.' + self.cssClass.yearView); self.container.timeView = $(self.element.main).children('.' + self.cssClass.timeView); self.container.toolbox = $(self.element.main).children('.' + self.cssClass.toolbox); if (self.navigator.enabled && self.onlyTimePicker == false) { self.navigator = new Navigator($.extend(true, self.navigator, {datepicker: self}), self.container.navigator); } else { self.container.navigator.remove(); self.navigator = false; } if (self.toolbox.enabled && self.onlyTimePicker === false) { self.toolbox = new Toolbox($.extend(true, self.toolbox, {datepicker: self}), self.container.toolbox); } else { self.container.toolbox.remove(); self.toolbox = false; } if (self.dayPicker.enabled && self.onlyTimePicker === false) { self.dayPicker = new Daypicker($.extend(true, self.dayPicker, {datepicker: self}), self.container.dayView); self._pickers.day = self.dayPicker; } else { self.container