From 2768a68100247c8513b97a6a01ce1c8442a775fc Mon Sep 17 00:00:00 2001 From: Nazar Mokrynskyi Date: Tue, 13 Feb 2018 00:48:10 +0200 Subject: [PATCH] Added support for customizing position by specifying custom function as `position` option --- changelog.md | 3 +- dist/pickmeup.min.js | 70 +++++++++++++++++++++----------------------- js/pickmeup.js | 65 ++++++++++++++++++++++------------------ package.json | 2 +- readme.md | 56 +++++++++++++++++------------------ 5 files changed, 101 insertions(+), 95 deletions(-) diff --git a/changelog.md b/changelog.md index ba88a91..7f0e389 100644 --- a/changelog.md +++ b/changelog.md @@ -1,7 +1,8 @@ -Unreleased yet +3.1.0 (13 February, 2018) * License changed from MIT to 0BSD * Removed Bower support, use NPM instead * CoffeeScript files converted to LiveScript +* Added support for customizing position by specifying custom function as `position` option 3.0.11 (07 November, 2017) * Fix for selected is not defined diff --git a/dist/pickmeup.min.js b/dist/pickmeup.min.js index 618b494..46346df 100644 --- a/dist/pickmeup.min.js +++ b/dist/pickmeup.min.js @@ -1,38 +1,36 @@ /* - Copyright (c) 2013-2017, Nazar Mokrynskyi - @copyright Copyright (c) 2008-2009, Stefan Petre - @license MIT License, see license.txt + 0BSD */ -(function(F,y){"function"===typeof define&&define.amd?define(y):"object"===typeof exports?module.exports=y():F.pickmeup=y()})(this,function(){function F(a,b,c){c=c||[];if(a instanceof Element)b.apply(b,[a].concat(c));else{var d,e;d=a.length;for(e=0;el)){--h;q(G,-1);r=void 0;continue}r=new Date(k);if(!v&&(v=new Date(k), -v.setDate(1),q(v,1),A(v,-1),f&&f>v)){--h;q(G,1);v=void 0;continue}p.querySelector(".pmu-month").textContent=m;var t=function(a){return"range"==c.mode&&a>=(new Date(e[0])).getFullYear()&&a<=(new Date(e[1])).getFullYear()||"multiple"==c.mode&&-1!==e.reduce(function(a,c){a.push((new Date(c)).getFullYear());return a},[]).indexOf(a)||(new Date(e)).getFullYear()==a},u=function(a,b){var d=(new Date(e[0])).getFullYear(),k=(new Date(e[1])).getFullYear(),g=(new Date(e[0])).getMonth(),f=(new Date(e[1])).getMonth(); -return"range"==c.mode&&(a>d&&ad&&a==k&&b<=f||a==d&&a=g||a==d&&a==k&&b>=g&&b<=f)||"multiple"==c.mode&&-1!==e.reduce(function(a,c){c=new Date(c);a.push(c.getFullYear()+"-"+c.getMonth());return a},[]).indexOf(a+"-"+b)||(new Date(e)).getFullYear()==a&&(new Date(e)).getMonth()==b};(function(){var a=[],b=k.getFullYear()-6,d=(new Date(c.min)).getFullYear(),e=(new Date(c.max)).getFullYear(),f,h,l;for(l=0;12>l;++l)f=b+l,h=document.createElement("div"),h.textContent=f,h.__pickmeup_year=f,c.min&& -fe?g(h,"pmu-disabled"):t(f)&&g(h,"pmu-selected"),a.push(h);p.appendChild(c.instance_content_template(a,"pmu-years"))})();(function(){var a=[],b=k.getFullYear(),d=(new Date(c.min)).getFullYear(),e=(new Date(c.min)).getMonth(),f=(new Date(c.max)).getFullYear(),h=(new Date(c.max)).getMonth(),l,m;for(l=0;12>l;++l)m=document.createElement("div"),m.textContent=c.locales[c.locale].monthsShort[l],m.__pickmeup_month=l,m.__pickmeup_year=b,c.min&&(bf||l>h&&b>=f)?g(m,"pmu-disabled"): -u(b,l)&&g(m,"pmu-selected"),a.push(m);p.appendChild(c.instance_content_template(a,"pmu-months"))})();(function(){var a=[],b=k.getMonth(),d=x(new Date).valueOf(),e,f,h,l,m;(function(){k.setDate(1);var a=(k.getDay()-c.first_day)%7;A(k,-(a+(0>a?7:0)))})();for(e=0;42>e;++e)f=document.createElement("div"),f.textContent=k.getDate(),f.__pickmeup_day=k.getDate(),f.__pickmeup_month=k.getMonth(),f.__pickmeup_year=k.getFullYear(),b!=k.getMonth()&&g(f,"pmu-not-in-month"),0==k.getDay()?g(f,"pmu-sunday"):6==k.getDay()&& -g(f,"pmu-saturday"),h=c.render(new Date(k))||{},l=x(new Date(k)).valueOf(),m=c.min&&c.min>k||c.max&&c.max=c.date[0]&&l<=c.date[1],h.disabled||!("disabled"in h)&&m?g(f,"pmu-disabled"):(h.selected||!("selected"in h)&&selected)&&g(f,"pmu-selected"),l==d&&g(f,"pmu-today"),h.class_name&&h.class_name.split(" ").forEach(g.bind(f,f)),a.push(f),A(k,1);p.appendChild(c.instance_content_template(a, -"pmu-days"))})()}v.setDate(1);r.setDate(1);q(r,1);A(r,-1);d=b.querySelector(".pmu-prev");b=b.querySelector(".pmu-next");d&&(d.style.visibility=c.min&&c.min>=v?"hidden":"visible");b&&(b.style.visibility=c.max&&c.max<=r?"hidden":"visible");C(a,"fill")}function u(a,b){var c=b.format,d=b.separator,e=b.locales[b.locale];if(a instanceof Date||a instanceof Number)return x(new Date(a));if(!a)return x(new Date);if(a instanceof Array){a=a.slice();for(c=0;cl?2E3:1900;break;case "H":case "I":case "k":case "l":k=parseInt(a[c],10);break;case "P":case "p":/pm/i.test(a[c])&&12>k?k+=12:/am/i.test(a[c])&&12<=k&&(k-=12);break;case "M":m=parseInt(a[c],10)}e=new Date(void 0===l?p.getFullYear():l,void 0===f?p.getMonth():f,void 0===g?p.getDate():g,void 0===k?p.getHours():k,void 0===m?p.getMinutes():m,0);isNaN(1*e)&&(e=new Date);return x(e)}function x(a){a.setHours(0,0,0,0);return a}function D(a,b,c){var d=a.getMonth(),e=a.getDate(),g=a.getFullYear(), -f=a.getDay(),l=a.getHours(),k=12<=l,m=k?l-12:l,p;p=new Date(a.getFullYear(),a.getMonth(),a.getDate(),0,0,0);var n=new Date(a.getFullYear(),0,0,0,0,0);p=Math.floor((p-n)/24*36E5);0==m&&(m=12);var n=a.getMinutes(),r=a.getSeconds();b=b.split("");for(var h,q=0;qe?"0"+e:e;break;case "e":h=e;break;case "H":h= -10>l?"0"+l:l;break;case "I":h=10>m?"0"+m:m;break;case "j":h=100>p?10>p?"00"+p:"0"+p:p;break;case "k":h=l;break;case "l":h=m;break;case "m":h=9>d?"0"+(1+d):1+d;break;case "M":h=10>n?"0"+n:n;break;case "p":case "P":h=k?"PM":"AM";break;case "s":h=Math.floor(a.getTime()/1E3);break;case "S":h=10>r?"0"+r:r;break;case "u":h=f+1;break;case "w":h=f;break;case "y":h=(""+g).substr(2,2);break;case "Y":h=g}b[q]=h}return b.join("")}function O(a,b){var c=a.__pickmeup.options,d;x(b);a:{var e;switch(c.mode){case "multiple":e= -b.valueOf();for(d=0;df+k&&(m=e.top-c.offsetHeight);mg+l&&(p=e.left-c.offsetWidth);pa?new Date(b):c&&cn)){--h;p(G,-1);q=void 0;continue}q=new Date(k);if(!r&&(r=new Date(k), +r.setDate(1),p(r,1),z(r,-1),f&&f>r)){--h;p(G,1);r=void 0;continue}C.querySelector(".pmu-month").textContent=l;var t=function(a){return"range"==c.mode&&a>=(new Date(e[0])).getFullYear()&&a<=(new Date(e[1])).getFullYear()||"multiple"==c.mode&&-1!==e.reduce(function(a,b){a.push((new Date(b)).getFullYear());return a},[]).indexOf(a)||(new Date(e)).getFullYear()==a},u=function(a,b){var d=(new Date(e[0])).getFullYear(),k=(new Date(e[1])).getFullYear(),g=(new Date(e[0])).getMonth(),f=(new Date(e[1])).getMonth(); +return"range"==c.mode&&(a>d&&ad&&a==k&&b<=f||a==d&&a=g||a==d&&a==k&&b>=g&&b<=f)||"multiple"==c.mode&&-1!==e.reduce(function(a,b){b=new Date(b);a.push(b.getFullYear()+"-"+b.getMonth());return a},[]).indexOf(a+"-"+b)||(new Date(e)).getFullYear()==a&&(new Date(e)).getMonth()==b};(function(){var a=[],b=k.getFullYear()-6,d=(new Date(c.min)).getFullYear(),e=(new Date(c.max)).getFullYear(),f,h,l;for(l=0;12>l;++l)f=b+l,h=document.createElement("div"),h.textContent=f,h.__pickmeup_year=f,c.min&& +fe?g(h,"pmu-disabled"):t(f)&&g(h,"pmu-selected"),a.push(h);C.appendChild(c.instance_content_template(a,"pmu-years"))})();(function(){var a=[],b=k.getFullYear(),d=(new Date(c.min)).getFullYear(),e=(new Date(c.min)).getMonth(),f=(new Date(c.max)).getFullYear(),h=(new Date(c.max)).getMonth(),l,n;for(l=0;12>l;++l)n=document.createElement("div"),n.textContent=c.locales[c.locale].monthsShort[l],n.__pickmeup_month=l,n.__pickmeup_year=b,c.min&&(bf||l>h&&b>=f)?g(n,"pmu-disabled"): +u(b,l)&&g(n,"pmu-selected"),a.push(n);C.appendChild(c.instance_content_template(a,"pmu-months"))})();(function(){var a=[],b=k.getMonth(),d=w(new Date).valueOf(),e,f,h,l,n,m;(function(){k.setDate(1);var a=(k.getDay()-c.first_day)%7;z(k,-(a+(0>a?7:0)))})();for(e=0;42>e;++e)f=document.createElement("div"),f.textContent=k.getDate(),f.__pickmeup_day=k.getDate(),f.__pickmeup_month=k.getMonth(),f.__pickmeup_year=k.getFullYear(),b!=k.getMonth()&&g(f,"pmu-not-in-month"),0==k.getDay()?g(f,"pmu-sunday"):6== +k.getDay()&&g(f,"pmu-saturday"),h=c.render(new Date(k))||{},l=w(new Date(k)).valueOf(),n=c.min&&c.min>k||c.max&&c.max=c.date[0]&&l<=c.date[1],h.disabled||!("disabled"in h)&&n?g(f,"pmu-disabled"):(h.selected||!("selected"in h)&&m)&&g(f,"pmu-selected"),l==d&&g(f,"pmu-today"),h.class_name&&h.class_name.split(" ").forEach(g.bind(f,f)),a.push(f),z(k,1);C.appendChild(c.instance_content_template(a, +"pmu-days"))})()}r.setDate(1);q.setDate(1);p(q,1);z(q,-1);d=b.querySelector(".pmu-prev");b=b.querySelector(".pmu-next");d&&(d.style.visibility=c.min&&c.min>=r?"hidden":"visible");b&&(b.style.visibility=c.max&&c.max<=q?"hidden":"visible");B(a,"fill")}function u(a,b){var c=b.format,d=b.separator,e=b.locales[b.locale];if(a instanceof Date||a instanceof Number)return w(new Date(a));if(!a)return w(new Date);if(a instanceof Array){a=a.slice();for(c=0;cn?2E3:1900;break;case "H":case "I":case "k":case "l":k=parseInt(a[c],10);break;case "P":case "p":/pm/i.test(a[c])&&12>k?k+=12:/am/i.test(a[c])&&12<=k&&(k-=12);break;case "M":l=parseInt(a[c],10)}e=new Date(void 0===n?m.getFullYear():n,void 0===f?m.getMonth():f,void 0===g?m.getDate():g,void 0===k?m.getHours():k,void 0===l?m.getMinutes():l,0);isNaN(1*e)&&(e=new Date);return w(e)}function w(a){a.setHours(0,0,0,0);return a}function D(a,b,c){var d=a.getMonth(),e=a.getDate(),g=a.getFullYear(), +f=a.getDay(),n=a.getHours(),k=12<=n,l=k?n-12:n,m;m=new Date(a.getFullYear(),a.getMonth(),a.getDate(),0,0,0);var r=new Date(a.getFullYear(),0,0,0,0,0);m=Math.floor((m-r)/24*36E5);0==l&&(l=12);var r=a.getMinutes(),q=a.getSeconds();b=b.split("");for(var h,p=0;pe?"0"+e:e;break;case "e":h=e;break;case "H":h= +10>n?"0"+n:n;break;case "I":h=10>l?"0"+l:l;break;case "j":h=100>m?10>m?"00"+m:"0"+m:m;break;case "k":h=n;break;case "l":h=l;break;case "m":h=9>d?"0"+(1+d):1+d;break;case "M":h=10>r?"0"+r:r;break;case "p":case "P":h=k?"PM":"AM";break;case "s":h=Math.floor(a.getTime()/1E3);break;case "S":h=10>q?"0"+q:q;break;case "u":h=f+1;break;case "w":h=f;break;case "y":h=(""+g).substr(2,2);break;case "Y":h=g}b[p]=h}return b.join("")}function O(a,b){var c=a.__pickmeup.options,d;w(b);a:{var e;switch(c.mode){case "multiple":e= +b.valueOf();for(d=0;df+k&&(l=pos.top-c.offsetHeight);lg+n&&(b=pos.left-c.offsetWidth);ba?new Date(b):c&&c= 12); var ir = (pm) ? (hr - 12) : hr; @@ -907,7 +906,7 @@ value; if (force || dom_has_class(root_element, 'pmu-hidden')) { var options = target.__pickmeup.options, - pos = dom_offset(target), + position = dom_offset(target), viewport = { l : window.pageXOffset, t : window.pageYOffset, @@ -938,34 +937,42 @@ return; } if (!options.flat) { - switch (options.position) { - case 'top': - top -= root_element.offsetHeight; - break; - case 'left': - left -= root_element.offsetWidth; - break; - case 'right': - left += target.offsetWidth; - break; - case 'bottom': - top += target.offsetHeight; - break; - } - if (top + root_element.offsetHeight > viewport.t + viewport.h) { - top = pos.top - root_element.offsetHeight; - } - if (top < viewport.t) { - top = pos.top + target.offsetHeight; - } - if (left + root_element.offsetWidth > viewport.l + viewport.w) { - left = pos.left - root_element.offsetWidth; - } - if (left < viewport.l) { - left = pos.left + target.offsetWidth + if (options.position instanceof Function) { + position = options.position.call(target); + left = position.left; + top = position.top; + } else { + switch (options.position) { + case 'top': + top -= root_element.offsetHeight; + break; + case 'left': + left -= root_element.offsetWidth; + break; + case 'right': + left += target.offsetWidth; + break; + case 'bottom': + top += target.offsetHeight; + break; + } + if (top + root_element.offsetHeight > viewport.t + viewport.h) { + top = pos.top - root_element.offsetHeight; + } + if (top < viewport.t) { + top = pos.top + target.offsetHeight; + } + if (left + root_element.offsetWidth > viewport.l + viewport.w) { + left = pos.left - root_element.offsetWidth; + } + if (left < viewport.l) { + left = pos.left + target.offsetWidth; + } + left += 'px'; + top += 'px'; } - root_element.style.top = top + 'px'; - root_element.style.left = left + 'px'; + root_element.style.left = left; + root_element.style.top = top; dom_remove_class(root_element, 'pmu-hidden'); setTimeout(function () { dom_on(target, document.documentElement, 'click', options.bound.hide); diff --git a/package.json b/package.json index 0ce8a86..64894aa 100644 --- a/package.json +++ b/package.json @@ -7,7 +7,7 @@ "date", "calendar" ], - "version" : "3.0.11", + "version" : "3.1.0", "homepage" : "https://github.com/nazar-pc/PickMeUp", "author" : "Nazar Mokrynskyi ", "repository" : { diff --git a/readme.md b/readme.md index ad4c1c4..5fc72f6 100644 --- a/readme.md +++ b/readme.md @@ -61,34 +61,34 @@ All options and events are the same. ## Configuration options -| Option | Value type | Default | Description | -|---------------------------|-----------------------------------|-----------------------------------|----------------------------------------------------------------------------------------------------------------------| -| date | array/number/object/string | new Date | Selected date after initialization. Can be single date string/object or array depending on selection mode | -| default_date | boolean | true | If `false` will keep empty value until date selected | -| current | number/object/string | date | Represents date that will be in the center of rendered calendar, defaults to `date` option's value | -| flat | boolean | false | Whatever if the date picker is appended to the element or triggered by an event | -| first_day | 0/1 | 1 | First day of week: 0 - Sunday, 1 - Monday | -| prev | string | ◀ | Previous button content | -| next | string | ▶ | Next button content | -| mode | single/multiple/range | single | Date selection mode | -| select_day | boolean | true | Allow or deny days selection | -| select_month | boolean | true | Allow or deny months selection | -| select_year | boolean | true | Allow or deny year selection | -| view | days/months/years | days | View mode after initialization | -| calendars | int | 1 | Number of calendars, that will be rendered | -| format | string | d-m-Y | Date format (aAbBCdeHIjklmMpPsSuwyY are supported) | -| title_format | string | B, Y | Date format for calendar title in days view (aAbBCdeHIjklmMpPsSuwyY are supported) | -| position | top/right/bottom/left | bottom | Date picker's position relative to the triggered element | -| class_name | string | | Class to be added to root datepicker element | -| hide_on_select | boolean | false | If `true` - datepicker will be hidden after selection (for range mode allows to select first and last days) | -| min | number/object/string | | Min date available for selection | -| max | number/object/string | | Max date available for selection | -| separator | string | ` - ` | Is used for joining separate dates in multiple mode and first/last dates in range mode | -| locale | string | en | String, that specifies current locale. | -| locales | object | see [Localization](#localization) | Key-value object, where keys are locales and values contain localized days of week names and months | -| render | function | | Executed for each day element rendering, takes date argument, allows to select, disable or add class to element | -| instance_template | function | (look at source code) | Responsible for rendering simple PickMeUp instance with header and days of weeks | -| instance_content_template | function | (look at source code) | Responsible for rendering instance content container (which contains years, months or days) | +| Option | Value type | Default | Description | +|---------------------------|-----------------------------------|-----------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------| +| date | array/number/object/string | new Date | Selected date after initialization. Can be single date string/object or array depending on selection mode | +| default_date | boolean | true | If `false` will keep empty value until date selected | +| current | number/object/string | date | Represents date that will be in the center of rendered calendar, defaults to `date` option's value | +| flat | boolean | false | Whatever if the date picker is appended to the element or triggered by an event | +| first_day | 0/1 | 1 | First day of week: 0 - Sunday, 1 - Monday | +| prev | string | ◀ | Previous button content | +| next | string | ▶ | Next button content | +| mode | single/multiple/range | single | Date selection mode | +| select_day | boolean | true | Allow or deny days selection | +| select_month | boolean | true | Allow or deny months selection | +| select_year | boolean | true | Allow or deny year selection | +| view | days/months/years | days | View mode after initialization | +| calendars | int | 1 | Number of calendars, that will be rendered | +| format | string | d-m-Y | Date format (aAbBCdeHIjklmMpPsSuwyY are supported) | +| title_format | string | B, Y | Date format for calendar title in days view (aAbBCdeHIjklmMpPsSuwyY are supported) | +| position | top/right/bottom/left/function | bottom | Date picker's position relative to the triggered element, if function - must return an object with `left` and `top` keys and include units | +| class_name | string | | Class to be added to root datepicker element | +| hide_on_select | boolean | false | If `true` - datepicker will be hidden after selection (for range mode allows to select first and last days) | +| min | number/object/string | | Min date available for selection | +| max | number/object/string | | Max date available for selection | +| separator | string | ` - ` | Is used for joining separate dates in multiple mode and first/last dates in range mode | +| locale | string | en | String, that specifies current locale. | +| locales | object | see [Localization](#localization) | Key-value object, where keys are locales and values contain localized days of week names and months | +| render | function | | Executed for each day element rendering, takes date argument, allows to select, disable or add class to element | +| instance_template | function | (look at source code) | Responsible for rendering simple PickMeUp instance with header and days of weeks | +| instance_content_template | function | (look at source code) | Responsible for rendering instance content container (which contains years, months or days) | ##### Selecting/disabling dates with custom logic `render` options might return object with any of following keys: