new style api

This commit is contained in:
Jaime Pillora
2013-06-03 12:28:03 +10:00
parent d0838b4c6d
commit 37631df657
3 changed files with 344 additions and 303 deletions
+124 -114
View File
@@ -5,12 +5,12 @@
(function(window,document,undefined) { (function(window,document,undefined) {
'use strict'; 'use strict';
var Notification, className, cornerElem, createElem, getAnchorElement, hAligns, incr, inherit, insertCSS, mainPositions, opposites, parsePosition, pluginName, pluginOptions, positions, realign, styles, vAligns, var Notification, addStyle, className, coreStyle, cornerElem, createElem, defaultStyle, defaultStyleName, getAnchorElement, hAligns, incr, inherit, insertCSS, mainPositions, opposites, options, parsePosition, pluginName, pluginOptions, positions, realign, styles, vAligns,
__indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; }; __indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; };
pluginName = 'notify'; pluginName = 'notify';
className = '__' + pluginName; className = pluginName + 'js';
positions = { positions = {
t: 'top', t: 'top',
@@ -49,40 +49,74 @@ parsePosition = function(str) {
return pos; return pos;
}; };
styles = { styles = {};
core: {
html: "<div class=\"" + className + "Wrapper\">\n <div class=\"" + className + "Arrow\"></div>\n <div class=\"" + className + "Container\"></div>\n</div>", coreStyle = {
css: "." + className + "Corner {\n position: fixed;\n top: 0;\n right: 0;\n margin: 5px;\n z-index: 1050;\n}\n\n." + className + "Corner ." + className + "Wrapper,\n." + className + "Corner ." + className + "Container {\n position: relative;\n display: block;\n height: inherit;\n width: inherit;\n}\n\n." + className + "Wrapper {\n z-index: 1;\n position: absolute;\n display: inline-block;\n height: 0;\n width: 0;\n}\n\n." + className + "Container {\n display: none;\n z-index: 1;\n position: absolute;\n cursor: pointer;\n}\n\n." + className + "Text {\n position: relative;\n}\n\n." + className + "Arrow {\n position: absolute;\n z-index: 2;\n width: 0;\n height: 0;\n}\n" name: 'core',
}, html: "<div class=\"" + className + "-wrapper\">\n <div class=\"" + className + "-arrow\"></div>\n <div class=\"" + className + "-container\"></div>\n</div>",
user: { css: "." + className + "-corner {\n position: fixed;\n top: 0;\n right: 0;\n margin: 5px;\n z-index: 1050;\n}\n\n." + className + "-corner ." + className + "-wrapper,\n." + className + "-corner ." + className + "-container {\n position: relative;\n display: block;\n height: inherit;\n width: inherit;\n}\n\n." + className + "-wrapper {\n z-index: 1;\n position: absolute;\n display: inline-block;\n height: 0;\n width: 0;\n}\n\n." + className + "-container {\n display: none;\n z-index: 1;\n position: absolute;\n cursor: pointer;\n}\n\n." + className + "-text {\n position: relative;\n}\n\n." + className + "-arrow {\n position: absolute;\n z-index: 2;\n width: 0;\n height: 0;\n}"
"default": { };
html: "<div class=\"" + className + "Default\" \n data-notify-style=\"\n color: {{color}}; \n border-color: {{color}};\n \">\n <span data-notify-text></span>\n </div>",
css: "." + className + "Default {\n background: #fff;\n font-size: 11px;\n box-shadow: 0 0 6px #000;\n -moz-box-shadow: 0 0 6px #000;\n -webkit-box-shadow: 0 0 6px #000;\n padding: 4px 10px 4px 8px;\n border-radius: 6px;\n border-style: solid;\n border-width: 2px;\n -moz-border-radius: 6px;\n -webkit-border-radius: 6px;\n white-space: nowrap;\n}" defaultStyleName = "bootstrap";
},
bootstrap: { defaultStyle = {
html: "<div class=\"alert alert-error " + className + "Bootstrap\">\n <strong data-notify-text></strong>\n</div>", html: "<div>\n <span data-notify-text></span>\n</div>",
css: "." + className + "Bootstrap {\n white-space: nowrap;\n margin: 5px !important;\n padding-left: 25px !important;\n background-repeat: no-repeat;\n background-position: 3px 7px;\n background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAtRJREFUeNqkVc1u00AQHq+dOD+0poIQfkIjalW0SEGqRMuRnHos3DjwAH0ArlyQeANOOSMeAA5VjyBxKBQhgSpVUKKQNGloFdw4cWw2jtfMOna6JOUArDTazXi/b3dm55socPqQhFka++aHBsI8GsopRJERNFlY88FCEk9Yiwf8RhgRyaHFQpPHCDmZG5oX2ui2yilkcTT1AcDsbYC1NMAyOi7zTX2Agx7A9luAl88BauiiQ/cJaZQfIpAlngDcvZZMrl8vFPK5+XktrWlx3/ehZ5r9+t6e+WVnp1pxnNIjgBe4/6dAysQc8dsmHwPcW9C0h3fW1hans1ltwJhy0GxK7XZbUlMp5Ww2eyan6+ft/f2FAqXGK4CvQk5HueFz7D6GOZtIrK+srupdx1GRBBqNBtzc2AiMr7nPplRdKhb1q6q6zjFhrklEFOUutoQ50xcX86ZlqaZpQrfbBdu2R6/G19zX6XSgh6RX5ubyHCM8nqSID6ICrGiZjGYYxojEsiw4PDwMSL5VKsC8Yf4VRYFzMzMaxwjlJSlCyAQ9l0CW44PBADzXhe7xMdi9HtTrdYjFYkDQL0cn4Xdq2/EAE+InCnvADTf2eah4Sx9vExQjkqXT6aAERICMewd/UAp/IeYANM2joxt+q5VI+ieq2i0Wg3l6DNzHwTERPgo1ko7XBXj3vdlsT2F+UuhIhYkp7u7CarkcrFOCtR3H5JiwbAIeImjT/YQKKBtGjRFCU5IUgFRe7fF4cCNVIPMYo3VKqxwjyNAXNepuopyqnld602qVsfRpEkkz+GFL1wPj6ySXBpJtWVa5xlhpcyhBNwpZHmtX8AGgfIExo0ZpzkWVTBGiXCSEaHh62/PoR0p/vHaczxXGnj4bSo+G78lELU80h1uogBwWLf5YlsPmgDEd4M236xjm+8nm4IuE/9u+/PH2JXZfbwz4zw1WbO+SQPpXfwG/BBgAhCNZiSb/pOQAAAAASUVORK5CYII=);\n}", classes: {
colors: { base: "padding: 8px 35px 8px 14px;\ntext-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);\nbackground-color: #fcf8e3;\nborder: 1px solid #fbeed5;\n-webkit-border-radius: 4px;\n-moz-border-radius: 4px;\nborder-radius: 4px;\nwhite-space: nowrap;",
red: '#eed3d7' error: "color: #B94A48;\nbackground-color: #F2DEDE;\nborder-color: #EED3D7;\npadding-left: 25px;\nbackground-repeat: no-repeat;\nbackground-position: 3px 7px;\nbackground-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAtRJREFUeNqkVc1u00AQHq+dOD+0poIQfkIjalW0SEGqRMuRnHos3DjwAH0ArlyQeANOOSMeAA5VjyBxKBQhgSpVUKKQNGloFdw4cWw2jtfMOna6JOUArDTazXi/b3dm55socPqQhFka++aHBsI8GsopRJERNFlY88FCEk9Yiwf8RhgRyaHFQpPHCDmZG5oX2ui2yilkcTT1AcDsbYC1NMAyOi7zTX2Agx7A9luAl88BauiiQ/cJaZQfIpAlngDcvZZMrl8vFPK5+XktrWlx3/ehZ5r9+t6e+WVnp1pxnNIjgBe4/6dAysQc8dsmHwPcW9C0h3fW1hans1ltwJhy0GxK7XZbUlMp5Ww2eyan6+ft/f2FAqXGK4CvQk5HueFz7D6GOZtIrK+srupdx1GRBBqNBtzc2AiMr7nPplRdKhb1q6q6zjFhrklEFOUutoQ50xcX86ZlqaZpQrfbBdu2R6/G19zX6XSgh6RX5ubyHCM8nqSID6ICrGiZjGYYxojEsiw4PDwMSL5VKsC8Yf4VRYFzMzMaxwjlJSlCyAQ9l0CW44PBADzXhe7xMdi9HtTrdYjFYkDQL0cn4Xdq2/EAE+InCnvADTf2eah4Sx9vExQjkqXT6aAERICMewd/UAp/IeYANM2joxt+q5VI+ieq2i0Wg3l6DNzHwTERPgo1ko7XBXj3vdlsT2F+UuhIhYkp7u7CarkcrFOCtR3H5JiwbAIeImjT/YQKKBtGjRFCU5IUgFRe7fF4cCNVIPMYo3VKqxwjyNAXNepuopyqnld602qVsfRpEkkz+GFL1wPj6ySXBpJtWVa5xlhpcyhBNwpZHmtX8AGgfIExo0ZpzkWVTBGiXCSEaHh62/PoR0p/vHaczxXGnj4bSo+G78lELU80h1uogBwWLf5YlsPmgDEd4M236xjm+8nm4IuE/9u+/PH2JXZfbwz4zw1WbO+SQPpXfwG/BBgAhCNZiSb/pOQAAAAASUVORK5CYII=);",
} info: "",
} warn: ""
} }
}; };
addStyle = function(name, def) {
var cssText;
if (styles[name]) {
alert("" + pluginName + ": style '" + name + "' already defined");
return;
}
def.name = name;
styles[name] = def;
if (def.cssElem) {
return;
}
cssText = "";
if (def.classes) {
$.each(def.classes, function(subClassName, css) {
return cssText += "." + className + "-" + def.name + "-" + subClassName + " {\n " + css + "\n}\n";
});
}
if (def.css) {
cssText += "/* styles for " + def.name + " */\n" + def.css;
}
if (!cssText) {
return;
}
def.cssElem = insertCSS(cssText);
return def.cssElem.attr('data-notify-style', def.name);
};
insertCSS = function(cssText) {
var elem;
elem = createElem("style");
$("head").append(elem);
try {
elem.html(cssText);
} catch (e) {
elem[0].styleSheet.cssText = cssText;
}
return elem;
};
pluginOptions = { pluginOptions = {
autoHide: false, autoHide: false,
autoHideDelay: 2000, autoHideDelay: 2000,
arrowShow: true, arrowShow: true,
arrowSize: 5, arrowSize: 5,
arrowColor: 'border',
position: 'bottom', position: 'bottom',
style: 'default', style: 'bootstrap',
color: 'black', cls: 'error',
colors: {
red: '#b94a48',
green: '#33be40',
black: '#393939',
blue: '#00f'
},
showAnimation: 'slideDown', showAnimation: 'slideDown',
showDuration: 400, showDuration: 400,
hideAnimation: 'slideUp', hideAnimation: 'slideUp',
@@ -91,10 +125,6 @@ pluginOptions = {
offsetX: 0 offsetX: 0
}; };
createElem = function(tag) {
return $("<" + tag + "></" + tag + ">");
};
inherit = function(a, b) { inherit = function(a, b) {
var F; var F;
F = function() {}; F = function() {};
@@ -102,7 +132,15 @@ inherit = function(a, b) {
return $.extend(true, new F(), b); return $.extend(true, new F(), b);
}; };
cornerElem = createElem("div").addClass("" + className + "Corner"); options = function(opts) {
return $.extend(pluginOptions, opts);
};
createElem = function(tag) {
return $("<" + tag + "></" + tag + ">");
};
cornerElem = createElem("div").addClass("" + className + "-corner");
getAnchorElement = function(element) { getAnchorElement = function(element) {
var radios; var radios;
@@ -150,25 +188,6 @@ realign = function(alignment, inner, outer) {
throw "Invalid alignment"; throw "Invalid alignment";
}; };
insertCSS = function(style) {
var elem;
if (!(style && style.css)) {
return;
}
elem = style.cssElem;
if (elem) {
return;
}
elem = createElem("style");
$("head").append(elem);
style.cssElem = elem;
try {
return elem.html(style.css);
} catch (e) {
return elem[0].styleSheet.cssText = style.css;
}
};
Notification = (function() { Notification = (function() {
function Notification(elem, data, options) { function Notification(elem, data, options) {
@@ -178,12 +197,11 @@ Notification = (function() {
}; };
} }
this.options = inherit(pluginOptions, $.isPlainObject(options) ? options : {}); this.options = inherit(pluginOptions, $.isPlainObject(options) ? options : {});
this.loadCSS();
this.loadHTML(); this.loadHTML();
this.wrapper = $(styles.core.html); this.wrapper = $(coreStyle.html);
this.wrapper.data(className, this); this.wrapper.data(className, this);
this.arrow = this.wrapper.find("." + className + "Arrow"); this.arrow = this.wrapper.find("." + className + "-arrow");
this.container = this.wrapper.find("." + className + "Container"); this.container = this.wrapper.find("." + className + "-container");
this.container.append(this.userContainer); this.container.append(this.userContainer);
if (elem && elem.length) { if (elem && elem.length) {
this.elementType = elem.attr('type'); this.elementType = elem.attr('type');
@@ -199,15 +217,6 @@ Notification = (function() {
this.run(data); this.run(data);
} }
Notification.prototype.loadCSS = function(style) {
var name;
if (!style) {
name = this.options.style;
style = this.getStyle(name);
}
return insertCSS(style);
};
Notification.prototype.loadHTML = function() { Notification.prototype.loadHTML = function() {
var style; var style;
style = this.getStyle(); style = this.getStyle();
@@ -216,7 +225,7 @@ Notification = (function() {
if (this.text.length === 0) { if (this.text.length === 0) {
throw "style: " + name + " HTML is missing the: 'data-notify-text' attribute"; throw "style: " + name + " HTML is missing the: 'data-notify-text' attribute";
} }
return this.text.addClass("" + className + "Text"); return this.text.addClass("" + className + "-text");
}; };
Notification.prototype.show = function(show, callback) { Notification.prototype.show = function(show, callback) {
@@ -245,7 +254,7 @@ Notification = (function() {
}; };
Notification.prototype.updatePosition = function() { Notification.prototype.updatePosition = function() {
var arrowCss, arrowSize, color, contH, contW, css, elemH, elemIH, elemIW, elemPos, elemW, mainFull, margin, opp, oppFull, pAlign, pArrow, pMain, padding, pos, posFull, position, wrapPos, _i, _len; var arrowCss, arrowSize, color, contH, contW, css, elemH, elemIH, elemIW, elemPos, elemW, mainFull, margin, opp, oppFull, pAlign, pArrow, pMain, padding, pos, posFull, position, style, wrapPos, _i, _len;
if (!this.elem) { if (!this.elem) {
return; return;
} }
@@ -258,6 +267,7 @@ Notification = (function() {
contH = this.container.height(); contH = this.container.height();
contW = this.container.width(); contW = this.container.width();
position = this.getPosition(); position = this.getPosition();
console.log(position);
pMain = position[0]; pMain = position[0];
pAlign = position[1]; pAlign = position[1];
pArrow = position[2] || pAlign; pArrow = position[2] || pAlign;
@@ -279,6 +289,7 @@ Notification = (function() {
} }
incr(css, 'top', this.options.offsetY); incr(css, 'top', this.options.offsetY);
incr(css, 'left', this.options.offsetX); incr(css, 'left', this.options.offsetX);
style = this.getStyle();
if (!this.options.arrowShow) { if (!this.options.arrowShow) {
this.arrow.hide(); this.arrow.hide();
} else { } else {
@@ -290,7 +301,7 @@ Notification = (function() {
if (pos === opp) { if (pos === opp) {
continue; continue;
} }
color = posFull === mainFull ? this.getColor() : 'transparent'; color = posFull === mainFull ? 'black' : 'transparent';
arrowCss["border-" + posFull] = "" + arrowSize + "px solid " + color; arrowCss["border-" + posFull] = "" + arrowSize + "px solid " + color;
} }
incr(css, positions[opp], arrowSize); incr(css, positions[opp], arrowSize);
@@ -337,12 +348,6 @@ Notification = (function() {
throw "Not implemented"; throw "Not implemented";
}; };
Notification.prototype.getColor = function() {
var styleColors;
styleColors = this.getStyle().colors;
return (styleColors && styleColors[this.options.color]) || this.options.colors[this.options.color] || this.options.color;
};
Notification.prototype.getStyle = function(name) { Notification.prototype.getStyle = function(name) {
var style; var style;
if (!name) { if (!name) {
@@ -351,18 +356,26 @@ Notification = (function() {
if (!name) { if (!name) {
name = 'default'; name = 'default';
} }
style = styles.user[name]; style = styles[name];
if (!style) { if (!style) {
throw "Missing style: " + name; throw "Missing style: " + name;
} }
return style; return style;
}; };
Notification.prototype.updateStyle = function() { Notification.prototype.updateStyleClasses = function() {
var _this = this; var cls, style;
return this.wrapper.find('[data-notify-style]').each(function(i, e) { cls = ['base'];
return $(e).attr('style', $(e).attr('data-notify-style').replace(/\{\{\s*color\s*\}\}/ig, _this.getColor())); if ($.isArray(this.options.cls)) {
}); cls = cls.concat(this.options.cls);
} else if (this.options.cls) {
cls.push(this.options.cls);
}
style = this.getStyle();
cls = $.map(cls, function(n) {
return "" + className + "-" + style.name + "-" + n;
}).join(' ');
return this.userContainer.attr('class', cls);
}; };
Notification.prototype.run = function(data, options) { Notification.prototype.run = function(data, options) {
@@ -383,6 +396,7 @@ Notification = (function() {
} else { } else {
this.text.empty().append(data); this.text.empty().append(data);
} }
this.updateStyleClasses();
this.updatePosition(); this.updatePosition();
this.show(true); this.show(true);
if (this.options.autoHide) { if (this.options.autoHide) {
@@ -404,31 +418,6 @@ Notification = (function() {
})(); })();
$(function() {
$("body").append(cornerElem);
$("link").each(function() {
var bootstrapDetected, src;
src = $(this).attr('href');
if (src.match(/bootstrap/)) {
bootstrapDetected = true;
return false;
}
});
insertCSS(styles.core);
return $(document).on('click', "." + className + "Wrapper", function() {
var inst;
inst = $(this).data(className);
if (!inst) {
return;
}
if (inst.elem) {
return inst.show(false);
} else {
return inst.destroy();
}
});
});
$[pluginName] = function(elem, data, options) { $[pluginName] = function(elem, data, options) {
if ((elem && elem.nodeName) || elem.jquery) { if ((elem && elem.nodeName) || elem.jquery) {
$(elem)[pluginName](data, options); $(elem)[pluginName](data, options);
@@ -440,16 +429,6 @@ $[pluginName] = function(elem, data, options) {
return elem; return elem;
}; };
$[pluginName].options = function(options) {
return $.extend(pluginOptions, options);
};
$[pluginName].styles = function(s) {
return $.extend(true, styles.user, s);
};
$[pluginName].insertCSS = insertCSS;
$.fn[pluginName] = function(data, options) { $.fn[pluginName] = function(data, options) {
$(this).each(function() { $(this).each(function() {
var inst; var inst;
@@ -463,4 +442,35 @@ $.fn[pluginName] = function(data, options) {
return this; return this;
}; };
$.extend($[pluginName], {
options: options,
addStyle: addStyle
});
$(function() {
$("body").append(cornerElem);
$("link").each(function() {
var bootstrapDetected, src;
src = $(this).attr('href');
if (src.match(/bootstrap/)) {
bootstrapDetected = true;
return false;
}
});
insertCSS(coreStyle.css).attr('data-notify-style', 'core');
$[pluginName].addStyle(defaultStyleName, defaultStyle);
return $(document).on('click', "." + className + "-wrapper", function() {
var inst;
inst = $(this).data(className);
if (!inst) {
return;
}
if (inst.elem) {
return inst.show(false);
} else {
return inst.destroy();
}
});
});
}(window,document)); }(window,document));
+1 -1
View File
File diff suppressed because one or more lines are too long
+219 -188
View File
@@ -3,8 +3,11 @@
#plugin constants #plugin constants
pluginName = 'notify' pluginName = 'notify'
className = '__'+pluginName className = pluginName+'js'
# ================================
# POSITIONING
# ================================
positions = positions =
t: 'top' t: 'top'
@@ -32,109 +35,144 @@ parsePosition = (str) ->
pos.push w if positions[w] pos.push w if positions[w]
pos pos
#built-in styles # ================================
styles = # STYLES
core: # ================================
html: """ styles = {}
<div class="#{className}Wrapper">
<div class="#{className}Arrow"></div> coreStyle =
<div class="#{className}Container"></div> name: 'core'
</div> html: """
<div class="#{className}-wrapper">
<div class="#{className}-arrow"></div>
<div class="#{className}-container"></div>
</div>
"""
# <div class="#{className}Debug"></div>
# .#{className}Debug {
# position: absolute;
# border: 3px solid red;
# height: 0;
# width: 0;
# }
css: """
.#{className}-corner {
position: fixed;
top: 0;
right: 0;
margin: 5px;
z-index: 1050;
}
.#{className}-corner .#{className}-wrapper,
.#{className}-corner .#{className}-container {
position: relative;
display: block;
height: inherit;
width: inherit;
}
.#{className}-wrapper {
z-index: 1;
position: absolute;
display: inline-block;
height: 0;
width: 0;
}
.#{className}-container {
display: none;
z-index: 1;
position: absolute;
cursor: pointer;
}
.#{className}-text {
position: relative;
}
.#{className}-arrow {
position: absolute;
z-index: 2;
width: 0;
height: 0;
}
"""
defaultStyleName = "bootstrap"
defaultStyle =
html: """
<div>
<span data-notify-text></span>
</div>
"""
classes:
base: """
padding: 8px 35px 8px 14px;
text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);
background-color: #fcf8e3;
border: 1px solid #fbeed5;
-webkit-border-radius: 4px;
-moz-border-radius: 4px;
border-radius: 4px;
white-space: nowrap;
"""
error: """
color: #B94A48;
background-color: #F2DEDE;
border-color: #EED3D7;
padding-left: 25px;
background-repeat: no-repeat;
background-position: 3px 7px;
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAtRJREFUeNqkVc1u00AQHq+dOD+0poIQfkIjalW0SEGqRMuRnHos3DjwAH0ArlyQeANOOSMeAA5VjyBxKBQhgSpVUKKQNGloFdw4cWw2jtfMOna6JOUArDTazXi/b3dm55socPqQhFka++aHBsI8GsopRJERNFlY88FCEk9Yiwf8RhgRyaHFQpPHCDmZG5oX2ui2yilkcTT1AcDsbYC1NMAyOi7zTX2Agx7A9luAl88BauiiQ/cJaZQfIpAlngDcvZZMrl8vFPK5+XktrWlx3/ehZ5r9+t6e+WVnp1pxnNIjgBe4/6dAysQc8dsmHwPcW9C0h3fW1hans1ltwJhy0GxK7XZbUlMp5Ww2eyan6+ft/f2FAqXGK4CvQk5HueFz7D6GOZtIrK+srupdx1GRBBqNBtzc2AiMr7nPplRdKhb1q6q6zjFhrklEFOUutoQ50xcX86ZlqaZpQrfbBdu2R6/G19zX6XSgh6RX5ubyHCM8nqSID6ICrGiZjGYYxojEsiw4PDwMSL5VKsC8Yf4VRYFzMzMaxwjlJSlCyAQ9l0CW44PBADzXhe7xMdi9HtTrdYjFYkDQL0cn4Xdq2/EAE+InCnvADTf2eah4Sx9vExQjkqXT6aAERICMewd/UAp/IeYANM2joxt+q5VI+ieq2i0Wg3l6DNzHwTERPgo1ko7XBXj3vdlsT2F+UuhIhYkp7u7CarkcrFOCtR3H5JiwbAIeImjT/YQKKBtGjRFCU5IUgFRe7fF4cCNVIPMYo3VKqxwjyNAXNepuopyqnld602qVsfRpEkkz+GFL1wPj6ySXBpJtWVa5xlhpcyhBNwpZHmtX8AGgfIExo0ZpzkWVTBGiXCSEaHh62/PoR0p/vHaczxXGnj4bSo+G78lELU80h1uogBwWLf5YlsPmgDEd4M236xjm+8nm4IuE/9u+/PH2JXZfbwz4zw1WbO+SQPpXfwG/BBgAhCNZiSb/pOQAAAAASUVORK5CYII=);
"""
info: ""
warn: ""
addStyle = (name, def) ->
if styles[name]
alert "#{pluginName}: style '#{name}' already defined"
return
def.name = name
styles[name] = def
return if def.cssElem
cssText = ""
if def.classes
$.each def.classes, (subClassName, css) ->
cssText += """
.#{className}-#{def.name}-#{subClassName} {
#{css}
}\n
"""
if def.css
cssText += """
/* styles for #{def.name} */
#{def.css}
""" """
# <div class="#{className}Debug"></div> return unless cssText
def.cssElem = insertCSS cssText
def.cssElem.attr('data-notify-style', def.name)
# .#{className}Debug { insertCSS = (cssText) ->
# position: absolute; elem = createElem("style")
# border: 3px solid red; $("head").append elem
# height: 0; try
# width: 0; elem.html cssText
# } catch e #ie fix
elem[0].styleSheet.cssText = cssText
elem
css: """
.#{className}Corner {
position: fixed;
top: 0;
right: 0;
margin: 5px;
z-index: 1050;
}
.#{className}Corner .#{className}Wrapper, # ================================
.#{className}Corner .#{className}Container { # OPTIONS
position: relative; # ================================
display: block;
height: inherit;
width: inherit;
}
.#{className}Wrapper {
z-index: 1;
position: absolute;
display: inline-block;
height: 0;
width: 0;
}
.#{className}Container {
display: none;
z-index: 1;
position: absolute;
cursor: pointer;
}
.#{className}Text {
position: relative;
}
.#{className}Arrow {
position: absolute;
z-index: 2;
width: 0;
height: 0;
}
"""
user:
bootstrap:
html: """
<div>
<span data-notify-text></span>
</div>
"""
classes:
base: """
padding: 8px 35px 8px 14px;
margin-bottom: 20px;
text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);
background-color: #fcf8e3;
border: 1px solid #fbeed5;
-webkit-border-radius: 4px;
-moz-border-radius: 4px;
border-radius: 4px;
"""
error:
info:
warn:
bootstrap:
html: """
<div class="alert alert-error #{className}Bootstrap">
<strong data-notify-text></strong>
</div>
"""
css: """
.#{className}Bootstrap {
white-space: nowrap;
margin: 5px !important;
padding-left: 25px !important;
background-repeat: no-repeat;
background-position: 3px 7px;
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAtRJREFUeNqkVc1u00AQHq+dOD+0poIQfkIjalW0SEGqRMuRnHos3DjwAH0ArlyQeANOOSMeAA5VjyBxKBQhgSpVUKKQNGloFdw4cWw2jtfMOna6JOUArDTazXi/b3dm55socPqQhFka++aHBsI8GsopRJERNFlY88FCEk9Yiwf8RhgRyaHFQpPHCDmZG5oX2ui2yilkcTT1AcDsbYC1NMAyOi7zTX2Agx7A9luAl88BauiiQ/cJaZQfIpAlngDcvZZMrl8vFPK5+XktrWlx3/ehZ5r9+t6e+WVnp1pxnNIjgBe4/6dAysQc8dsmHwPcW9C0h3fW1hans1ltwJhy0GxK7XZbUlMp5Ww2eyan6+ft/f2FAqXGK4CvQk5HueFz7D6GOZtIrK+srupdx1GRBBqNBtzc2AiMr7nPplRdKhb1q6q6zjFhrklEFOUutoQ50xcX86ZlqaZpQrfbBdu2R6/G19zX6XSgh6RX5ubyHCM8nqSID6ICrGiZjGYYxojEsiw4PDwMSL5VKsC8Yf4VRYFzMzMaxwjlJSlCyAQ9l0CW44PBADzXhe7xMdi9HtTrdYjFYkDQL0cn4Xdq2/EAE+InCnvADTf2eah4Sx9vExQjkqXT6aAERICMewd/UAp/IeYANM2joxt+q5VI+ieq2i0Wg3l6DNzHwTERPgo1ko7XBXj3vdlsT2F+UuhIhYkp7u7CarkcrFOCtR3H5JiwbAIeImjT/YQKKBtGjRFCU5IUgFRe7fF4cCNVIPMYo3VKqxwjyNAXNepuopyqnld602qVsfRpEkkz+GFL1wPj6ySXBpJtWVa5xlhpcyhBNwpZHmtX8AGgfIExo0ZpzkWVTBGiXCSEaHh62/PoR0p/vHaczxXGnj4bSo+G78lELU80h1uogBwWLf5YlsPmgDEd4M236xjm+8nm4IuE/9u+/PH2JXZfbwz4zw1WbO+SQPpXfwG/BBgAhCNZiSb/pOQAAAAASUVORK5CYII=);
}
"""
colors:
red: '#eed3d7'
#overridable options #overridable options
pluginOptions = pluginOptions =
@@ -142,17 +180,11 @@ pluginOptions =
autoHideDelay: 2000 autoHideDelay: 2000
arrowShow: true arrowShow: true
arrowSize: 5 arrowSize: 5
arrowColor: 'border'
position: 'bottom' position: 'bottom'
# Default style # Default style
style: 'default' style: 'bootstrap'
# Default color cls: 'error'
color: 'black'
# Color mappings
colors:
red: '#b94a48'
green: '#33be40'
black: '#393939'
blue: '#00f'
showAnimation: 'slideDown' showAnimation: 'slideDown'
showDuration: 400 showDuration: 400
hideAnimation: 'slideUp' hideAnimation: 'slideUp'
@@ -163,16 +195,25 @@ pluginOptions =
#TODO add z-index watches #TODO add z-index watches
#parents: { '.ui-dialog': 5001 } #parents: { '.ui-dialog': 5001 }
# plugin helpers
createElem = (tag) ->
$ "<#{tag}></#{tag}>"
inherit = (a, b) -> inherit = (a, b) ->
F = () -> F = () ->
F.prototype = a F.prototype = a
$.extend true, new F(), b $.extend true, new F(), b
options = (opts) ->
$.extend pluginOptions, opts
# ================================
# DOM MANIPULATION
# ================================
# plugin helpers
createElem = (tag) ->
$ "<#{tag}></#{tag}>"
# container for element-less notifications # container for element-less notifications
cornerElem = createElem("div").addClass("#{className}Corner") cornerElem = createElem("div").addClass("#{className}-corner")
#gets first on n radios, and gets the fancy stylised input for hidden inputs #gets first on n radios, and gets the fancy stylised input for hidden inputs
getAnchorElement = (element) -> getAnchorElement = (element) ->
@@ -216,18 +257,10 @@ realign = (alignment, inner, outer) ->
outer - inner outer - inner
throw "Invalid alignment" throw "Invalid alignment"
insertCSS = (style) ->
return unless style and style.css
elem = style.cssElem
return if elem
elem = createElem("style")
$("head").append elem
style.cssElem = elem
try # ================================
elem.html style.css # NOTIFY CLASS
catch e #ie fix # ================================
elem[0].styleSheet.cssText = style.css
#define plugin #define plugin
class Notification class Notification
@@ -237,15 +270,13 @@ class Notification
options = {color: options} if typeof options is 'string' options = {color: options} if typeof options is 'string'
@options = inherit pluginOptions, if $.isPlainObject(options) then options else {} @options = inherit pluginOptions, if $.isPlainObject(options) then options else {}
#load user css into dom
@loadCSS()
#load user html into @userContainer #load user html into @userContainer
@loadHTML() @loadHTML()
@wrapper = $(styles.core.html) @wrapper = $(coreStyle.html)
@wrapper.data className, @ @wrapper.data className, @
@arrow = @wrapper.find ".#{className}Arrow" @arrow = @wrapper.find ".#{className}-arrow"
@container = @wrapper.find ".#{className}Container" @container = @wrapper.find ".#{className}-container"
@container.append @userContainer @container.append @userContainer
if elem and elem.length if elem and elem.length
@@ -263,20 +294,13 @@ class Notification
@container.hide() @container.hide()
@run(data) @run(data)
loadCSS: (style) ->
unless style
name = @options.style
style = @getStyle(name)
#insert
insertCSS style
loadHTML: -> loadHTML: ->
style = @getStyle() style = @getStyle()
@userContainer = $(style.html) @userContainer = $(style.html)
@text = @userContainer.find '[data-notify-text]' @text = @userContainer.find '[data-notify-text]'
if @text.length is 0 if @text.length is 0
throw "style: #{name} HTML is missing the: 'data-notify-text' attribute" throw "style: #{name} HTML is missing the: 'data-notify-text' attribute"
@text.addClass "#{className}Text" @text.addClass "#{className}-text"
show: (show, callback = $.noop) -> show: (show, callback = $.noop) ->
@@ -318,6 +342,8 @@ class Notification
#get user defined position #get user defined position
position = @getPosition() position = @getPosition()
console.log position
pMain = position[0] pMain = position[0]
pAlign = position[1] pAlign = position[1]
pArrow = position[2] or pAlign pArrow = position[2] or pAlign
@@ -347,6 +373,10 @@ class Notification
incr css, 'top', @options.offsetY incr css, 'top', @options.offsetY
incr css, 'left', @options.offsetX incr css, 'left', @options.offsetX
style = @getStyle()
# if style.css
#calculate arrow #calculate arrow
if not @options.arrowShow if not @options.arrowShow
@arrow.hide() @arrow.hide()
@@ -357,7 +387,7 @@ class Notification
for pos in mainPositions for pos in mainPositions
posFull = positions[pos] posFull = positions[pos]
continue if pos is opp continue if pos is opp
color = if posFull is mainFull then @getColor() else 'transparent' color = if posFull is mainFull then 'black' else 'transparent'
arrowCss["border-#{posFull}"] = "#{arrowSize}px solid #{color}" arrowCss["border-#{posFull}"] = "#{arrowSize}px solid #{color}"
#add some room for the arrow #add some room for the arrow
incr css, positions[opp], arrowSize incr css, positions[opp], arrowSize
@@ -385,7 +415,7 @@ class Notification
pos[0] = 'b' if pos.length is 0 pos[0] = 'b' if pos.length is 0
if pos[0] not in mainPositions if pos[0] not in mainPositions
throw "Must be one of [#{mainPositions}]" throw "Must be one of [#{mainPositions}]"
#validate alignment #validate alignment
if pos.length is 1 or if pos.length is 1 or
(pos[0] in vAligns and pos[1] not in hAligns) or (pos[0] in vAligns and pos[1] not in hAligns) or
@@ -400,27 +430,26 @@ class Notification
# return 'bottom' # return 'bottom'
throw "Not implemented" throw "Not implemented"
getColor: ->
styleColors = @getStyle().colors
return (styleColors and
styleColors[@options.color]) or
@options.colors[@options.color] or
@options.color
getStyle: (name) -> getStyle: (name) ->
name = @options.style unless name name = @options.style unless name
name = 'default' unless name name = 'default' unless name
style = styles.user[name] style = styles[name]
throw "Missing style: #{name}" unless style throw "Missing style: #{name}" unless style
style style
updateStyle: -> updateStyleClasses: ->
#update colors cls = ['base']
@wrapper.find('[data-notify-style]').each (i,e) =>
$(e).attr 'style', $(e).attr('data-notify-style'). if $.isArray @options.cls
replace(/\{\{\s*color\s*\}\}/ig, @getColor()) cls = cls.concat @options.cls
# . else if @options.cls
# replace(/\{\{\s*position\s*\}\}/ig, @getPosition()) cls.push @options.cls
style = @getStyle()
cls = $.map(cls, (n) -> "#{className}-#{style.name}-#{n}").join ' '
@userContainer.attr 'class', cls
#run plugin #run plugin
run: (data, options) -> run: (data, options) ->
@@ -443,6 +472,10 @@ class Notification
else else
@text.empty().append(data) @text.empty().append(data)
#set styles
@updateStyleClasses()
#position
@updatePosition() @updatePosition()
@show true @show true
@@ -458,6 +491,34 @@ class Notification
@show false, => @show false, =>
@wrapper.remove() @wrapper.remove()
# ================================
# API
# ================================
# $.pluginName( { ... } ) changes options for all instances
$[pluginName] = (elem, data, options) ->
if (elem and elem.nodeName) or elem.jquery
$(elem)[pluginName](data, options)
else
options = data
data = elem
new Notification null, data, options
elem
# $( ... ).pluginName( { .. } ) creates a cached instance on each
$.fn[pluginName] = (data, options) ->
$(@).each ->
inst = getAnchorElement($(@)).data(className)
if inst
inst.run data, options
else
new Notification $(@), data, options
@
#extra
$.extend $[pluginName], { options, addStyle }
#when ready #when ready
$ -> $ ->
#corner notification container #corner notification container
@@ -470,11 +531,13 @@ $ ->
bootstrapDetected = true bootstrapDetected = true
return false return false
#add core styles #insert default style
insertCSS styles.core insertCSS(coreStyle.css).attr('data-notify-style', 'core')
#insert default style
$[pluginName].addStyle(defaultStyleName, defaultStyle)
#watch all notifications clicks #watch all notifications clicks
$(document).on 'click', ".#{className}Wrapper", -> $(document).on 'click', ".#{className}-wrapper", ->
inst = $(@).data className inst = $(@).data className
return unless inst return unless inst
if inst.elem if inst.elem
@@ -482,35 +545,3 @@ $ ->
else else
inst.destroy() inst.destroy()
# publicise jquery plugin
# return alert "$.#{pluginName} already defined" if $[pluginName]?
# $.pluginName( { ... } ) changes options for all instances
$[pluginName] = (elem, data, options) ->
if (elem and elem.nodeName) or elem.jquery
$(elem)[pluginName](data, options)
else
options = data
data = elem
new Notification null, data, options
elem
# publicise methods
$[pluginName].options = (options) ->
$.extend pluginOptions, options
$[pluginName].styles = (s) ->
$.extend true, styles.user, s
$[pluginName].insertCSS = insertCSS
# $( ... ).pluginName( { .. } ) creates a cached instance on each
$.fn[pluginName] = (data, options) ->
$(@).each ->
inst = getAnchorElement($(@)).data(className)
if inst
inst.run data, options
else
new Notification $(@), data, options
@