Способы расширения функционала jQuery

С примерами на Coffeescript

dpetroff.ru/slides/jquery_extension

Зачем Coffeecript? coffeescript.org

				
				
			

Зачем Coffeecript? Синтаксис

				class Javascript extends Language
				constructor: (@dialect='ecma') ->
				getKeywords: (which='used') ->
					keywords =
				
					keywords[which] || null
				echo: () ->
					words = @getKeywords 'unused'
					console.log "#{word}" for word in words
			

Зачем Coffeecript? Синтаксис

				var Javascript,
				  __hasProp = {}.hasOwnProperty,
				  __extends = function(child, parent) { for (var key in parent) {
				  if (__hasProp.call(parent, key)) child[key] = parent[key]; }
				  function ctor() { this.constructor = child; }
				  ctor.prototype = parent.prototype; child.prototype = new ctor(); 
				  child.__super__ = parent.prototype; return child; };
				Javascript = (function(_super) {
				  __extends(Javascript, _super);
				

Зачем Coffeecript? Синтаксис

				  function Javascript(dialect) {
				    this.dialect = dialect != null ? dialect : 'ecma';
				  }
				  Javascript.prototype.getKeywords = function(which) {
				    var keywords;
				    if (which == null) {
				      which = 'used';
				    }
				

Зачем Coffeecript? Синтаксис

				    keywords = {
				      used: ['var', 'const', 'in', 'for'],
				      unused: ['class', 'export', 'import']
				    };
				    return keywords[which] || null;
				  };
				  Javascript.prototype.echo = function() {
				    var word, _i, _len, _ref, _results;
				

Зачем Coffeecript? Синтаксис

				    _ref = getKeywords('unused');
				    _results = [];
				    for (_i = 0, _len = _ref.length; _i < _len; _i++) {
				      word = _ref[_i];
				      _results.push(console.log("" + word + " is reserved"));
				    }
				    return _results;
				  };
				  return Javascript;
				})(Language);
			

Что классного в jQuery?

Зачем расширять jQuery?

Как будем расширять?

jQuery - сборник плагинов

jQuery.fn

jQuery.fn

				$.fn.myPlugin = (options) ->
				@ # <- this 
				options # <- object 
				
					# do stuff
			

jQuery.fn. Состояние

Хорошо бы иметь такое API:

				# создали виджет
				$('#selector').mywidget({opt: ions})
				# дергаем метод
				$('#selector').mywidget( 'show', 'message')
			

jQuery.fn. Реализация

				$.fn.myPlugin = (options, args..) ->
					class MyPlugin
						constructor: (@element, @options) ->
						oneMethod: () ->
						anotherOne: (props) ->
					defaultOptions = {}
			

jQuery.fn. Реализация

					@.each ->
						obj = @data 'myplugin'
						unless obj
							options = $.extend {}, defaultOptions, options
				
						else
							method = options
				
			

jQuery.fn. Выводы

jQuery.fn. Признаки хорошего плагина

Opensource - это хорошо!

jQuery API

Где бы хотелось расширить методы jQuery?

$.fn.css

src/css.js

$.fn.css. Зачем расширять

$.fn.css

				jQuery.cssHooks.cats =
					get: (elem, computed, extra) ->
						'300 ms'
					set: (elem, value) ->
						# do something to cats
				jQuery.cssProps.cats = 'mscats' # алиас
				jQuery.cssNumber.cats = true # хотим работать с числом
			

$.fn.css

$.fn.animate

				# алиас для длительности
				jQuery.extend jQuery.fx.speeds, { uberfast: 100 }
				# функция для анимирования
				jQuery.easing.bumble =
						(percent, current, start, stop, duration) ->
							percent * (10 - percent * 9)
			

$.fn.animate

Уже не нужно, но еще можно!

				jQuery.fx.cats = (tween) ->
						jQuery.style(tween.elem, tween.prop,
									tween.now + tween.unit)
			

$.fn.on

src/event.js

$.fn.on. Зачем это?

$.fn.on. API. Part1

				jQuery.event.special.custom = # @ == elem
					noBubble: true
				
				
			

$.fn.on. API. Part2

				jQuery.event.special.custom = # @ == elem
					trigger: (data) ->
					handle: (event) ->
					_default: (data) ->
					preDispatch: (event) ->
					postDispatch: (event) ->
			

$.fn.on. Пример

				jQuery.event.special.beforeunload =
					setup: ( data, namespaces, eventHandle )
						if jQuery.isWindow( this )
							this.onbeforeunload = eventHandle
					teardown: ( namespaces, eventHandle ) ->
						if this.onbeforeunload == eventHandle
							@onbeforeunload = null
			

$.fn.on. Пример сложного свойства

				jQuery.event.special.empty =
					setup: ( data, namespaces, eventHandle ) ->
						jQuery.data(elem = @, data = {})
						data.timer = setInterval(=>
							if elem.innerHTML.length == 0
								data.triggered || $(@).trigger 'empty'
								data.triggered = true
							else if data.triggered
								data.triggered = false
						, 100)
			

$.fn.on. Пример сложного свойства

					teardown: ( namespaces, eventHandle ) ->
						clearInterval jQuery.data(@, 'empty_event').timer
			

$.ajax

src/ajax.js

$.ajax. Профит?

$.ajax. Свои типы

				jQuery.ajaxSetup
				
				
				
			

$.ajax. Свои типы

				jQuery.ajaxPrefilter "script", (s, origs, jqXHR) ->
					#prepare stuff
					"anothertype"
			

$.ajax. Свои транспорты

				jQuery.ajaxTransport "transport", (s) ->
					if condition
						# return transport
						send: (headers, callback) ->
							#do stuff
						abort: () ->
							#omg, abort
					else
						#return fallback transport optionaly
			

Sizzle

src/sizzle

Sizzle, jQuery API

Пример: поиск незагруженных картинок

Sizzle, jQuery API

				jQuery.expr[':'].mailto = (node, index, props, nodes) ->
					if node.href && node.href.match /^mailto:/
						unless props[3]
							true
						else
							node.href.replace(/^.*@/, '') == props[3]
			

Бонус

Для использования функционала jQuery не обязательно использовать коллекции

Еще функции jQuery

param, Callbacks, Deffered, camelCase, contains, each, extend, inArray, isArray, grep, isEmptyObject, isFuction, isNumeric, isPlainObject, isWindow, isXmlDoc, makeArray, map, merge, noop, now, parseJSON, proxy, queue, trim, unique

Немного про будущее. 2013

Итоги

Дмитрий Петров, Skype

http://dpetroff.ru/slides/jquery_extension/