notification-js
Version:
A dependency-free, well designed and highly customizable notification library.
12 lines • 16.1 kB
JavaScript
/*!
* Notification.js
*
* A well designed, highly customizable and lightweigth notification library.
*
* @author Dominique Müller <dominique.m.mueller@gmail.com>
* @copyright Dominique Müller 2015
* @license MIT <http://opensource.org/licenses/MIT>
* @link Github <https://github.com/dominique-mueller/notification-js>
* @version 1.0.0
*/
!function(a,b){"use strict";"function"==typeof define&&define.amd?define(b):"object"==typeof module&&module.exports?module.exports=b():a.notification=b()}(this,function(){"use strict";!function(a){function b(a,b){b=b||{bubbles:!1,cancelable:!1,detail:void 0};var c=document.createEvent("CustomEvent");return c.initCustomEvent(a,b.bubbles,b.cancelable,b.detail),c}b.prototype=a.Event.prototype,a.CustomEvent=b}(window);var a={success:'<svg viewBox="0 0 24 24" height="24" width="24" xmlns="http://www.w3.org/2000/svg"><polyline points="4,12.5 9,17.5 20,6.5" fill="none" stroke="#FFF" stroke-width="2" stroke-dasharray="23" /></svg>',error:'<svg viewBox="0 0 24 24" height="24" width="24" xmlns="http://www.w3.org/2000/svg"><line x1="6" y1="6" x2="18" y2="18" stroke="#FFF" stroke-width="2" stroke-dasharray="17" /><line x1="6" y1="18" x2="18" y2="6" stroke="#FFF" stroke-width="2" stroke-dasharray="17" /></svg>'},b=function(){var a={global:{notification:{position:["left","bottom"],distances:[20,20,10],height:60,maxWidth:!1,roundCorners:[1,1,1,1],color:"#555"},symbol:{visible:!1,resource:!1,roundCorners:!1,color:"rgba(0,0,0,.1)"},message:{visible:!0,color:"#FFF",textSize:14},dismiss:{visible:!0,color:"#FFF",text:!1},behaviour:{autoHide:5,onMouseover:"pause",stacking:!0,limit:!0,htmlMode:!1},animations:{enabled:!0,duration:[.75,.75],easing:["ease","ease"]},callbacks:{onOpen:!1,onOpened:!1,onClose:!1,onClosed:!1,onDismiss:!1,onMouseenter:!1,onMouseleave:!1}},default:{notification:{color:"#555"}},info:{notification:{color:"#2574A9"}},success:{notification:{color:"#239D58"},symbol:{visible:!0}},error:{notification:{color:"#B9493E"},symbol:{visible:!0}},warning:{notification:{color:"#C7932F"}}},b=function(b){return a[b]},c=function(b){return a.hasOwnProperty(b)},d=function(b,c){for(var d in c){a[b].hasOwnProperty(d)||(a[b][d]={});for(var e in c[d])a[b][d][e]=c[d][e]}},e=function(b,c){a[b]="undefined"!=typeof c?c:{}},f=function(b){delete a[b]},g=function(b){a[b]={}},h=function(b,c){var d={};for(var e in a.global)d[e]=i(a.global[e],a[b][e],c[e]);return d},i=function(){for(var a=arguments.length,b={},c=a-1;c>0;c--)"undefined"==typeof arguments[c]&&delete arguments[c];for(var d in arguments[0])for(var e=a-1;e>=0;e--)if("undefined"!=typeof arguments[e]&&arguments[e].hasOwnProperty(d)){b[d]=arguments[e][d];break}return b},j={get:b,check:c,config:d,add:e,remove:f,reset:g,combine:h};return j}(),c=function(a,c,d){this.profile="undefined"!=typeof b.get(a)?a:"default",this.message=c,this.options="undefined"!=typeof d?d:{},this.$components={},this.initialize()};c.instances=[],c.prototype.EVENTS={onOpen:new CustomEvent("notification.open"),onOpened:new CustomEvent("notification.opened"),onClose:new CustomEvent("notification.close"),onClosed:new CustomEvent("notification.closed"),onDismiss:new CustomEvent("notification.dismiss"),onMouseenter:new CustomEvent("notification.mouseenter"),onMouseleave:new CustomEvent("notification.mouseleave")},c.prototype.initialize=function(){var c=this;if(c.options=b.combine(c.profile,c.options),!c.options.symbol.resource)switch(c.profile){case"success":c.options.symbol.resource=a.success;break;case"error":c.options.symbol.resource=a.error;break;default:c.options.symbol.visible=!1}},c.prototype.build=function(b){function c(){var a=document.createElement("div"),b=j.position[0],c=j.position[1],d=j.distances[0],e=j.distances[1],f=j.height,g=j.roundCorners;switch(b){case"left":a.style.left=d+"px",a.style.marginRight=d+"px";break;case"right":a.style.right=d+"px",a.style.marginLeft=d+"px";break;case"middle":a.style.left="50%",a.style.webkitTransform="translateX(-50%)",a.style.transform="translateX(-50%)"}switch(c){case"top":a.style.top=e+"px";break;case"bottom":a.style.bottom=e+"px"}return k.visible&&(a.style.paddingLeft=f+"px"),g&&g[0]+g[1]+g[2]+g[3]>0&&(a.style.borderRadius=g.join("px ")+"px"),m.visible&&!m.text&&(a.style.paddingRight=f-20+"px"),j.maxWidth&&(a.style.maxWidth=j.maxWidth+"px"),a.classList.add("notification"),a.classList.add("notification-"+h.profile),a}function d(){var a=document.createElement("div"),b=j.height/2,c=j.color;return a.style.left="calc(-100% + "+b+"px)",a.style.backgroundColor=c,a.classList.add("notification-background"),a}function e(){var a,b=j.height,c=k.resource,d=k.roundCorners,e=k.color;if(null!==c.match(/^<svg.*>.*<\/svg>$/i)||"function"==typeof c){if("function"==typeof c){if(a=c(),"undefined"==typeof a||"svg"!==a.nodeName.toLowerCase())throw new Error("The custom notification symbol is not valid svg.")}else a=(new DOMParser).parseFromString(c,"image/svg+xml").childNodes[0];a.setAttributeNS(null,"width","24"),a.setAttributeNS(null,"height","24"),d&&d[0]+d[1]+d[2]+d[3]>0?a.style.padding=b/2-17+"px":a.style.padding=b/2-12+"px",e&&(a.style.backgroundColor=e)}else a=document.createElement("div"),a.style.backgroundImage='url("'+c+'")',a.style.backgroundPosition="center",a.style.backgroundSize="cover",a.style.backgroundRepeat="no-repeat";return d&&d[0]+d[1]+d[2]+d[3]>0?(a.style.left="5px",a.style.height=b-10+"px",a.style.width=b-10+"px",a.style.borderRadius=d.join("px ")+"px"):(a.style.left="0",a.style.height="100%",a.style.width=b+"px"),a.setAttributeNS(null,"class","notification-symbol notification-symbol-"+h.profile),a}function f(){var a=document.createElement("p"),b=l.color,c=l.textSize,d=Math.round(1.7*c),e=Math.round(j.height/2.75),f=Math.round((j.height-d)/2);return n.htmlMode?a.innerHTML=h.message:a.textContent=h.message,a.style.color=b,a.style.fontSize=c+"px",a.style.lineHeight=d+"px",a.style.padding=f+"px "+e+"px",a.classList.add("notification-message"),a}function g(){var b=document.createElement("button"),c=j.height,d=m.color,e=m.text;if(b.setAttribute("type","button"),b.setAttribute("title","dismiss this notification"),b.style.height=c-20+"px",b.style.padding=c/2-18+"px",e)b.textContent=e,b.style.color=d,b.style.fontSize="12px",b.style.lineHeight="16px";else{var f=(new DOMParser).parseFromString(a.error,"image/svg+xml").childNodes[0];f.setAttributeNS(null,"width","16"),f.setAttributeNS(null,"height","16"),b.appendChild(f),b.style.width=c-20+"px"}return b.classList.add("notification-btn"),b}var h=this,i=document.createDocumentFragment(),j=h.options.notification,k=h.options.symbol,l=h.options.message,m=h.options.dismiss,n=h.options.behaviour;h.$components.notification=c(),h.$components.background=d(),h.$components.notification.appendChild(h.$components.background),k.visible&&(h.$components.symbol=e(),h.$components.notification.appendChild(h.$components.symbol)),l.visible&&(h.$components.message=f(),h.$components.notification.appendChild(h.$components.message)),m.visible&&(h.$components.button=g(),h.$components.notification.appendChild(h.$components.button)),i.appendChild(h.$components.notification),document.body.appendChild(i),m.visible&&m.text&&(h.$components.notification.style.paddingRight=h.$components.button.offsetWidth+"px"),h.next(b)},c.prototype.prepare=function(a){var b=this;if(c.instances.length)if(b.options.behaviour.stacking){var d,e=b.options.behaviour.limit,f=c.instances.length,g=b.$components.notification.offsetHeight;if(e===!0||0>e){var h=b.options.notification,i=h.height,j=h.distances[1],k=h.distances[2],l=g+2*j+f*k;c.instances.forEach(function(a){l+=a.$components.notification.offsetHeight}),0>e&&(l-=(i+k)*e),d=l>window.innerHeight?!0:!1}else d=e!==!1&&0!==e&&f===e?!0:!1;d?c.instances[0].close(function(){b.shift(c.instances,"up",g,function(){b.next(a)})}):b.shift(c.instances,"up",g,function(){b.next(a)})}else c.instances[0].close(function(){b.next(a)});else b.next(a)},c.prototype.open=function(a){var b=this;c.instances.push(b),document.dispatchEvent(b.EVENTS.onOpen),"function"==typeof b.options.callbacks.onOpen&&b.options.callbacks.onOpen(),b.animate("in",function(){document.dispatchEvent(b.EVENTS.onOpened),"function"==typeof b.options.callbacks.onOpened&&b.options.callbacks.onOpened(),b.next(a)})},c.prototype.wait=function(a){var b=this;if(b.options.behaviour.autoHide){var c=new d(1e3*b.options.behaviour.autoHide,function(){b.next(a)});b.options.behaviour.onMouseover&&(b.$components.notification.addEventListener("mouseenter",function(){switch(document.dispatchEvent(b.EVENTS.onMouseenter),"function"==typeof b.options.callbacks.onMouseenter&&b.options.callbacks.onMouseenter(),b.options.behaviour.onMouseover){case"pause":c.pause();break;case"reset":c.stop()}}),b.$components.notification.addEventListener("mouseleave",function(){document.dispatchEvent(b.EVENTS.onMouseleave),"function"==typeof b.options.callbacks.onMouseleave&&b.options.callbacks.onMouseleave(),c.resume()}))}b.options.dismiss.visible&&b.$components.button.addEventListener("click",function d(e){e.target.removeEventListener(e.type,d),document.dispatchEvent(b.EVENTS.onDismiss),"function"==typeof b.options.callbacks.onDismiss&&b.options.callbacks.onDismiss(),b.options.behaviour.autoHide&&c.stop(),b.next(a)})},c.prototype.close=function(a){var b=this;document.dispatchEvent(b.EVENTS.onClose),"function"==typeof b.options.callbacks.onClose&&b.options.callbacks.onClose(),b.animate("out",function(){if(document.dispatchEvent(b.EVENTS.onClosed),"function"==typeof b.options.callbacks.onClosed&&b.options.callbacks.onClosed(),b.options.behaviour.stacking&&c.instances.length-1){var d=c.instances.indexOf(b),e=b.$components.notification.offsetHeight;b.shift(c.instances.slice(0,d),"down",e,function(){c.instances.splice(d,1),b.next(a)})}else c.instances=[],b.next(a);document.body.removeChild(b.$components.notification)})},c.prototype.animate=function(a,b){function c(){return d.$components.notification.offsetWidth}var d=this,e=d.options.animations.duration[0],f=d.options.animations.duration[1],g=d.options.animations.easing;switch(a){case"in":d.options.animations.enabled&&(d.$components.notification.style.transition="box-shadow "+e/1.5+"s "+g[0]+" "+e/1.5+"s, opacity "+e+"s "+g[0],d.$components.background.style.transition="transform "+e+"s "+g[0],d.options.symbol.visible&&(d.$components.symbol.style.transition="opacity "+e+"s "+g[0]),d.options.message.visible&&(d.$components.message.style.transition="transform "+e+"s "+g[0]+", opacity "+e+"s "+g[0]),d.options.dismiss.visible&&(d.$components.button.style.transition="opacity "+e/1.5+"s "+g[0]+" "+e/1.5+"s")),c(),d.$components.notification.classList.add("is-visible");break;case"out":d.options.animations.enabled&&(d.$components.notification.style.transition="box-shadow "+f+"s "+g[1]+", opacity "+f+"s "+g[1],d.$components.background.style.transition="transform 0s linear "+f+"s",d.options.symbol.visible&&(d.$components.symbol.style.transition="opacity 0s linear "+f+"s"),d.options.message.visible&&(d.$components.message.style.transition="transform 0s linear "+f+"s, opacity 0s linear "+f+"s"),d.options.dismiss.visible&&(d.$components.button.style.transition="opacity 0s linear "+f+"s")),c(),d.$components.notification.classList.remove("is-visible")}d.options.animations.enabled?d.$components.notification.addEventListener("transitionend",function a(){d.$components.notification.removeEventListener("transitionend",a),d.next(b)}):d.next(b)},c.prototype.shift=function(a,b,d,e){function f(){var a=i.options.animations,b=new Date,c=a.enabled?(b-j)/(1e3*a.duration[0]/1.5):1;1>c?(g(h(c)),requestAnimationFrame(f)):(g(1),i.next(e))}function g(a){for(var e,f,g,h=k-1;h>=0;h--){if(h!==k-1)e+=p[h+1]+m;else if("up"===b)e=0;else{e=d+m;for(var i=l-1;i>k;i--)e+=p[i]+m}f=e+a*(d+m)*("up"===b?1:-1),g="translate("+n+", "+o+f+"px)",c.instances[h].$components.notification.style.webkitTransform=g,c.instances[h].$components.notification.style.transform=g}}function h(a){return.5>a?2*a*a:-1+(4-2*a)*a}var i=this;if(a.length){for(var j=new Date,k=a.length,l=c.instances.length,m=i.options.notification.distances[2],n="middle"===i.options.notification.position[0]?"-50%":"0",o="top"===i.options.notification.position[1]?"+":"-",p=[],q=l-1;q>=0;q--)p[q]=c.instances[q].$components.notification.offsetHeight;requestAnimationFrame(f)}else i.next(e)},c.prototype.next=function(a){"function"==typeof a&&a()};var d=function(a,b){this.duration=a,this.remaining=a,this.callback=b,this.resume()};d.prototype.resume=function(){this.now=new Date,this.timerId=window.setTimeout(this.callback,this.remaining)},d.prototype.pause=function(){window.clearTimeout(this.timerId),this.remaining-=new Date-this.now},d.prototype.stop=function(){window.clearTimeout(this.timerId),this.remaining=this.duration};var e={notify:function(a,b,d){var e=new c(a,b,d);e.build(function(){e.prepare(function(){e.open(function(){e.wait(function(){e.close()})})})})},on:function(a,b){if("undefined"==typeof a||"undefined"==typeof b)throw new Error("Adding an event listener requires an event name and a callback function.");if(-1===c.EVENTS.indexOf(a))throw new Error("An event with the name <"+a+"> does not exist.");document.addEventListener("notification."+a,b)},off:function(a,b){if("undefined"==typeof a||"undefined"==typeof b)throw new Error("Removing an event listener requires an event name and a callback function.");if(-1===c.EVENTS.indexOf(a))throw new Error("An event with the name <"+a+"> does not exist.");document.removeEventListener("notification."+a,b)},clearAll:function(){function a(a){var b={};switch(a.length){case 0:b.offset=.15,b.callback=void 0;break;case 1:b.offset="function"==typeof a[0]?.15:a[0],b.callback="function"==typeof a[0]?a[0]:void 0;break;default:b.offset=a[0],b.callback=a[1]}return b}function b(a){var b=c.instances[a];setTimeout(function(){a===e-1&&"undefined"!=typeof d.callback?b.close(d.callback):b.close()},a*d.offset*1e3)}if(c.instances.length)for(var d=a(arguments),e=c.instances.length,f=e-1;f>=0;f--)d.offset?b(f):f||"undefined"==typeof d.callback?c.instances[f].close():c.instances[f].close(d.callback)},clearOldest:function(a){if(c.instances.length){var b=c.instances[0];"undefined"!=typeof a?b.close(a):b.close()}},clearNewest:function(a){if(c.instances.length){var b=c.instances[c.instances.length-1];"undefined"!=typeof a?b.close(a):b.close()}},getProfile:function(a){if("undefined"==typeof a)throw new Error("Getting the options of a notification profile requires a profile name.");if(b.check(a))return b.get(a);throw new Error("A notification profile with the name <"+a+"> does not exist.")},checkProfile:function(a){if("undefined"==typeof a)throw new Error("Checking if a notification profile exists required a profile name.");return b.check(a)},configProfile:function(a,c){if("undefined"==typeof a||"undefined"==typeof c)throw new Error("Configuring a notification profile requires a profile name and an options object.");if(!b.check(a))throw new Error("A notification profile with the name <"+a+"> does not exist.");b.config(a,c)},addProfile:function(a,c){if("undefined"==typeof a)throw new Error("Adding a new notification profile requires at least a profile name.");if(b.check(a))throw new Error("A notification profile with the name <"+a+"> does not exist.");b.add(a,c)},removeProfile:function(a){if("undefined"==typeof a)throw new Error("Removing a notification profile requires a profile name.");if(-1!==["global","default","info","success","error","warning"].indexOf(a))throw new Error("The profile <"+a+"> is locked and cannot be removed.");if(!b.check(a))throw new Error("A notification profile with the name <"+a+"> does not exist.");b.remove(a)},resetProfile:function(a){if("undefined"==typeof a)throw new Error("Resetting a notification profile requires a profile name.");if(-1!==["global","default","info","success","error","warning"].indexOf(a))throw new Error("The profile <"+a+"> is locked and cannot be reset.");if(!b.check(a))throw new Error("A notification profile with the name <"+a+"> does not exist.");b.reset(a)}};return e});