This commit is contained in:
Jaime Pillora
2013-05-30 16:35:16 +10:00
parent 04ad20dda3
commit aa7d387776
4 changed files with 176 additions and 79 deletions
+76 -40
View File
@@ -1,23 +1,29 @@
/** Notify.js - v0.0.1 - 2013/05/29 /** Notify.js - v0.0.1 - 2013/05/30
* http://notifyjs.com/ * http://notifyjs.com/
* Copyright (c) 2013 Jaime Pillora - MIT * Copyright (c) 2013 Jaime Pillora - MIT
*/ */
(function(window,document,undefined) { (function(window,document,undefined) {
'use strict'; 'use strict';
var Notification, className, cornerElem, createElem, getAnchorElement, hPositions, inherit, insertCSS, parsePosition, pluginName, pluginOptions, styles, vPositions; var Notification, className, cornerElem, createElem, getAnchorElement, incr, inherit, insertCSS, opposites, parsePosition, pluginName, pluginOptions, positions, styles;
pluginName = 'notify'; pluginName = 'notify';
className = '__' + pluginName; className = '__' + pluginName;
vPositions = { positions = {
t: 'b', t: 'top',
m: null, m: 'middle',
b: 't' b: 'bottom',
l: 'left',
c: 'center',
r: 'right'
}; };
hPositions = { opposites = {
t: 'b',
m: null,
b: 't',
l: 'r', l: 'r',
c: null, c: null,
r: 'l' r: 'l'
@@ -28,11 +34,8 @@ parsePosition = function(str) {
pos = []; pos = [];
$.each(str.split(/\W+/), function(i, word) { $.each(str.split(/\W+/), function(i, word) {
var w; var w;
w = word.toLowerCase()[0]; w = word.toLowerCase().charAt(0);
if (vPositions[w]) { if (positions[w]) {
pos.push(w);
}
if (hPositions[w]) {
return pos.push(w); return pos.push(w);
} }
}); });
@@ -42,11 +45,11 @@ parsePosition = function(str) {
styles = { styles = {
core: { core: {
html: "<div class=\"" + className + "Wrapper\">\n <div class=\"" + className + "Arrow\"></div>\n <div class=\"" + className + "Container\"></div>\n</div>", html: "<div class=\"" + className + "Wrapper\">\n <div class=\"" + className + "Arrow\"></div>\n <div class=\"" + className + "Container\"></div>\n</div>",
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 opacity: 0.85;\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 margin-top: 2px;\n position: absolute;\n z-index: 2;\n margin-left: 10px;\n width: 0;\n height: 0;\n}\n" 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 border: thin solid red;\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 margin-top: 2px;\n position: absolute;\n z-index: 2;\n margin-left: 10px;\n width: 0;\n height: 0;\n}\n"
}, },
user: { user: {
"default": { "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>", 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}" 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}"
}, },
bootstrap: { bootstrap: {
@@ -65,7 +68,7 @@ pluginOptions = {
arrowShow: false, arrowShow: false,
arrowSize: 5, arrowSize: 5,
position: 'bottom', position: 'bottom',
style: null, style: 'default',
color: 'red', color: 'red',
colors: { colors: {
red: '#b94a48', red: '#b94a48',
@@ -105,17 +108,49 @@ getAnchorElement = function(element) {
return element; return element;
}; };
incr = function(obj, pos, val, useOpposite) {
var opp, temp;
if (useOpposite == null) {
useOpposite = true;
}
if (typeof val === 'string') {
val = parseInt(val, 10);
} else if (typeof val !== 'number') {
return;
}
if (isNaN(val)) {
return;
}
opp = positions[opposites[pos.charAt(0)]];
temp = pos;
if (obj[opp] !== undefined) {
if (!useOpposite) {
return;
}
pos = positions[opp.charAt(0)];
val *= -1;
}
if (obj[pos] === undefined) {
obj[pos] = val;
} else {
obj[pos] += val;
}
console.log("incr (" + opp + ">>" + temp + ") " + pos + " by " + val);
return null;
};
insertCSS = function(style) { insertCSS = function(style) {
var elem; var elem;
if (!(style && style.css)) { if (!(style && style.css)) {
return; return;
} }
elem = style.cssElem; elem = style.cssElem;
if (!elem) { if (elem) {
elem = createElem("style"); return;
$("head").append(elem);
style.cssElem = elem;
} }
elem = createElem("style");
$("head").append(elem);
style.cssElem = elem;
try { try {
return elem.html(style.css); return elem.html(style.css);
} catch (e) { } catch (e) {
@@ -166,9 +201,9 @@ Notification = (function() {
var style; var style;
style = this.getStyle(); style = this.getStyle();
this.userContainer = $(style.html); this.userContainer = $(style.html);
this.text = this.userContainer.find('[data-notify=text]'); this.text = this.userContainer.find('[data-notify-text]');
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");
}; };
@@ -197,34 +232,36 @@ Notification = (function() {
}; };
Notification.prototype.updatePosition = function() { Notification.prototype.updatePosition = function() {
var elementPosition, mainPosition, p, position; var elementPosition, p, position, wrapperPosition;
if (!this.elem) { if (!this.elem) {
return; return;
} }
elementPosition = this.elem.position(); elementPosition = this.elem.position();
mainPosition = this.wrapper.position(); wrapperPosition = this.wrapper.position();
position = this.getPosition(); position = this.getPosition();
p = { console.log(this.elem[0]);
top: 0, console.log("update position", position, " elem ", elementPosition, " main ", wrapperPosition);
left: 0 p = {};
}; switch (position[0]) {
switch (position) { case 'b':
case 'bottom': incr(p, 'top', this.elem.outerHeight());
p.top += this.elem.outerHeight();
break; break;
case 'right': case 't':
p.left += this.elem.width(); incr(p, 'bottom', 0);
break;
case 'l':
incr(p, 'right', 0);
break;
case 'r':
incr(p, 'left', this.elem.outerWidth());
break; break;
default: default:
throw "Unknown position: " + position; throw "Unknown position: " + position;
} }
if (!navigator.userAgent.match(/MSIE/)) { if (!navigator.userAgent.match(/MSIE/)) {
p.top += elementPosition.top - mainPosition.top; incr(p, 'top', elementPosition.top - wrapperPosition.top);
} }
p.left += elementPosition.left - mainPosition.left; incr(p, 'left', elementPosition.left - wrapperPosition.left);
p.top += this.options.offsetY;
p.left += this.options.offsetX;
this.updateArrow(p, position);
return this.container.css(p); return this.container.css(p);
}; };
@@ -283,9 +320,6 @@ Notification = (function() {
if (!name) { if (!name) {
name = this.options.style; name = this.options.style;
} }
if (bootstrapDetected && !name) {
name = 'bootstrap';
}
if (!name) { if (!name) {
name = 'default'; name = 'default';
} }
@@ -387,6 +421,8 @@ $[pluginName].styles = function(s) {
return $.extend(true, styles.user, 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;
+2 -2
View File
File diff suppressed because one or more lines are too long
+17 -3
View File
@@ -6,7 +6,18 @@
<style type="text/css"> <style type="text/css">
.box { padding: 30px; } .boxes {
margin: 150px;
}
.box {
padding: 10px;
margin: 10px;
border: thin solid blue;
width: 100px;
}
.wrapper {
margin-top: 50px
}
</style> </style>
<div class="boxes"></div> <div class="boxes"></div>
@@ -19,8 +30,11 @@
$.each(positions, function(i, p) { $.each(positions, function(i, p) {
var box = $("<div class=\"box\">"+p+"</div>"); var box = $("<div class=\"box\">"+p+"</div>");
boxes.append(box); boxes.append($("<div class=\"wrapper\"/>").append(box));
box.notify(p, {pos: p});
setTimeout(function() {
box.notify(p, {position: p});
}, 500)
}); });
</script> </script>
+81 -34
View File
@@ -5,12 +5,19 @@
pluginName = 'notify' pluginName = 'notify'
className = '__'+pluginName className = '__'+pluginName
positions =
t: 'top'
m: 'middle'
b: 'bottom'
l: 'left'
c: 'center'
r: 'right'
#positions mapped to opposites #positions mapped to opposites
vPositions = opposites =
t: 'b' t: 'b'
m: null m: null
b: 't' b: 't'
hPositions =
l: 'r' l: 'r'
c: null c: null
r: 'l' r: 'l'
@@ -18,9 +25,8 @@ hPositions =
parsePosition = (str) -> parsePosition = (str) ->
pos = [] pos = []
$.each str.split(/\W+/), (i,word) -> $.each str.split(/\W+/), (i,word) ->
w = word.toLowerCase()[0] w = word.toLowerCase().charAt(0)
pos.push w if vPositions[w] pos.push w if positions[w]
pos.push w if hPositions[w]
pos pos
#built-in styles #built-in styles
@@ -55,7 +61,7 @@ styles =
display: inline-block; display: inline-block;
height: 0; height: 0;
width: 0; width: 0;
opacity: 0.85; border: thin solid red;
} }
.#{className}Container { .#{className}Container {
@@ -87,7 +93,7 @@ styles =
color: {{color}}; color: {{color}};
border-color: {{color}}; border-color: {{color}};
"> ">
<span data-notify="text"></span> <span data-notify-text></span>
</div> </div>
""" """
css: """ css: """
@@ -134,7 +140,7 @@ pluginOptions =
arrowSize: 5 arrowSize: 5
position: 'bottom' position: 'bottom'
# Default style # Default style
style: null style: 'default'
# Default color # Default color
color: 'red' color: 'red'
# Color mappings # Color mappings
@@ -154,7 +160,8 @@ pluginOptions =
#parents: { '.ui-dialog': 5001 } #parents: { '.ui-dialog': 5001 }
# plugin helpers # plugin helpers
createElem = (tag) -> $ "<#{tag}></#{tag}>" createElem = (tag) ->
$ "<#{tag}></#{tag}>"
inherit = (a, b) -> inherit = (a, b) ->
F = () -> F = () ->
F.prototype = a F.prototype = a
@@ -173,13 +180,41 @@ getAnchorElement = (element) ->
#custom-styled inputs - find thier real element #custom-styled inputs - find thier real element
element element
incr = (obj, pos, val, useOpposite = true) ->
# console.log "incr ---- #{pos} #{val} (#{typeof val})"
if typeof val is 'string'
val = parseInt val, 10
else if typeof val isnt 'number'
return
return if isNaN val
opp = positions[opposites[pos.charAt(0)]]
temp = pos
#use the opposite if exists
if obj[opp] isnt `undefined`
return unless useOpposite
pos = positions[opp.charAt(0)]
val *= -1
if obj[pos] is `undefined`
obj[pos] = val
else
obj[pos] += val
console.log "incr (#{opp}>>#{temp}) #{pos} by #{val}"
null
insertCSS = (style) -> insertCSS = (style) ->
return unless style and style.css return unless style and style.css
elem = style.cssElem elem = style.cssElem
unless elem return if elem
elem = createElem("style") elem = createElem("style")
$("head").append elem $("head").append elem
style.cssElem = elem style.cssElem = elem
try try
elem.html style.css elem.html style.css
@@ -230,9 +265,9 @@ class Notification
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) ->
@@ -261,32 +296,43 @@ class Notification
return unless @elem return unless @elem
# #
elementPosition = @elem.position() elementPosition = @elem.position()
mainPosition = @wrapper.position() wrapperPosition = @wrapper.position()
# #
position = @getPosition() position = @getPosition()
console.log @elem[0]
console.log "update position", position, " elem ", elementPosition, " main ", wrapperPosition
#start calculations #start calculations
p = p = {}
top: 0 switch position[0]
left: 0 when 'b'
switch position incr p, 'top', @elem.outerHeight()
when 'bottom' when 't'
p.top += @elem.outerHeight() incr p, 'bottom', 0
when 'right' when 'l'
p.left += @elem.width() incr p, 'right', 0
when 'r'
incr p, 'left', @elem.outerWidth()
else else
throw "Unknown position: #{position}" throw "Unknown position: #{position}"
#elem vs wrapper corrections #elem vs wrapper corrections
p.top += (elementPosition.top - mainPosition.top) unless navigator.userAgent.match /MSIE/ unless navigator.userAgent.match /MSIE/
p.left += elementPosition.left - mainPosition.left incr p, 'top', (elementPosition.top - wrapperPosition.top)
#set user offset incr p, 'left', elementPosition.left - wrapperPosition.left
p.top += @options.offsetY
p.left += @options.offsetX # console.log "corrent margin"
# for pos in ['top','right','bottom','left']
# incr p, pos, @elem.css("margin-#{pos}"), false
@updateArrow p, position #set user offset
# p.top += @options.offsetY
# p.left += @options.offsetX
# @updateArrow p, position
# if @setCSS # if @setCSS
# @container.stop().animate(p) # @container.stop().animate(p)
@@ -344,7 +390,6 @@ class Notification
getStyle: (name) -> getStyle: (name) ->
name = @options.style unless name name = @options.style unless name
name = 'bootstrap' if bootstrapDetected and not name
name = 'default' unless name name = 'default' unless name
style = styles.user[name] style = styles.user[name]
throw "Missing style: #{name}" unless style throw "Missing style: #{name}" unless style
@@ -379,7 +424,6 @@ class Notification
else else
@text.empty().append(data) @text.empty().append(data)
@updatePosition() @updatePosition()
@show true @show true
@@ -438,13 +482,16 @@ $[pluginName].options = (options) ->
$[pluginName].styles = (s) -> $[pluginName].styles = (s) ->
$.extend true, styles.user, s $.extend true, styles.user, s
$[pluginName].insertCSS = insertCSS
# $( ... ).pluginName( { .. } ) creates a cached instance on each # $( ... ).pluginName( { .. } ) creates a cached instance on each
$.fn[pluginName] = (data, options) -> $.fn[pluginName] = (data, options) ->
$(@).each -> $(@).each ->
inst = getAnchorElement($(@)).data className inst = getAnchorElement($(@)).data(className)
if inst if inst
inst.run data, options inst.run data, options
else else
new Notification $(@), data, options new Notification $(@), data, options
@ @