Skip to content

Instantly share code, notes, and snippets.

@Dionid
Last active October 29, 2015 15:38
Show Gist options
  • Save Dionid/8a84ecdb642586f8a042 to your computer and use it in GitHub Desktop.
Save Dionid/8a84ecdb642586f8a042 to your computer and use it in GitHub Desktop.
TZQ - something from JQuery, Mediator and Underscore
# Есть опасение, что большой ошибкой было добавлять новые функции в сам нод
# Сейчас, если найти нод, который уже был пройден через функции TZQ, то он
# будет иметь все методы, что были переданы при создании.
# В следующей версии надо будет разделить, как в jQuery, модель от нода, при
# помощи создания нового пустого объекта, копировании в него функций модели и
# дальнейшего доавбления внутрь под индекс нода. Пример:
# createModel: (el)->
# if el?
# res = {}
# @extend res, @model
# unless el.aTZModel
# if @isNode el
# res[0] = el
# else if @isArray el
# for e,i in el
# res[i]=el if @isNode e
# else
# console.error 'Ellement is not node!'
#
# return res
# PRIVATE HELPERS
addEventListener = (el, evt, fn)->
if el? && evt? && fn? && typeof(fn) == 'function'
if el.addEventListener
el.addEventListener(evt, fn, false)
else if el.attachEvent
el.attachEvent('on' + evt, fn)
else
el['on' + evt] = fn;
return el
else
throw TypeError("Cant add eventListner!")
removeEventListener = (el, evt, fn)->
if el? && evt? && fn? && typeof(fn) == 'function'
if el.removeEventListener
el.removeEventListener(evt, fn, false)
else if el.detachEvent
el.detachEvent('on' + evt, fn)
else
el['on' + evt] = '';
return el
else
throw TypeError("Cant add eventListner!")
class EllementModelTZ
constructor: ()->
aTZModel: true
on: (event, handler)->
if event? && handler?
addEventListener @, event, handler
else
console.error 'No event or handler typped!'
return @
off: (event, handler)->
if event? && handler?
removeEventListener @, event, handler
else
console.error 'No event or handler typped!'
return @
addClass: (className)->
if TZQ.isString className
@.classList.add className if $.isString(className)
return @
class TZQClass
constructor: ()->
@channels = {}
#HELPERS
# extend obj with other obj
extend: (object, properties)->
for key, val of properties
object[key] = val
object
# создает новый объект со свойствами двух объектов
merge: (options, overrides) ->
@extend (@extend {}, options), overrides
# is string
isString: (string) -> typeof string is 'string'
# is int like 1, 2, 3
isInt: (num)->
return Number(num) == num && num % 1 == 0
isFloat: (num)->
return num == Number(num) && num % 1 != 0
# is Array or NodeList
isArray: (list) ->
list? and ((list instanceof NodeList) or Array.isArray(list))
# is Node
isNode: (node) -> node? and (node instanceof Node)
# Приводим аргументы в массив
argsToArray: (args) -> Array.prototype.slice.call(args)
# ELEMENT HELPERS
# MEDIATOR
sub: (name, callback, context)->
@channels[name] = [] unless @channels[name]?
context ||= @
@channels[name].push context: context, callback: callback
unsub: (name, callback)->
for sub, i in @channels[name]
@channels[name].splice(i, 1) if sub.callback == callback
pub: (name, data...)->
if @channels[name]?
for sub in @channels[name]
sub.callback.apply sub.context, data
# MODEL
model: new EllementModelTZ()
# ELLEMENT MODEL FUNCTIONS
createModel: (el)->
if el?
unless el.aTZModel
if @isNode el
@extend el, @model
else if @isArray el
for e in el
@extend e, @model if @isNode e
else
console.error 'Ellement is not node!'
return el
# FUNCTIONS
# Аналог jQuery(document).ready()
ready: (callback) ->
document.addEventListener 'readystatechange', ->
callback?() if document.readyState is "complete"
addCSSRule: (selector, rules)->
sheet = document.styleSheets[0]
if ('insertRule' of sheet)
# sheet.insertRule(selector + '{' + rules + '}', index)
sheet.insertRule("#{selector} { #{rules} }", sheet.cssRules.length)
else if ('addRule' of sheet)
sheet.addRule(selector, rules, sheet.cssRules.length)
# ELEMENT FUNCTIONS
# Получаем элемент по селектору
# Если родитель не передан - родителем является document
$: (root, selector) ->
if arguments.length is 1
selector = root
root = document
# Если передали не селектор, а Node - возвращаем его же
if $.isNode(selector)
return @createModel(selector)
# массив или NodeList - возвращаем первый элемент из списка
if $.isArray(selector)
if selector.length
return @createModel selector[0]
return undefined
# Если селектор не строка - ошибка
throw TypeError("Selector is not a string") unless $.isString(selector)
return @createModel root?.querySelector(selector)
# Получаем все элементы по селектору
# Если родитель не передан - родителем является document
$$: (root, selector) ->
if arguments.length is 1
selector = root
root = document
# Если передали не селектор, а Node
# - возввращаем массив с единственным элементов
return [@createModel(selector)] if $.isNode(selector)
# массив или NodeList - возвращаем его же
return @createModel(selector) if $.isArray(selector)
# Если селектор не строка - ошибка
throw TypeError("Selector is not a string") unless $.isString(selector)
return @createModel root?.querySelectorAll(selector)
# if elsArr?
# for el in elsArr
# @createModel el
# elsArr
# Вешаем обработчик (handler) события (event)
# - на элемент - если передан конкретный элемент
# - на элемент - если передан селекторв, возвращающий один элемент
# - на несколько элементов - если передано несколько элементов
# - на несколько элементов - если передан селектор, возвращающий список
# элементов
on: (element, event, handler) ->
for el in @.$$(element)
# el?.addEventListener event, handler, false
addEventListener el, event, handler if el?
# Удаляем обработчик события
# См. $.on()
off: (element, event, handler) ->
for el in @.$$(element)
# el?.removeEventListener event, handler, false
removeEventListener el, event, handler if el?
# Прогулка по DOM-дереву
# Если передан селектер - вернет родителя по селектору или null
# Если селектор не передан - вернет родителя
parent: (element, selector) ->
return @.$(element)?.parentNode unless selector
_has = (collection, el) ->
for e in collection
return true if e is el
return false
all = @.$$(selector)
cur = @.parent(element)
while cur and !_has(all, cur)
cur = @.parent(cur)
return cur
# Аттрибуты
# Существует класс у элемента
# (или первого элемента в стеке)
hasClass: (element, className) ->
element = @.$(element)
return false if !element
return " #{element.className} "
.replace(/[\n\t]/g, " ")
.indexOf(" #{className} ") >= 0
# Добавляем класс ко все элементам
addClass: (element, className) ->
elements = @.$$(element)
for element in elements
unless @.hasClass(element, className)
element?.className =
"#{element.className} #{className}"
.replace(/\s+/g, " ")
.trim()
# Удаляем класс у всех элементов
removeClass: (element, className) ->
elements = @.$$(element)
re = new RegExp("(^|\\s)#{className}(\\s|$)", "g")
for element in elements
element?.className =
element.className
.replace(re, "$1")
.replace(/\s+/g, " ")
.trim()
# Переключаем класс
toggleClass: (element, className) ->
args = @.argsToArray(arguments)
if @.hasClass(element, className)
@.removeClass(element, className)
else
@.addClass(element, className)
# Элемент виден или нет
isVisible: (element) ->
self = @
window.getComputedStyle(self.$(element))?.display is none
# Высота элемента включая маргины
outerHeight: (element) ->
element = @.$(element)
compStyle = getComputedStyle(element)
marginTop = parseFloat(compStyle.marginTop)
marginBottom = parseFloat(compStyle.marginBottom)
element.offsetHeight + marginTop + marginBottom
# INIT
TZQMod = (selector,context)->
return TZQMod.$(selector)
TZQ.prototype.extend TZQMod, new TZQ
window.$ = TZQMod
# OR
# window.$ = new TZQ
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment