Розбираємо розтягнення поля пошуку

20

Від автора: Підручник про те, як створити адаптивне розтягнення поле пошуку з хорошою підтримкою сенсорного введення.

Можливо, ви помітили ті маленькі удосконалення, які останнім часом з’явилися тут, на Codrops. Однією з тих речей, які ми вирішили змінити, стало поле введення для пошуку. Воно було перенесено з бічної колонки в верхній колонтитул і застосований простий ефект, при якому потрібно клацнути, щоб поле вводу збільшилася. Ми отримали безліч прохань пояснити, як це зроблено, і сьогодні хотіли б показати вам, як «з нуля» створити подібний input для пошуку. Нашою метою стало максимальне збільшення сумісності мобільних пристроїв і старих браузерів (аж до IE8). Хоча це може здатися дуже легким завданням, нам доведеться застосувати декілька хитрощів, щоб все запрацювало належним чином.

Розбираємо розтягнення поля пошукуРозбираємо розтягнення поля пошуку

Коротенько, ось що повинен робити наш пошуковий компонент:

З самого початку нам потрібно, щоб показувалася тільки кнопка з піктограмою пошуку.

При клацанні по іконці потрібно, щоб выскальзывало поле пошуку.

Компонент повинен бути гнучким, щоб його можна було використовувати в адаптивному контексті.

Після написання чогось потрібна можливість відправки форми шляхом натиснення enter або клацання по іконці пошуку.

Якщо поле вводу розтягнуто і порожньо, воно повинно знову закриватися клацання по іконці пошуку.

Нам також потрібно, щоб поле вводу закривалося при клацанні поза його незалежно від того, порожнє воно чи ні.

При відключеному JavaScript’е потрібно, щоб поле пошуку відображалося розтягнутим.

Для застосування в сенсорних пристроях потрібно додати підтримку подій дотику.

Тепер, коли зрозуміло, що нам потрібно, давайте почнемо з розмітки.

РОЗМІТКА

Для розмітки нам потрібен основний контейнер, форма, текст і input-s відправки, а для іконки – span:

Як правило, для іконки можна було б застосувати псевдоэлемент, але так як не планується його використання з до елементами, такими як елементи форми, то ми просто в даному випадку скористаємося span. Коли всі елементи розміщені, давайте призначимо їм стилі.

CSS

Слідуючи власним вимогам, нам спочатку потрібно переконатися, що кнопка з піктограмою пошуку видно. Все інше повинно бути приховано. Але давайте продумаємо ще один крок вперед і уявімо собі, що станеться, коли ми збільшимо поле пошуку (основний пакувальник). Як нам це зробити? Давайте скористаємося overflow: hidden і при збільшенні ширини пакувальника sb-search input повинен проявитися.

Тому першим ми призначаємо стилі упаковщику sb-search. Вільно розміщуємо його праворуч і встановлюємо overflow на hidden. Спочатку ширина повинна бути 60px, але так як нам потрібно анімувати її до 100%, на мобільних браузерах (iOS) буде проблема. Їм не подобається перехід з ширини на основі пікселів до процентної. Вони просто пропустять перехід. Тому замість того ми визначаємо значення min-width в 60px і ширину в 0%. Це блискуче рішення, придумане @julienknebel, і він пише про нього тут: Перехід CSS від фіксованої ширини в пікселях до автоматичної (CSS transition from a fixed px width to an auto width).

Також додамо перехід ширини і -webkit-backface-visibility: hidden уникнути деяких відбитків введення для мобільних браузерів (iOS):

.sb-search {
position: relative;
margin-top: 10px;
width: 0%;
min-width: 60px;
height: 60px;
float: right;
overflow: hidden;
-webkit-transition: width 0.3 s;
-moz-transition: width 0.3 s;
transition: width 0.3 s;
-webkit-backface-visibility: hidden;
}

Все, що переповнює цей невеликий блок, видно не буде. Тепер розмістимо input пошуку. Встановимо ширину на основі відсотків з тим, щоб при розширенні батьківського елемента input збільшувався разом з ним. Встановлення правильної висоти, розміру шрифту і відступу гарантує, що текст буде знаходитися по центру (використання висоти рядка в IE8 не спрацює належним чином, тому давайте встановимо замість нього відступи).

Установка input на position absolute може здатися непотрібною справою, але вона вирішує дрібну прикру неприємність, яка іноді трапляється при закритті пошуку: на якийсь короткий час input здається видимим праворуч.

.sb-search-input {
position: absolute;
top: 0;
right: 0;
border: none;
outline: none;
background: #fff;
width: 100%;
height: 60px;
margin: 0;
z-index: 10;
padding: 20px 65px 20px 20px;
font-family: inherit;
font-size: 20px;
color: #2c3e50;
}
input[type=»search»].sb-search-input {
-webkit-appearance: none;
-webkit-border-radius: 0px;
}

До того ж ми видаляємо стилі input за замовчуванням для браузерів WebKit. Давайте визначимо колір тексту-заповнювача з допомогою вендорних правил:

.sb-search-input::-webkit-input-placeholder {
color: #efb480;
}
.sb-search-input:-moz-placeholder {
color: #efb480;
}
.sb-search-input::-moz-placeholder {
color: #efb480;
}
.sb-search-input:-ms-input-placeholder {
color: #efb480;
}

Тепер подбаємо про кнопці з іконкою пошуку і input -му відправлення. Відомо, що вони потрібні нам в одному місці, тому розмістимо їх у правому кутку і встановимо однакові розміри. Так як вони будуть знаходитись один над іншим, ми встановимо їм абсолютне позиціонування:

.sb-icon-search,
.sb-search-submit {
width: 60px;
height: 60px;
display: block;
position: absolute;
right: 0;
top: 0;
padding: 0;
margin: 0;
line-height: 60px;
text-align: center;
cursor: pointer;
}

У вихідному положенні нам потрібно, щоб на кнопку з піктограмою можна було натиснути. Потім, при відкритті input -а, потрібна можливість клацнути input відправлення. Тому ми спочатку встановимо z-index для input -а відправки на -1 і зробимо його прозорим, щоб весь час бачити іконку пошуку:

.sb-search-submit {
background: #fff; /* потрібно для IE */
-ms-filter: «програми:DXImageTransform.Microsoft.Alpha(Opacity=0)»; /* IE 8 */
filter: alpha(opacity=0); /* IE 5-7 */
opacity: 0;
color: transparent;
border: none;
outline: none;
z-index: -1;
}

Чому б просто не встановити прозорий фон? Схоже, що в IE це нормально не спрацює, оскільки елемент не піддається клацання. Отже, ми замість цього застосовуємо щільний фоновий колір і встановлюємо непрозорість на 0.
Діапазон іконки пошуку буде спочатку високий z-index, тому що нам потрібно, щоб вона перебувала поверх всього іншого. Для додавання іконки пошуку ми застосуємо псевдоэлемент :before:

.sb-icon-search {
color: #fff;
background: #e67e22;
z-index: 90;
font-size: 22px;
font-family: ‘icomoon’;
speak: none;
font-style: normal;
font-weight: normal;
font-variant: normal;
text-transform: none;
-webkit-font-smoothing: antialiased;
}
.sb-icon-search:before {
content: «\e000»;
}

Не забудьте підключити шрифт на початку вашого CSS:

/* Іконка пошуку від IcoMoon, створена за допомогою програми http://icomoon.io/app/ */
@font-face {
font-family: ‘icomoon’;
src:url(‘../fonts/icomoon/icomoon.eot’);
src:url(‘../fonts/icomoon/icomoon.eot?#iefix’) format(’embedded-opentype’),
url(‘../fonts/icomoon/icomoon.woff’) format(‘woff’),
url(‘../fonts/icomoon/icomoon.ttf’) format(‘truetype’),
url(‘../fonts/icomoon/icomoon.svg#icomoon’) format(‘svg’);
font-weight: normal;
font-style: normal;
}

Коли стилі призначені таким чином, вже можна просто встановити ширину пакувальника sb-search, щоб та ставала 100% при додаванні класу sb-search-open. При неактивному JavaScript’е нам потрібно, щоб input був пошуку за умовчанням відкритий:

.sb-search.sb-search-open,
.no-js .sb-search {
width: 100%;
}

Давайте змінимо колір діапазону іконки пошуку і помістимо її під input -му відправки, встановивши z-index на більш низьке значення:

.sb-search.sb-search-open .sb-icon-search,
.no-js .sb-search .sb-icon-search {
background: #da6d0d;
color: #fff;
z-index: 11;
}

І нарешті, встановимо z-index input відправки на більш високе значення, щоб на нього можна було клацати:

.sb-search.sb-search-open .sb-search-submit,
.no-js .sb-search .sb-search-submit {
z-index: 90;
}

Коли всі необхідні стилі визначені, можна перейти до JavaScript’у.

JAVASCRIPT

Почнемо з перемикання класу sb-search-open. Додаємо його при клацанні по основним упаковщику (sb-search) і видаляємо при клацанні по input -у відправки, тільки якщо input порожній. В іншому випадку ми відправляємо форму. Щоб не запускати видалення класу при клацанні по input -у (так як наш спусковий механізм – це весь пакувальник), на цьому елементі потрібно запобігти появі події клацання. Це означає, що клацання по input -у не викличе запуск клацання на його батьківських елементах.

;( function( window ) {
function UISearch( el, options ) {
this.el = el;
this.inputEl = el.querySelector( ‘form > input.sb-search-input’ );
this._initEvents();
}
UISearch.prototype = {
_initEvents : function() {
var self = this,
initSearchFn = function( ev ) {
if( !classie.has( self.el, ‘sb-search-open’ ) ) { // відкрийте його
ev.preventDefault();
self.open();
}
else if( classie.has( self.el, ‘sb-search-open’ ) && /^\s*$/.test( self.inputEl.value ) ) { // закрийте його
self.close();
}
}
this.el.addEventListener. ( ‘click’, initSearchFn );
this.inputEl.addEventListener. ( ‘click’, function( ev ) { ev.stopPropagation(); });
},
open : function() {
classie.add( this.el, ‘sb-search-open’ );
},
close : function() {
classie.remove( this.el, ‘sb-search-open’ );
}
}
// додайте в глобальний простір імен
window.UISearch = UISearch;
} )( window );

Далі нам слід додати події для видалення класу sb-search-open клацання в будь-якому місці поза полем пошуку. Щоб це запрацювало, також потрібно подбати про появу події при клацанні по основним упаковщику.

;( function( window ) {
function UISearch( el, options ) {
this.el = el;
this.inputEl = el.querySelector( ‘form > input.sb-search-input’ );
this._initEvents();
}
UISearch.prototype = {
_initEvents : function() {
var self = this,
initSearchFn = function( ev ) {
ev.stopPropagation();
if( !classie.has( self.el, ‘sb-search-open’ ) ) { // відкрийте його
ev.preventDefault();
self.open();
}
else if( classie.has( self.el, ‘sb-search-open’ ) && /^\s*$/.test( self.inputEl.value ) ) { // закрийте його
self.close();
}
}
this.el.addEventListener. ( ‘click’, initSearchFn );
this.inputEl.addEventListener. ( ‘click’, function( ev ) { ev.stopPropagation(); });
},
open : function() {
var self = this;
classie.add( this.el, ‘sb-search-open’ );
// у разі клацання по тілу закрийте input пошуку
var bodyFn = function( ev ) {
self.close();
this.removeEventListener( ‘click’, bodyFn );
};
document.addEventListener. ( ‘click’, bodyFn );
},
close : function() {
classie.remove( this.el, ‘sb-search-open’ );
}
}
// додайте в глобальний простір імен
window.UISearch = UISearch;
} )( window );

Ще одна річ, про яку слід подбати – це обрізка пошукової фрази. Крім того, клацання по іконці пошуку нам потрібно, щоб input потрапляв у фокус. Так як в мобільних браузерах (iOS) це викликає кілька засмиканий перехід (з одночасним відкриттям клавіатури), в даному випадку хотілося б цього уникнути. При закритті поля пошуку ми зробимо розмиття input-а пошуку. Це вирішить проблеми на деяких пристроях, де навіть після закриття input -а курсор показується мерехтливим.

;( function( window ) {
// http://stackoverflow.com/a/11381730/989439
function mobilecheck() {
var check = false;
(function(a){if(/(android|ipad|playbook|silk|bb\d+|meego).+mobile|
avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile
|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4/6)0|symbian|treo
|up\.(browser|link)|vodafone|wap|windows ce|phone)|xda
|xiino/i.test(a)||/1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s
|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)
|aptu|ar(ch|go)|as(te|us)|attw|au(di|\m|r |s )|avan|be(ck|ll|nq)
|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)
|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)
|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)
|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene
|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)
|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)
|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom
|im1k|inno|ipaq|iris|uk(t|v)a|jbro|jemu|jigs|kddi|keji
|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg
( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)
|mc(01/21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo
(01/02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0/2)|n50(0/2/5)
|n7(0(0/1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)
|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg
|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po
(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07/12/21/32/60|\-[2-7]|i\-)
|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)
|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar
|sie(\-|m)|sk\-0|sl(45|id|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18/50)|t6(00/10/18)|ta(gt|lk)|tcl\-|tdg\-|tel
(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up
(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40/5[0-3]|\-v)
|vm40|voda|vulc|vx(52/53/60/61/70/80/81/83/85/98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.test(a.substr(0,4)))check = true})(navigator.userAgent||navigator.vendor||window.opera);
return check;
}
// http://www.jonathantneal.com/blog/polyfills-and-prototypes/
!String.prototype.trim && (String.prototype.trim = function() {
return this.replace(/^\s+|\s+$/g, «);
});
function UISearch( el, options ) {
this.el = el;
this.inputEl = el.querySelector( ‘form > input.sb-search-input’ );
this._initEvents();
}
UISearch.prototype = {
_initEvents : function() {
var self = this,
initSearchFn = function( ev ) {
ev.stopPropagation();
// обріжте його значення
self.inputEl.value = self.inputEl.value.trim();
if( !classie.has( self.el, ‘sb-search-open’ ) ) { // відкрийте його
ev.preventDefault();
self.open();
}
else if( classie.has( self.el, ‘sb-search-open’ ) && /^\s*$/.test( self.inputEl.value ) ) { // закрийте його
self.close();
}
}
this.el.addEventListener. ( ‘click’, initSearchFn );
this.inputEl.addEventListener. ( ‘click’, function( ev ) { ev.stopPropagation(); });
},
open : function() {
var self = this;
classie.add( this.el, ‘sb-search-open’ );
// сфокусуйте на вводі
if( !mobilecheck() ) {
this.inputEl.focus();
}
// закрийте enter пошуку при клацанні по тілу
var bodyFn = function( ev ) {
self.close();
this.removeEventListener( ‘click’, bodyFn );
};
document.addEventListener. ( ‘click’, bodyFn );
},
close : function() {
this.inputEl.blur();
classie.remove( this.el, ‘sb-search-open’ );
}
}
// додайте в глобальний простір імен
window.UISearch = UISearch;
} )( window );

Щоб в мобільних пристроях все працювало добре, нам знадобиться додати відповідні події дотику. Додавши preventDefault в функцію initSearchFn, ми уникнемо події торкання і клацання від одночасного запуску на сенсорних пристроях.

;( function( window ) {
// http://stackoverflow.com/a/11381730/989439
function mobilecheck() {
var check = false;
(function(a){if(/(android|ipad|playbook|silk|bb\d+|meego).+mobile|avantgo
|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)
|iris|kindle|lge |maemo|midp|mmp|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4/6)0|symbian|treo
|up\.(browser|link)|vodafone|wap|windows ce|phone)|xda
|xiino/i.test(a)||/1207|6310|6590|3gso|4thp|50[1-6]i
|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)
|aptu|ar(ch|go)|as(te|us)|attw|au(di|\m|r |s )|avan|be(ck|ll|nq)
|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb
|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)
|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)
|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc
|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)
|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c
|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230
|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris
|uk(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt
|kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])
|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)
|mc(01/21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef
|mo(01/02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]
|n20[2-3]|n30(0/2)|n50(0/2/5)|n7(0(0/1)|10)
|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)
|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire
|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07/12/21/32/60
|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)
|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar
|sie(\-|m)|sk\-0|sl(45|id|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18/50)|t6(00/10/18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)
|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst
|v400|v750|veri|vi(rg|te)|vk(40/5[0-3]|\-v)|vm40|voda|vulc
|vx(52/53/60/61/70/80/81/83/85/98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.test(a.substr(0,4)))check = true})(navigator.userAgent||navigator.vendor||window.opera);
return check;
}
// http://www.jonathantneal.com/blog/polyfills-and-prototypes/
!String.prototype.trim && (String.prototype.trim = function() {
return this.replace(/^\s+|\s+$/g, «);
});
function UISearch( el, options ) {
this.el = el;
this.inputEl = el.querySelector( ‘form > input.sb-search-input’ );
this._initEvents();
}
UISearch.prototype = {
_initEvents : function() {
var self = this,
initSearchFn = function( ev ) {
ev.stopPropagation();
// обріжте його значення
self.inputEl.value = self.inputEl.value.trim();
if( !classie.has( self.el, ‘sb-search-open’ ) ) { // відкрийте його
ev.preventDefault();
self.open();
}
else if( classie.has( self.el, ‘sb-search-open’ ) && /^\s*$/.test( self.inputEl.value ) ) { // закрийте його
ev.preventDefault();
self.close();
}
}
this.el.addEventListener. ( ‘click’, initSearchFn );
this.el.addEventListener. ( ‘touchstart’, initSearchFn );
this.inputEl.addEventListener. ( ‘click’, function( ev ) { ev.stopPropagation(); });
this.inputEl.addEventListener. ( ‘touchstart’, function( ev ) { ev.stopPropagation(); } );
},
open : function() {
var self = this;
classie.add( this.el, ‘sb-search-open’ );
// сфокусуйте на вводі
if( !mobilecheck() ) {
this.inputEl.focus();
}
//закрийте enter пошуку, якщо клацання проводиться по тілу
var bodyFn = function( ev ) {
self.close();
this.removeEventListener( ‘click’, bodyFn );
this.removeEventListener( ‘touchstart’, bodyFn );
};
document.addEventListener. ( ‘click’, bodyFn );
document.addEventListener. ( ‘touchstart’, bodyFn );
},
close : function() {
this.inputEl.blur();
classie.remove( this.el, ‘sb-search-open’ );
}
}
// додайте в глобальний простір імен
window.UISearch = UISearch;
} )( window );

Нарешті, для браузерів, які не мають підтримки addEventListener. і removeEventListener, ми застосовуємо полифил EventListener Джонатана Нілу (Jonathan Neal).

// EventListener | @jon_neal | //github.com/jonathantneal/EventListener
!window.addEventListener. & & window.Element && (function () {
function addToPrototype(name, method) {
Window.prototype[name] = HTMLDocument.prototype[name] = Element.prototype[name] = method;
}
var registry = [];
addToPrototype(«addEventListener.», function (type, listener) {
var target = this;
registry.unshift({
__listener: function (event) {
event.currentTarget = target;
event.pageX = event.clientX + document.documentElement.scrollLeft;
event.pageY = event.clientY + document.documentElement.scrollTop;
event.preventDefault = function () { event.returnValue = false };
event.relatedTarget = event.fromElement || null;
event.stopPropagation = function () { event.cancelBubble = true };
event.relatedTarget = event.fromElement || null;
event.target = event.srcElement || target;
event.timeStamp = +new Date;
listener.call(target, event);
},
listener: listener,
target: target,
type: type
});
this.attachEvent(«on» + type, registry[0].__listener);
});
addToPrototype(«removeEventListener», function (type, listener) {
for (var index = 0, length = registry.length; index < length; index++) {
if (registry[index].target == this && registry[index].type == type && registry[index].listener == listener) {
return this.detachEvent(«on» + type, registry.splice(index, 1)[0].__listener);
}
}
});
addToPrototype(«dispatchEvent», function (eventObject) {
try {
return this.fireEvent(«on» + eventObject.type, eventObject);
} catch (error) {
for (var index = 0, length = registry.length; index < length; index++) {
if (registry[index].target == this && registry[index].type == eventObject.type) {
registry[index].call(this, eventObject);
}
}
}
});
})();

От і все! Сподіваюся, вам сподобався цей підручник і ви визнали його корисним!