Last active
October 29, 2015 15:38
-
-
Save Dionid/8a84ecdb642586f8a042 to your computer and use it in GitHub Desktop.
TZQ - something from JQuery, Mediator and Underscore
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Есть опасение, что большой ошибкой было добавлять новые функции в сам нод | |
# Сейчас, если найти нод, который уже был пройден через функции 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