2013-04-04 13:13:08 +11:00
|
|
|
|
|
|
|
|
'use strict'
|
|
|
|
|
|
|
|
|
|
#plugin constants
|
|
|
|
|
pluginName = 'notify'
|
2013-06-04 17:01:03 +10:00
|
|
|
pluginClassName = pluginName+'js'
|
2013-07-05 12:04:05 +10:00
|
|
|
blankFieldName = pluginName+"!blank"
|
2013-04-04 13:13:08 +11:00
|
|
|
|
2013-06-03 12:28:03 +10:00
|
|
|
# ================================
|
|
|
|
|
# POSITIONING
|
|
|
|
|
# ================================
|
2013-05-30 16:35:16 +10:00
|
|
|
|
2013-06-02 23:19:34 +10:00
|
|
|
positions =
|
2013-05-30 16:35:16 +10:00
|
|
|
t: 'top'
|
|
|
|
|
m: 'middle'
|
|
|
|
|
b: 'bottom'
|
|
|
|
|
l: 'left'
|
|
|
|
|
c: 'center'
|
|
|
|
|
r: 'right'
|
2013-06-03 09:15:58 +10:00
|
|
|
hAligns = ['l','c','r']
|
|
|
|
|
vAligns = ['t','m','b']
|
2013-05-31 13:18:43 +10:00
|
|
|
mainPositions = ['t','b','l','r']
|
2013-05-29 16:59:19 +10:00
|
|
|
#positions mapped to opposites
|
2013-05-30 16:35:16 +10:00
|
|
|
opposites =
|
2013-05-29 16:59:19 +10:00
|
|
|
t: 'b'
|
|
|
|
|
m: null
|
|
|
|
|
b: 't'
|
|
|
|
|
l: 'r'
|
|
|
|
|
c: null
|
|
|
|
|
r: 'l'
|
2013-04-04 13:13:08 +11:00
|
|
|
|
2013-05-29 16:59:19 +10:00
|
|
|
parsePosition = (str) ->
|
|
|
|
|
pos = []
|
|
|
|
|
$.each str.split(/\W+/), (i,word) ->
|
2013-05-30 16:35:16 +10:00
|
|
|
w = word.toLowerCase().charAt(0)
|
|
|
|
|
pos.push w if positions[w]
|
2013-05-29 16:59:19 +10:00
|
|
|
pos
|
|
|
|
|
|
2013-06-03 12:28:03 +10:00
|
|
|
# ================================
|
|
|
|
|
# STYLES
|
|
|
|
|
# ================================
|
|
|
|
|
styles = {}
|
|
|
|
|
|
|
|
|
|
coreStyle =
|
|
|
|
|
name: 'core'
|
|
|
|
|
html: """
|
2013-06-04 17:01:03 +10:00
|
|
|
<div class="#{pluginClassName}-wrapper">
|
|
|
|
|
<div class="#{pluginClassName}-arrow"></div>
|
|
|
|
|
<div class="#{pluginClassName}-container"></div>
|
2013-06-03 12:28:03 +10:00
|
|
|
</div>
|
|
|
|
|
"""
|
2013-06-06 14:03:15 +10:00
|
|
|
# <div class="#{pluginClassName}-debug"></div>
|
|
|
|
|
# .#{pluginClassName}-debug {
|
2013-06-03 12:28:03 +10:00
|
|
|
# position: absolute;
|
|
|
|
|
# border: 3px solid red;
|
|
|
|
|
# height: 0;
|
|
|
|
|
# width: 0;
|
|
|
|
|
# }
|
|
|
|
|
css: """
|
2013-06-04 17:01:03 +10:00
|
|
|
.#{pluginClassName}-corner {
|
2013-06-03 12:28:03 +10:00
|
|
|
position: fixed;
|
|
|
|
|
margin: 5px;
|
|
|
|
|
z-index: 1050;
|
|
|
|
|
}
|
|
|
|
|
|
2013-06-04 17:01:03 +10:00
|
|
|
.#{pluginClassName}-corner .#{pluginClassName}-wrapper,
|
|
|
|
|
.#{pluginClassName}-corner .#{pluginClassName}-container {
|
2013-06-03 12:28:03 +10:00
|
|
|
position: relative;
|
|
|
|
|
display: block;
|
|
|
|
|
height: inherit;
|
|
|
|
|
width: inherit;
|
2013-06-06 15:35:06 +10:00
|
|
|
margin: 3px;
|
2013-06-03 12:28:03 +10:00
|
|
|
}
|
|
|
|
|
|
2013-06-04 17:01:03 +10:00
|
|
|
.#{pluginClassName}-wrapper {
|
2013-06-03 12:28:03 +10:00
|
|
|
z-index: 1;
|
|
|
|
|
position: absolute;
|
|
|
|
|
display: inline-block;
|
|
|
|
|
height: 0;
|
|
|
|
|
width: 0;
|
|
|
|
|
}
|
|
|
|
|
|
2013-06-04 17:01:03 +10:00
|
|
|
.#{pluginClassName}-container {
|
2013-06-03 12:28:03 +10:00
|
|
|
display: none;
|
|
|
|
|
z-index: 1;
|
|
|
|
|
position: absolute;
|
|
|
|
|
cursor: pointer;
|
|
|
|
|
}
|
|
|
|
|
|
2013-07-05 12:04:05 +10:00
|
|
|
[data-notify-text],[data-notify-html] {
|
2013-06-03 12:28:03 +10:00
|
|
|
position: relative;
|
|
|
|
|
}
|
|
|
|
|
|
2013-06-04 17:01:03 +10:00
|
|
|
.#{pluginClassName}-arrow {
|
2013-06-03 12:28:03 +10:00
|
|
|
position: absolute;
|
|
|
|
|
z-index: 2;
|
|
|
|
|
width: 0;
|
|
|
|
|
height: 0;
|
|
|
|
|
}
|
|
|
|
|
"""
|
|
|
|
|
|
2013-06-04 17:01:03 +10:00
|
|
|
stylePrefixes =
|
|
|
|
|
"border-radius": ["-webkit-", "-moz-"]
|
2013-06-03 12:28:03 +10:00
|
|
|
|
2013-06-11 18:28:39 +10:00
|
|
|
getStyle = (name) ->
|
|
|
|
|
styles[name]
|
|
|
|
|
|
2013-06-03 12:28:03 +10:00
|
|
|
addStyle = (name, def) ->
|
2013-06-06 14:03:15 +10:00
|
|
|
|
2013-06-11 18:28:39 +10:00
|
|
|
unless name
|
|
|
|
|
throw "Missing Style name"
|
|
|
|
|
unless def
|
|
|
|
|
throw "Missing Style definition"
|
2013-07-05 12:04:05 +10:00
|
|
|
unless def.html
|
|
|
|
|
throw "Missing Style HTML"
|
2013-06-11 18:28:39 +10:00
|
|
|
|
2013-06-06 14:03:15 +10:00
|
|
|
if styles[name]?.cssElem
|
2013-06-05 13:17:20 +10:00
|
|
|
if window.console
|
|
|
|
|
console.warn "#{pluginName}: overwriting style '#{name}'"
|
2013-06-06 14:03:15 +10:00
|
|
|
styles[name].cssElem.remove()
|
2013-06-05 13:17:20 +10:00
|
|
|
|
2013-06-03 12:28:03 +10:00
|
|
|
def.name = name
|
|
|
|
|
styles[name] = def
|
|
|
|
|
|
|
|
|
|
cssText = ""
|
|
|
|
|
if def.classes
|
2013-06-04 17:01:03 +10:00
|
|
|
$.each def.classes, (className, props) ->
|
|
|
|
|
cssText += ".#{pluginClassName}-#{def.name}-#{className} {\n"
|
|
|
|
|
$.each props, (name, val) ->
|
|
|
|
|
#vendor prefixes
|
|
|
|
|
if stylePrefixes[name]
|
|
|
|
|
$.each stylePrefixes[name], (i, prefix) ->
|
|
|
|
|
cssText += " #{prefix}#{name}: #{val};\n"
|
|
|
|
|
#add prop
|
|
|
|
|
cssText += " #{name}: #{val};\n"
|
|
|
|
|
cssText += "}\n"
|
2013-06-03 12:28:03 +10:00
|
|
|
if def.css
|
|
|
|
|
cssText += """
|
|
|
|
|
/* styles for #{def.name} */
|
|
|
|
|
#{def.css}
|
2013-04-04 13:48:42 +11:00
|
|
|
"""
|
2013-06-03 09:15:58 +10:00
|
|
|
|
2013-07-05 12:04:05 +10:00
|
|
|
if cssText
|
|
|
|
|
def.cssElem = insertCSS cssText
|
|
|
|
|
def.cssElem.attr('id', "notify-#{def.name}")
|
|
|
|
|
|
|
|
|
|
#precompute usable text fields
|
|
|
|
|
fields = {}
|
|
|
|
|
elem = $(def.html)
|
|
|
|
|
findFields 'html', elem, fields
|
|
|
|
|
findFields 'text', elem, fields
|
|
|
|
|
def.fields = fields
|
2013-06-03 09:15:58 +10:00
|
|
|
|
2013-06-03 12:28:03 +10:00
|
|
|
insertCSS = (cssText) ->
|
2013-06-04 17:01:03 +10:00
|
|
|
|
2013-06-03 12:28:03 +10:00
|
|
|
elem = createElem("style")
|
2013-06-12 13:28:47 +10:00
|
|
|
elem.attr 'type', 'text/css'
|
2013-06-03 12:28:03 +10:00
|
|
|
$("head").append elem
|
|
|
|
|
try
|
|
|
|
|
elem.html cssText
|
|
|
|
|
catch e #ie fix
|
|
|
|
|
elem[0].styleSheet.cssText = cssText
|
|
|
|
|
elem
|
2013-06-03 09:15:58 +10:00
|
|
|
|
2013-07-05 12:04:05 +10:00
|
|
|
# style.html helper
|
|
|
|
|
findFields = (type, elem, fields) ->
|
|
|
|
|
type = 'text' if type isnt 'html'
|
|
|
|
|
attr = "data-notify-#{type}"
|
|
|
|
|
find(elem,"[#{attr}]").each ->
|
|
|
|
|
name = $(@).attr attr
|
|
|
|
|
name = blankFieldName unless name
|
|
|
|
|
fields[name] = type
|
|
|
|
|
|
|
|
|
|
find = (elem, selector) ->
|
|
|
|
|
if elem.is(selector) then elem else elem.find selector
|
2013-04-04 16:58:22 +11:00
|
|
|
|
2013-06-03 12:28:03 +10:00
|
|
|
# ================================
|
|
|
|
|
# OPTIONS
|
|
|
|
|
# ================================
|
2013-04-04 13:13:08 +11:00
|
|
|
|
|
|
|
|
#overridable options
|
|
|
|
|
pluginOptions =
|
2013-06-12 13:28:47 +10:00
|
|
|
clickToHide: true
|
2013-06-04 17:01:03 +10:00
|
|
|
autoHide: true
|
|
|
|
|
autoHideDelay: 5000
|
2013-05-31 13:18:43 +10:00
|
|
|
arrowShow: true
|
2013-04-04 13:13:08 +11:00
|
|
|
arrowSize: 5
|
2013-06-14 16:54:40 +10:00
|
|
|
breakNewLines: true
|
2013-06-21 09:44:21 +10:00
|
|
|
# autoReposition: true
|
2013-06-05 13:17:20 +10:00
|
|
|
elementPosition: 'bottom'
|
|
|
|
|
globalPosition: 'top right'
|
2013-06-03 12:28:03 +10:00
|
|
|
style: 'bootstrap'
|
2013-06-04 17:01:03 +10:00
|
|
|
className: 'error'
|
2013-04-04 16:58:22 +11:00
|
|
|
showAnimation: 'slideDown'
|
2013-04-05 11:53:48 +11:00
|
|
|
showDuration: 400
|
2013-04-04 16:58:22 +11:00
|
|
|
hideAnimation: 'slideUp'
|
2013-04-05 11:53:48 +11:00
|
|
|
hideDuration: 200
|
2013-06-06 14:03:15 +10:00
|
|
|
gap: 5
|
2013-04-04 13:13:08 +11:00
|
|
|
|
2013-04-05 11:53:48 +11:00
|
|
|
inherit = (a, b) ->
|
|
|
|
|
F = () ->
|
|
|
|
|
F.prototype = a
|
|
|
|
|
$.extend true, new F(), b
|
2013-04-04 13:13:08 +11:00
|
|
|
|
2013-06-05 13:17:20 +10:00
|
|
|
defaults = (opts) ->
|
2013-06-03 12:28:03 +10:00
|
|
|
$.extend pluginOptions, opts
|
|
|
|
|
|
|
|
|
|
# ================================
|
|
|
|
|
# DOM MANIPULATION
|
|
|
|
|
# ================================
|
|
|
|
|
|
|
|
|
|
# plugin helpers
|
|
|
|
|
createElem = (tag) ->
|
|
|
|
|
$ "<#{tag}></#{tag}>"
|
|
|
|
|
|
2013-06-06 14:03:15 +10:00
|
|
|
# references to global anchor positions
|
|
|
|
|
globalAnchors = {}
|
2013-04-04 16:58:22 +11:00
|
|
|
|
|
|
|
|
#gets first on n radios, and gets the fancy stylised input for hidden inputs
|
2013-04-04 13:13:08 +11:00
|
|
|
getAnchorElement = (element) ->
|
|
|
|
|
#choose the first of n radios
|
|
|
|
|
if element.is('[type=radio]')
|
|
|
|
|
radios = element.parents('form:first').find('[type=radio]').filter (i, e) ->
|
|
|
|
|
$(e).attr('name') is element.attr('name')
|
|
|
|
|
element = radios.first()
|
|
|
|
|
#custom-styled inputs - find thier real element
|
|
|
|
|
element
|
|
|
|
|
|
2013-05-31 13:18:43 +10:00
|
|
|
incr = (obj, pos, val) ->
|
2013-05-30 16:35:16 +10:00
|
|
|
# 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
|
|
|
|
|
|
2013-06-02 23:19:34 +10:00
|
|
|
opp = positions[opposites[pos.charAt(0)]]
|
2013-05-30 16:35:16 +10:00
|
|
|
temp = pos
|
|
|
|
|
|
|
|
|
|
#use the opposite if exists
|
|
|
|
|
if obj[opp] isnt `undefined`
|
|
|
|
|
pos = positions[opp.charAt(0)]
|
2013-06-06 14:03:15 +10:00
|
|
|
val = -val
|
2013-05-30 16:35:16 +10:00
|
|
|
|
|
|
|
|
if obj[pos] is `undefined`
|
|
|
|
|
obj[pos] = val
|
|
|
|
|
else
|
|
|
|
|
obj[pos] += val
|
|
|
|
|
null
|
|
|
|
|
|
2013-05-31 13:18:43 +10:00
|
|
|
realign = (alignment, inner, outer) ->
|
|
|
|
|
return if alignment in ['l','t']
|
|
|
|
|
0
|
|
|
|
|
else if alignment in ['c','m']
|
|
|
|
|
outer/2 - inner/2
|
|
|
|
|
else if alignment in ['r','b']
|
|
|
|
|
outer - inner
|
|
|
|
|
throw "Invalid alignment"
|
|
|
|
|
|
2013-06-14 16:54:40 +10:00
|
|
|
encode = (text) ->
|
|
|
|
|
encode.e = encode.e or createElem "div"
|
|
|
|
|
encode.e.text(text).html()
|
2013-04-05 11:53:48 +11:00
|
|
|
|
2013-06-03 12:28:03 +10:00
|
|
|
# ================================
|
|
|
|
|
# NOTIFY CLASS
|
|
|
|
|
# ================================
|
2013-04-16 15:57:38 +10:00
|
|
|
|
2013-04-04 13:13:08 +11:00
|
|
|
#define plugin
|
2013-04-04 16:58:22 +11:00
|
|
|
class Notification
|
2013-06-02 23:19:34 +10:00
|
|
|
|
2013-04-04 13:13:08 +11:00
|
|
|
#setup instance variables
|
2013-04-04 16:58:22 +11:00
|
|
|
constructor: (elem, data, options) ->
|
2013-06-04 17:01:03 +10:00
|
|
|
options = {className: options} if typeof options is 'string'
|
2013-04-05 11:53:48 +11:00
|
|
|
@options = inherit pluginOptions, if $.isPlainObject(options) then options else {}
|
2013-04-04 13:48:42 +11:00
|
|
|
|
2013-06-06 14:03:15 +10:00
|
|
|
#load style html into @userContainer
|
2013-04-04 13:48:42 +11:00
|
|
|
@loadHTML()
|
|
|
|
|
|
2013-06-03 12:28:03 +10:00
|
|
|
@wrapper = $(coreStyle.html)
|
2013-06-04 17:01:03 +10:00
|
|
|
@wrapper.data pluginClassName, @
|
|
|
|
|
@arrow = @wrapper.find ".#{pluginClassName}-arrow"
|
|
|
|
|
@container = @wrapper.find ".#{pluginClassName}-container"
|
2013-04-04 14:02:55 +11:00
|
|
|
@container.append @userContainer
|
2013-04-04 13:13:08 +11:00
|
|
|
|
2013-04-04 16:58:22 +11:00
|
|
|
if elem and elem.length
|
|
|
|
|
@elementType = elem.attr('type')
|
|
|
|
|
@originalElement = elem
|
|
|
|
|
@elem = getAnchorElement(elem)
|
2013-06-04 17:01:03 +10:00
|
|
|
@elem.data pluginClassName, @
|
2013-04-04 16:58:22 +11:00
|
|
|
# add into dom above elem
|
|
|
|
|
@elem.before @wrapper
|
2013-04-04 13:13:08 +11:00
|
|
|
|
2013-04-04 16:58:22 +11:00
|
|
|
@container.hide()
|
|
|
|
|
@run(data)
|
2013-04-04 13:13:08 +11:00
|
|
|
|
2013-04-11 17:22:27 +10:00
|
|
|
loadHTML: ->
|
|
|
|
|
style = @getStyle()
|
2013-04-04 14:02:55 +11:00
|
|
|
@userContainer = $(style.html)
|
2013-07-05 12:04:05 +10:00
|
|
|
@userFields = style.fields
|
2013-04-04 13:48:42 +11:00
|
|
|
|
2013-06-06 14:03:15 +10:00
|
|
|
show: (show, userCallback) ->
|
|
|
|
|
|
|
|
|
|
callback = =>
|
|
|
|
|
@destroy() if not show and not @elem
|
|
|
|
|
userCallback() if userCallback
|
2013-04-05 12:26:27 +11:00
|
|
|
|
2013-04-04 13:48:42 +11:00
|
|
|
hidden = @container.parent().parents(':hidden').length > 0
|
2013-06-02 23:19:34 +10:00
|
|
|
|
2013-04-05 12:26:27 +11:00
|
|
|
elems = @container.add @arrow
|
2013-04-05 15:34:55 +11:00
|
|
|
args = []
|
|
|
|
|
|
|
|
|
|
if hidden and show
|
|
|
|
|
fn = 'show'
|
|
|
|
|
else if hidden and not show
|
|
|
|
|
fn = 'hide'
|
|
|
|
|
else if not hidden and show
|
|
|
|
|
fn = @options.showAnimation
|
|
|
|
|
args.push @options.showDuration
|
|
|
|
|
else if not hidden and not show
|
|
|
|
|
fn = @options.hideAnimation
|
|
|
|
|
args.push @options.hideDuration
|
2013-05-31 13:18:43 +10:00
|
|
|
else
|
|
|
|
|
return callback()
|
2013-04-05 15:34:55 +11:00
|
|
|
|
|
|
|
|
args.push callback
|
|
|
|
|
|
2013-06-02 23:19:34 +10:00
|
|
|
elems[fn].apply elems, args
|
2013-04-04 13:13:08 +11:00
|
|
|
|
2013-06-06 14:03:15 +10:00
|
|
|
|
2013-06-06 15:35:06 +10:00
|
|
|
setGlobalPosition: () ->
|
2014-02-06 00:30:03 +11:00
|
|
|
[pMain, pAlign] = @getPosition()
|
2013-06-06 14:03:15 +10:00
|
|
|
|
|
|
|
|
main = positions[pMain]
|
|
|
|
|
align = positions[pAlign]
|
|
|
|
|
|
2013-06-06 15:35:06 +10:00
|
|
|
key = pMain+"|"+pAlign
|
2013-06-06 14:03:15 +10:00
|
|
|
anchor = globalAnchors[key]
|
|
|
|
|
unless anchor
|
|
|
|
|
anchor = globalAnchors[key] = createElem("div")
|
|
|
|
|
css = {}
|
|
|
|
|
css[main] = 0
|
|
|
|
|
if align is 'middle'
|
|
|
|
|
css.top = '45%'
|
|
|
|
|
else if align is 'center'
|
|
|
|
|
css.left = '45%'
|
|
|
|
|
else
|
|
|
|
|
css[align] = 0
|
|
|
|
|
anchor.css(css).addClass("#{pluginClassName}-corner")
|
|
|
|
|
$("body").append anchor
|
|
|
|
|
|
|
|
|
|
anchor.prepend @wrapper
|
|
|
|
|
|
2013-06-06 15:35:06 +10:00
|
|
|
setElementPosition: () ->
|
|
|
|
|
position = @getPosition()
|
2013-06-06 14:03:15 +10:00
|
|
|
|
|
|
|
|
[pMain, pAlign, pArrow] = position
|
2013-05-30 16:35:16 +10:00
|
|
|
|
2013-05-31 13:18:43 +10:00
|
|
|
#grab some dimensions
|
|
|
|
|
elemPos = @elem.position()
|
|
|
|
|
elemH = @elem.outerHeight()
|
|
|
|
|
elemW = @elem.outerWidth()
|
2013-06-03 09:15:58 +10:00
|
|
|
elemIH = @elem.innerHeight()
|
|
|
|
|
elemIW = @elem.innerWidth()
|
2013-05-31 13:18:43 +10:00
|
|
|
wrapPos = @wrapper.position()
|
|
|
|
|
contH = @container.height()
|
|
|
|
|
contW = @container.width()
|
|
|
|
|
|
2013-05-30 16:35:16 +10:00
|
|
|
|
2013-04-05 11:53:48 +11:00
|
|
|
#start calculations
|
2013-05-31 13:18:43 +10:00
|
|
|
mainFull = positions[pMain]
|
|
|
|
|
opp = opposites[pMain]
|
|
|
|
|
oppFull = positions[opp]
|
|
|
|
|
#initial positioning
|
|
|
|
|
css = {}
|
2013-06-04 17:01:03 +10:00
|
|
|
css[oppFull] = if pMain is 'b'
|
|
|
|
|
elemH
|
|
|
|
|
else if pMain is 'r'
|
|
|
|
|
elemW
|
|
|
|
|
else
|
|
|
|
|
0
|
2013-04-05 11:53:48 +11:00
|
|
|
|
2013-05-31 13:18:43 +10:00
|
|
|
#correct for elem-wrapper offset
|
|
|
|
|
# unless navigator.userAgent.match /MSIE/
|
2013-06-06 14:03:15 +10:00
|
|
|
incr css, 'top', elemPos.top - wrapPos.top
|
2013-05-31 13:18:43 +10:00
|
|
|
incr css, 'left', elemPos.left - wrapPos.left
|
2013-06-02 23:19:34 +10:00
|
|
|
|
2013-06-06 14:03:15 +10:00
|
|
|
#correct for margins
|
|
|
|
|
for pos in ['top', 'left']
|
|
|
|
|
margin = parseInt @elem.css("margin-#{pos}"), 10
|
|
|
|
|
incr css, pos, margin if margin
|
|
|
|
|
#correct for paddings (only for inline)
|
|
|
|
|
# if /^inline/.test @elem.css('display')
|
|
|
|
|
# padding = parseInt @elem.css("padding-#{pos}"), 10
|
|
|
|
|
# incr css, pos, -padding if padding
|
2013-04-05 11:53:48 +11:00
|
|
|
|
2013-06-06 14:03:15 +10:00
|
|
|
#add gap
|
|
|
|
|
gap = Math.max 0, @options.gap - if @options.arrowShow then arrowSize else 0
|
|
|
|
|
incr css, oppFull, gap
|
2013-06-03 12:28:03 +10:00
|
|
|
|
2013-05-31 13:18:43 +10:00
|
|
|
#calculate arrow
|
|
|
|
|
if not @options.arrowShow
|
2013-04-05 11:53:48 +11:00
|
|
|
@arrow.hide()
|
2013-05-31 13:18:43 +10:00
|
|
|
else
|
2013-06-03 09:15:58 +10:00
|
|
|
arrowSize = @options.arrowSize
|
2013-05-31 13:18:43 +10:00
|
|
|
arrowCss = $.extend {}, css
|
2013-06-04 17:01:03 +10:00
|
|
|
arrowColor = @userContainer.css("border-color") or
|
|
|
|
|
@userContainer.css("background-color") or
|
|
|
|
|
'white'
|
2013-05-31 13:18:43 +10:00
|
|
|
#build arrow
|
|
|
|
|
for pos in mainPositions
|
|
|
|
|
posFull = positions[pos]
|
|
|
|
|
continue if pos is opp
|
2013-06-04 17:01:03 +10:00
|
|
|
color = if posFull is mainFull then arrowColor else 'transparent'
|
2013-06-03 09:15:58 +10:00
|
|
|
arrowCss["border-#{posFull}"] = "#{arrowSize}px solid #{color}"
|
2013-05-31 13:18:43 +10:00
|
|
|
#add some room for the arrow
|
2013-06-03 09:15:58 +10:00
|
|
|
incr css, positions[opp], arrowSize
|
|
|
|
|
incr arrowCss, positions[pAlign], arrowSize*2 if pAlign in mainPositions
|
|
|
|
|
|
|
|
|
|
#calculate container alignment
|
|
|
|
|
if pMain in vAligns
|
2013-05-31 13:18:43 +10:00
|
|
|
incr css, 'left', realign(pAlign, contW, elemW)
|
2013-06-03 09:15:58 +10:00
|
|
|
incr arrowCss, 'left', realign(pAlign, arrowSize, elemIW) if arrowCss
|
|
|
|
|
else if pMain in hAligns
|
2013-05-31 13:18:43 +10:00
|
|
|
incr css, 'top', realign(pAlign, contH, elemH)
|
2013-06-03 09:15:58 +10:00
|
|
|
incr arrowCss, 'top', realign(pAlign, arrowSize, elemIH) if arrowCss
|
2013-04-05 11:53:48 +11:00
|
|
|
|
2013-05-31 13:18:43 +10:00
|
|
|
css.display = 'block' if @container.is(":visible")
|
2013-06-04 17:01:03 +10:00
|
|
|
#apply css
|
2013-05-31 13:18:43 +10:00
|
|
|
@container.removeAttr('style').css css
|
2013-06-03 09:15:58 +10:00
|
|
|
@arrow.removeAttr('style').css(arrowCss) if arrowCss
|
2013-04-05 11:53:48 +11:00
|
|
|
|
|
|
|
|
getPosition: ->
|
2013-06-05 13:17:20 +10:00
|
|
|
|
|
|
|
|
text = @options.position or if @elem then @options.elementPosition else @options.globalPosition
|
|
|
|
|
|
2013-05-29 16:59:19 +10:00
|
|
|
pos = parsePosition text
|
|
|
|
|
|
2013-06-03 09:15:58 +10:00
|
|
|
#validate position
|
2013-05-31 13:18:43 +10:00
|
|
|
pos[0] = 'b' if pos.length is 0
|
|
|
|
|
if pos[0] not in mainPositions
|
|
|
|
|
throw "Must be one of [#{mainPositions}]"
|
2013-06-03 12:28:03 +10:00
|
|
|
|
2013-06-03 09:15:58 +10:00
|
|
|
#validate alignment
|
2013-05-31 13:18:43 +10:00
|
|
|
if pos.length is 1 or
|
2013-06-03 09:15:58 +10:00
|
|
|
(pos[0] in vAligns and pos[1] not in hAligns) or
|
|
|
|
|
(pos[0] in hAligns and pos[1] not in vAligns)
|
|
|
|
|
pos[1] = if pos[0] in hAligns then 'm' else 'l'
|
2013-05-29 16:59:19 +10:00
|
|
|
|
2013-06-06 14:03:15 +10:00
|
|
|
if pos.length is 2
|
|
|
|
|
pos[2] = pos[1]
|
2013-05-29 16:59:19 +10:00
|
|
|
|
2013-06-06 14:03:15 +10:00
|
|
|
return pos
|
2013-04-04 13:13:08 +11:00
|
|
|
|
2013-04-04 13:48:42 +11:00
|
|
|
getStyle: (name) ->
|
|
|
|
|
name = @options.style unless name
|
2013-04-05 11:53:48 +11:00
|
|
|
name = 'default' unless name
|
2013-06-03 12:28:03 +10:00
|
|
|
style = styles[name]
|
2013-06-04 17:01:03 +10:00
|
|
|
throw "Missing style: #{name}"unless style
|
2013-04-04 13:48:42 +11:00
|
|
|
style
|
|
|
|
|
|
2013-06-05 13:17:20 +10:00
|
|
|
updateClasses: ->
|
2013-06-04 17:01:03 +10:00
|
|
|
classes = ['base']
|
2013-06-03 12:28:03 +10:00
|
|
|
|
2013-06-04 17:01:03 +10:00
|
|
|
if $.isArray @options.className
|
|
|
|
|
classes = classes.concat @options.className
|
|
|
|
|
else if @options.className
|
|
|
|
|
classes.push @options.className
|
2013-06-03 12:28:03 +10:00
|
|
|
|
|
|
|
|
style = @getStyle()
|
2013-06-04 17:01:03 +10:00
|
|
|
classes = $.map(classes, (n) -> "#{pluginClassName}-#{style.name}-#{n}").join ' '
|
2013-06-03 12:28:03 +10:00
|
|
|
|
2013-06-04 17:01:03 +10:00
|
|
|
@userContainer.attr 'class', classes
|
2013-04-05 11:53:48 +11:00
|
|
|
|
2013-04-04 13:13:08 +11:00
|
|
|
#run plugin
|
2013-04-04 16:58:22 +11:00
|
|
|
run: (data, options) ->
|
2013-04-04 13:13:08 +11:00
|
|
|
#update options
|
|
|
|
|
if $.isPlainObject(options)
|
2013-06-02 23:19:34 +10:00
|
|
|
$.extend @options, options
|
2013-04-04 13:13:08 +11:00
|
|
|
#shortcut special case
|
|
|
|
|
else if $.type(options) is 'string'
|
2014-02-06 00:30:03 +11:00
|
|
|
@options.className = options
|
2013-04-04 13:13:08 +11:00
|
|
|
|
2013-04-04 16:58:22 +11:00
|
|
|
if @container and not data
|
2013-06-05 13:17:20 +10:00
|
|
|
@show false
|
2013-04-04 13:13:08 +11:00
|
|
|
return
|
2013-04-04 16:58:22 +11:00
|
|
|
else if not @container and not data
|
2013-04-04 13:13:08 +11:00
|
|
|
return
|
|
|
|
|
|
2013-07-05 12:04:05 +10:00
|
|
|
datas = {}
|
|
|
|
|
if $.isPlainObject data
|
|
|
|
|
datas = data
|
|
|
|
|
else
|
|
|
|
|
datas[blankFieldName] = data
|
|
|
|
|
|
|
|
|
|
for name, d of datas
|
|
|
|
|
type = @userFields[name]
|
|
|
|
|
continue unless type
|
|
|
|
|
if type is 'text'
|
|
|
|
|
#escape
|
|
|
|
|
d = encode(d)
|
|
|
|
|
d = d.replace(/\n/g,'<br/>') if @options.breakNewLines
|
|
|
|
|
#update content
|
|
|
|
|
value = if name is blankFieldName then '' else '='+name
|
|
|
|
|
find(@userContainer,"[data-notify-#{type}#{value}]").html(d)
|
2013-04-04 14:02:55 +11:00
|
|
|
|
2013-06-03 12:28:03 +10:00
|
|
|
#set styles
|
2013-06-05 13:17:20 +10:00
|
|
|
@updateClasses()
|
2013-06-03 12:28:03 +10:00
|
|
|
|
2013-06-06 14:03:15 +10:00
|
|
|
#positioning
|
|
|
|
|
if @elem
|
2013-06-06 15:35:06 +10:00
|
|
|
@setElementPosition()
|
2013-06-06 14:03:15 +10:00
|
|
|
else
|
2013-06-06 15:35:06 +10:00
|
|
|
@setGlobalPosition()
|
2013-04-04 13:13:08 +11:00
|
|
|
|
2013-04-04 16:58:22 +11:00
|
|
|
@show true
|
2013-04-04 13:13:08 +11:00
|
|
|
|
|
|
|
|
#autohide
|
2013-04-04 16:58:22 +11:00
|
|
|
if @options.autoHide
|
|
|
|
|
clearTimeout @autohideTimer
|
2013-05-31 13:18:43 +10:00
|
|
|
@autohideTimer = setTimeout =>
|
2013-04-04 16:58:22 +11:00
|
|
|
@show false
|
2013-04-04 13:13:08 +11:00
|
|
|
, @options.autoHideDelay
|
|
|
|
|
|
2013-04-05 15:34:55 +11:00
|
|
|
destroy: ->
|
2013-06-06 14:03:15 +10:00
|
|
|
@wrapper.remove()
|
2013-04-05 15:34:55 +11:00
|
|
|
|
2013-06-03 12:28:03 +10:00
|
|
|
|
|
|
|
|
# ================================
|
|
|
|
|
# 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 ->
|
2013-06-04 17:01:03 +10:00
|
|
|
inst = getAnchorElement($(@)).data(pluginClassName)
|
2013-06-03 12:28:03 +10:00
|
|
|
if inst
|
|
|
|
|
inst.run data, options
|
|
|
|
|
else
|
|
|
|
|
new Notification $(@), data, options
|
|
|
|
|
@
|
|
|
|
|
|
2013-06-06 14:03:15 +10:00
|
|
|
#extra methods
|
2013-06-12 13:28:47 +10:00
|
|
|
$.extend $[pluginName], { defaults, addStyle, pluginOptions, getStyle, insertCSS }
|
2013-06-03 12:28:03 +10:00
|
|
|
|
2013-04-05 12:26:27 +11:00
|
|
|
#when ready
|
2013-04-04 13:13:08 +11:00
|
|
|
$ ->
|
2013-06-03 12:28:03 +10:00
|
|
|
#insert default style
|
2013-06-12 13:28:47 +10:00
|
|
|
insertCSS(coreStyle.css).attr('id', 'core-notify')
|
2013-04-05 11:53:48 +11:00
|
|
|
|
2013-04-04 16:58:22 +11:00
|
|
|
#watch all notifications clicks
|
2013-06-12 13:28:47 +10:00
|
|
|
$(document).on 'click notify-hide', ".#{pluginClassName}-wrapper", (e) ->
|
2013-06-04 17:01:03 +10:00
|
|
|
inst = $(@).data pluginClassName
|
2013-06-12 13:28:47 +10:00
|
|
|
if inst and (inst.options.clickToHide or e.type is 'notify-hide')
|
2013-04-05 15:34:55 +11:00
|
|
|
inst.show false
|
2013-04-04 13:13:08 +11:00
|
|
|
|