Added a fixture that has submodules.

This commit is contained in:
joshaber 2016-01-07 13:05:36 -05:00
parent a86d3b6d94
commit 0bef58a8a4
104 changed files with 9897 additions and 0 deletions

View File

@ -0,0 +1,6 @@
[submodule "jstips"]
path = jstips
url = https://github.com/loverajoel/jstips
[submodule "You-Dont-Need-jQuery"]
path = You-Dont-Need-jQuery
url = https://github.com/oneuijs/You-Dont-Need-jQuery

View File

View File

@ -0,0 +1,3 @@
{
presets: ["es2015", "stage-0"]
}

View File

@ -0,0 +1,18 @@
{
"extends": "eslint-config-airbnb",
"env": {
"browser": true,
"mocha": true,
"node": true
},
"rules": {
"valid-jsdoc": 2,
"no-param-reassign": 0,
"comma-dangle": 0,
"one-var": 0,
"no-else-return": 1,
"no-unused-expressions": 0,
"indent": 1,
"eol-last": 0
}
}

View File

@ -0,0 +1,5 @@
.DS_Store
*.log
node_modules
coverage
logs

View File

@ -0,0 +1,10 @@
language: node_js
node_js:
- "5"
- "4"
before_script:
- export DISPLAY=:99.0
- sh -e /etc/init.d/xvfb start
script:
- npm run lint
- npm test

View File

@ -0,0 +1,22 @@
The MIT License (MIT)
Copyright (c) 2015 oneuijs
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@ -0,0 +1,637 @@
> #### You Don't Need jQuery
Tú no necesitas jQuery
---
El desarrollo Frontend evoluciona día a día, y los navegadores modernos ya han implementado nativamente APIs para trabajar con DOM/BOM, las cuales son muy buenas, por lo que definitivamente no es necesario aprender jQuery desde cero para manipular el DOM. En la actualidad, gracias al surgimiento de librerías frontend como React, Angular y Vue, manipular el DOM es contrario a los patrones establecidos, y jQuery se ha vuelto menos importante. Este proyecto resume la mayoría de métodos alternativos a jQuery, pero de forma nativa con soporte IE 10+.
## Tabla de Contenidos
1. [Query Selector](#query-selector)
1. [CSS & Estilo](#css--estilo)
1. [Manipulación DOM](#manipulación-dom)
1. [Ajax](#ajax)
1. [Eventos](#eventos)
1. [Utilidades](#utilidades)
1. [Traducción](#traducción)
1. [Soporte de Navegadores](#soporte-de-navegadores)
## Query Selector
En lugar de los selectores comunes como clase, id o atributos podemos usar `document.querySelector` o `document.querySelectorAll` como alternativas. Las diferencias radican en:
* `document.querySelector` devuelve el primer elemento que cumpla con la condición
* `document.querySelectorAll` devuelve todos los elementos que cumplen con la condición en forma de NodeList. Puede ser convertido a Array usando `[].slice.call(document.querySelectorAll(selector) || []);`
* Si ningún elemento cumple con la condición, jQuery retornaría `[]` mientras la API DOM retornaría `null`. Nótese el NullPointerException. Se puede usar `||` para establecer el valor por defecto al no encontrar elementos, como en `document.querySelectorAll(selector) || []`
> Notice: `document.querySelector` and `document.querySelectorAll` are quite **SLOW**, try to use `getElementById`, `document.getElementsByClassName` o `document.getElementsByTagName` if you want to Obtener a performance bonus.
- [1.0](#1.0) <a name='1.0'></a> Buscar por selector
```js
// jQuery
$('selector');
// Nativo
document.querySelectorAll('selector');
```
- [1.1](#1.1) <a name='1.1'></a> Buscar por Clase
```js
// jQuery
$('.class');
// Nativo
document.querySelectorAll('.class');
// Forma alternativa
document.getElementsByClassName('class');
```
- [1.2](#1.2) <a name='1.2'></a> Buscar por id
```js
// jQuery
$('#id');
// Nativo
document.querySelector('#id');
// Forma alternativa
document.getElementById('id');
```
- [1.3](#1.3) <a name='1.3'></a> Buscar por atributo
```js
// jQuery
$('a[target=_blank]');
// Nativo
document.querySelectorAll('a[target=_blank]');
```
- [1.4](#1.4) <a name='1.4'></a> Buscar
+ Buscar nodos
```js
// jQuery
$el.find('li');
// Nativo
el.querySelectorAll('li');
```
+ Buscar "body"
```js
// jQuery
$('body');
// Nativo
document.body;
```
+ Buscar Atributo
```js
// jQuery
$el.attr('foo');
// Nativo
e.getAttribute('foo');
```
+ Buscar atributo "data"
```js
// jQuery
$el.data('foo');
// Nativo
// Usando getAttribute
el.getAttribute('data-foo');
// También puedes utilizar `dataset` desde IE 11+
el.dataset['foo'];
```
- [1.5](#1.5) <a name='1.5'></a> Elementos Hermanos/Previos/Siguientes
+ Elementos hermanos
```js
// jQuery
$el.siblings();
// Nativo
[].filter.call(el.parentNode.children, function(child) {
return child !== el;
});
```
+ Elementos previos
```js
// jQuery
$el.prev();
// Nativo
el.previousElementSibling;
```
+ Elementos siguientes
```js
// jQuery
$el.next();
// Nativo
el.nextElementSibling;
```
- [1.6](#1.6) <a name='1.6'></a> Closest
Retorna el elemento más cercano que coincida con la condición, partiendo desde el nodo actual hasta document.
```js
// jQuery
$el.closest(queryString);
// Nativo
function closest(el, selector) {
const matchesSelector = el.matches || el.webkitMatchesSelector || el.mozMatchesSelector || el.msMatchesSelector;
while (el) {
if (matchesSelector.call(el, selector)) {
return el;
} else {
el = el.parentElement;
}
}
return null;
}
```
- [1.7](#1.7) <a name='1.7'></a> Parents Until
Obtiene los ancestros de cada elemento en el set actual de elementos que cumplan con la condición, sin incluir el actual
```js
// jQuery
$el.parentsUntil(selector, filter);
// Nativo
function parentsUntil(el, selector, filter) {
const result = [];
const matchesSelector = el.matches || el.webkitMatchesSelector || el.mozMatchesSelector || el.msMatchesSelector;
// Partir desde el elemento padre
el = el.parentElement;
while (el && !matchesSelector.call(el, selector)) {
if (!filter) {
result.push(el);
} else {
if (matchesSelector.call(el, filter)) {
result.push(el);
}
}
el = el.parentElement;
}
return result;
}
```
- [1.8](#1.8) <a name='1.8'></a> Formularios
+ Input/Textarea
```js
// jQuery
$('#my-input').val();
// Nativo
document.querySelector('#my-input').value;
```
+ Obtener el índice de e.currentTarget en `.radio`
```js
// jQuery
$(e.currentTarget).index('.radio');
// Nativo
[].indexOf.call(document.querySelectAll('.radio'), e.currentTarget);
```
- [1.9](#1.9) <a name='1.9'></a> Contenidos de Iframe
`$('iframe').contents()` devuelve `contentDocument` para este iframe específico
+ Contenidos de Iframe
```js
// jQuery
$iframe.contents();
// Nativo
iframe.contentDocument;
```
+ Buscar dentro de un Iframe
```js
// jQuery
$iframe.contents().find('.css');
// Nativo
iframe.contentDocument.querySelectorAll('.css');
```
**[⬆ volver al inicio](#tabla-de-contenidos)**
## CSS & Estilo
- [2.1](#2.1) <a name='2.1'></a> CSS
+ Obtener Estilo
```js
// jQuery
$el.css("color");
// Nativo
// NOTA: Bug conocido, retornará 'auto' si el valor de estilo es 'auto'
const win = el.ownerDocument.defaultView;
// null significa que no tiene pseudo estilos
win.getComputedStyle(el, null).color;
```
+ Establecer style
```js
// jQuery
$el.css({ color: "#ff0011" });
// Nativo
el.style.color = '#ff0011';
```
+ Obtener/Establecer Estilos
Nótese que si se desea establecer múltiples estilos a la vez, se puede utilizar el método [setStyles](https://github.com/oneuijs/oui-dom-utils/blob/master/src/index.js#L194) en el paquete oui-dom-utils.
+ Agregar clase
```js
// jQuery
$el.addClass(className);
// Nativo
el.classList.add(className);
```
+ Quitar Clase
```js
// jQuery
$el.removeClass(className);
// Nativo
el.classList.remove(className);
```
+ Consultar si tiene clase
```js
// jQuery
$el.hasClass(className);
// Nativo
el.classList.contains(className);
```
+ Toggle class
```js
// jQuery
$el.toggleClass(className);
// Nativo
el.classList.toggle(className);
```
- [2.2](#2.2) <a name='2.2'></a> Width & Height
Ancho y Alto son teóricamente idénticos. Usaremos el Alto como ejemplo:
+ Alto de Ventana
```js
// alto de ventana
$(window).height();
// Sin scrollbar, se comporta como jQuery
window.document.documentElement.clientHeight;
// Con scrollbar
window.innerHeight;
```
+ Alto de Documento
```js
// jQuery
$(document).height();
// Nativo
document.documentElement.scrollHeight;
```
+ Alto de Elemento
```js
// jQuery
$el.height();
// Nativo
function getHeight(el) {
const styles = this.getComputedStyles(el);
const height = el.offsetHeight;
const borderTopWidth = parseFloat(styles.borderTopWidth);
const borderBottomWidth = parseFloat(styles.borderBottomWidth);
const paddingTop = parseFloat(styles.paddingTop);
const paddingBottom = parseFloat(styles.paddingBottom);
return height - borderBottomWidth - borderTopWidth - paddingTop - paddingBottom;
}
// Precisión de integerwhen `border-box`, it's `height`; when `content-box`, it's `height + padding + border`
el.clientHeight;
// Precisión de decimalwhen `border-box`, it's `height`; when `content-box`, it's `height + padding + border`
el.getBoundingClientRect().height;
```
- [2.3](#2.3) <a name='2.3'></a> Posición & Offset
+ Posición
```js
// jQuery
$el.position();
// Nativo
{ left: el.offsetLeft, top: el.offsetTop }
```
+ Offset
```js
// jQuery
$el.offset();
// Nativo
function getOffset (el) {
const box = el.getBoundingClientRect();
return {
top: box.top + window.pageYOffset - document.documentElement.clientTop,
left: box.left + window.pageXOffset - document.documentElement.clientLeft
}
}
```
- [2.4](#2.4) <a name='2.4'></a> Posición del Scroll Vertical
```js
// jQuery
$(window).scrollTop();
// Nativo
(document.documentElement && document.documentElement.scrollTop) || document.body.scrollTop;
```
**[⬆ volver al inicio](#tabla-de-contenidos)**
## Manipulación DOM
- [3.1](#3.1) <a name='3.1'></a> Remove
```js
// jQuery
$el.remove();
// Nativo
el.parentNode.removeChild(el);
```
- [3.2](#3.2) <a name='3.2'></a> Text
+ Obtener Texto
```js
// jQuery
$el.text();
// Nativo
el.textContent;
```
+ Establecer Texto
```js
// jQuery
$el.text(string);
// Nativo
el.textContent = string;
```
- [3.3](#3.3) <a name='3.3'></a> HTML
+ Obtener HTML
```js
// jQuery
$el.html();
// Nativo
el.innerHTML;
```
+ Establecer HTML
```js
// jQuery
$el.html(htmlString);
// Nativo
el.innerHTML = htmlString;
```
- [3.4](#3.4) <a name='3.4'></a> Append
Añadir elemento hijo después del último hijo del elemento padre
```js
// jQuery
$el.append("<div id='container'>hello</div>");
// Nativo
el.insertAdjacentHTML("beforeend","<div id='container'>hello</div>");
```
- [3.5](#3.5) <a name='3.5'></a> Prepend
Añadir elemento hijo después del último hijo del elemento padre
```js
// jQuery
$el.prepend("<div id='container'>hello</div>");
// Nativo
el.insertAdjacentHTML("afterbegin","<div id='container'>hello</div>");
```
- [3.6](#3.6) <a name='3.6'></a> insertBefore
Insertar un nuevo nodo antes del primero de los elementos seleccionados
```js
// jQuery
$newEl.insertBefore(queryString);
// Nativo
const target = document.querySelector(queryString);
target.parentNode.insertBefore(newEl, target);
```
- [3.7](#3.7) <a name='3.7'></a> insertAfter
Insertar un nuevo nodo después de los elementos seleccionados
```js
// jQuery
$newEl.insertAfter(queryString);
// Nativo
const target = document.querySelector(queryString);
target.parentNode.insertBefore(newEl, target.nextSibling);
```
**[⬆ volver al inicio](#tabla-de-contenidos)**
## Ajax
Reemplazar con [fetch](https://github.com/camsong/fetch-ie8) y [fetch-jsonp](https://github.com/camsong/fetch-jsonp)
+[Fetch API](https://fetch.spec.whatwg.org/) es el nuevo estándar quue reemplaza a XMLHttpRequest para efectuar peticiones AJAX. Funciona en Chrome y Firefox, como también es posible usar un polyfill en otros navegadores.
+
+Es una buena alternativa utilizar [github/fetch](http://github.com/github/fetch) en IE9+ o [fetch-ie8](https://github.com/camsong/fetch-ie8/) en IE8+, [fetch-jsonp](https://github.com/camsong/fetch-jsonp) para efectuar peticiones JSONP.
**[⬆ volver al inicio](#tabla-de-contenidos)**
## Eventos
Para un reemplazo completo con namespace y delegación, utilizar https://github.com/oneuijs/oui-dom-events
- [5.1](#5.1) <a name='5.1'></a> Asignar un evento con "on"
```js
// jQuery
$el.on(eventName, eventHandler);
// Nativo
el.addEventListener(eventName, eventHandler);
```
- [5.2](#5.2) <a name='5.2'></a> Desasignar un evento con "off"
```js
// jQuery
$el.off(eventName, eventHandler);
// Nativo
el.removeEventListener(eventName, eventHandler);
```
- [5.3](#5.3) <a name='5.3'></a> Trigger
```js
// jQuery
$(el).trigger('custom-event', {key1: 'data'});
// Nativo
if (window.CustomEvent) {
const event = new CustomEvent('custom-event', {detail: {key1: 'data'}});
} else {
const event = document.createEvent('CustomEvent');
event.initCustomEvent('custom-event', true, true, {key1: 'data'});
}
el.dispatchEvent(event);
```
**[⬆ volver al inicio](#tabla-de-contenidos)**
## Utilidades
- [6.1](#6.1) <a name='6.1'></a> isArray
```js
// jQuery
$.isArray(range);
// Nativo
Array.isArray(range);
```
- [6.2](#6.2) <a name='6.2'></a> Trim
```js
// jQuery
$.trim(string);
// Nativo
string.trim();
```
- [6.3](#6.3) <a name='6.3'></a> Object Assign
Utilizar polyfill para object.assign https://github.com/ljharb/object.assign
```js
// jQuery
$.extend({}, defaultOpts, opts);
// Nativo
Object.assign({}, defaultOpts, opts);
```
- [6.4](#6.4) <a name='6.4'></a> Contains
```js
// jQuery
$.contains(el, child);
// Nativo
el !== child && el.contains(child);
```
**[⬆ volver al inicio](#tabla-de-contenidos)**
## Traducción
* [한국어](./README.ko-KR.md)
* [简体中文](./README.zh-CN.md)
* [Bahasa Melayu](./README-my.md)
* [Bahasa Indonesia](./README-id.md)
* [Português(PT-BR)](./README.pt-BR.md)
* [Tiếng Việt Nam](./README-vi.md)
* [Español](./README-es.md)
* [Русский](./README-ru.md)
* [Türkçe](./README-tr.md)
## Soporte de Navegadores
![Chrome](https://raw.github.com/alrra/browser-logos/master/chrome/chrome_48x48.png) | ![Firefox](https://raw.github.com/alrra/browser-logos/master/firefox/firefox_48x48.png) | ![IE](https://raw.github.com/alrra/browser-logos/master/internet-explorer/internet-explorer_48x48.png) | ![Opera](https://raw.github.com/alrra/browser-logos/master/opera/opera_48x48.png) | ![Safari](https://raw.github.com/alrra/browser-logos/master/safari/safari_48x48.png)
--- | --- | --- | --- | --- |
Última ✔ | Última ✔ | 10+ ✔ | Última ✔ | 6.1+ ✔ |
# Licencia
MIT

View File

@ -0,0 +1,634 @@
## Anda tidak memerlukan jQuery
Dewasa ini perkembangan environment frontend sangatlah pesat, dimana banyak browser sudah mengimplementasikan DOM/BOM APIs dengan baik. Kita tidak perlu lagi belajar jQuery dari nol untuk keperluan manipulasi DOM atau events. Disaat yang sama; dengan berterimakasih kepada library frontend terkini seperti React, Angular dan Vue; Memanipulasi DOM secara langsung telah menjadi anti-pattern alias sesuatu yang tidak perlu dilakukan. Dengan kata lain, jQuery sekarang menjadi semakin tidak diperlukan. Projek ini memberikan informasi mengenai metode alternatif dari jQuery untuk implementasi Native dengan support untuk browser IE 10+.
## Daftar Isi
1. [Query Selector](#query-selector)
1. [CSS & Style](#css-style)
1. [DOM Manipulation](#dom-manipulation)
1. [Ajax](#ajax)
1. [Events](#events)
1. [Utilities](#utilities)
1. [Translation](#translation)
1. [Browser Support](#browser-yang-di-support)
## Query Selector
Untuk selector-selector umum seperti class, id atau attribute, kita dapat menggunakan `document.querySelector` atau `document.querySelectorAll` sebagai pengganti. Perbedaan diantaranya adalah:
* `document.querySelector` mengembalikan elemen pertama yang cocok
* `document.querySelectorAll` mengembalikan semua elemen yang cocok sebagai NodeList. Hasilnya bisa dikonversikan menjadi Array `[].slice.call(document.querySelectorAll(selector) || []);`
* Bila tidak ada hasil pengembalian elemen yang cocok, jQuery akan mengembalikan `[]` sedangkan DOM API akan mengembalikan `null`. Mohon diperhatikan mengenai Null Pointer Exception. Anda juga bisa menggunakan operator `||` untuk set nilai awal jika hasil pencarian tidak ditemukan : `document.querySelectorAll(selector) || []`
> Perhatian: `document.querySelector` dan `document.querySelectorAll` sedikit **LAMBAT**. Silahkan menggunakan `getElementById`, `document.getElementsByClassName` atau `document.getElementsByTagName` jika anda menginginkan tambahan performa.
- [1.0](#1.0) <a name='1.0'></a> Query by selector
```js
// jQuery
$('selector');
// Native
document.querySelectorAll('selector');
```
- [1.1](#1.1) <a name='1.1'></a> Query by class
```js
// jQuery
$('.class');
// Native
document.querySelectorAll('.class');
// or
document.getElementsByClassName('class');
```
- [1.2](#1.2) <a name='1.2'></a> Query by id
```js
// jQuery
$('#id');
// Native
document.querySelector('#id');
// or
document.getElementById('id');
```
- [1.3](#1.3) <a name='1.3'></a> Query menggunakan attribute
```js
// jQuery
$('a[target=_blank]');
// Native
document.querySelectorAll('a[target=_blank]');
```
- [1.4](#1.4) <a name='1.4'></a> Pencarian.
+ Mencari nodes
```js
// jQuery
$el.find('li');
// Native
el.querySelectorAll('li');
```
+ Mencari body
```js
// jQuery
$('body');
// Native
document.body;
```
+ Mencari Attribute
```js
// jQuery
$el.attr('foo');
// Native
e.getAttribute('foo');
```
+ Mencari data attribute
```js
// jQuery
$el.data('foo');
// Native
// gunakan getAttribute
el.getAttribute('data-foo');
// anda juga bisa menggunakan `dataset` bila anda perlu support IE 11+
el.dataset['foo'];
```
- [1.5](#1.5) <a name='1.5'></a> Elemen-elemen Sibling/Previous/Next
+ Elemen Sibling
```js
// jQuery
$el.siblings();
// Native
[].filter.call(el.parentNode.children, function(child) {
return child !== el;
});
```
+ Elemen Previous
```js
// jQuery
$el.prev();
// Native
el.previousElementSibling;
```
+ Elemen Next
```js
// next
$el.next();
el.nextElementSibling;
```
- [1.6](#1.6) <a name='1.6'></a> Closest
Mengembalikan elemen pertama yang cocok dari selector yang digunakan, dengan cara mencari mulai dari elemen-sekarang sampai ke document.
```js
// jQuery
$el.closest(queryString);
// Native
function closest(el, selector) {
const matchesSelector = el.matches || el.webkitMatchesSelector || el.mozMatchesSelector || el.msMatchesSelector;
while (el) {
if (matchesSelector.call(el, selector)) {
return el;
} else {
el = el.parentElement;
}
}
return null;
}
```
- [1.7](#1.7) <a name='1.7'></a> Parents Until
Digunakan untuk mendapatkan "ancestor" dari setiap elemen yang ditemukan. Namun tidak termasuk elemen-sekarang yang didapat dari pencarian oleh selector, DOM node, atau object jQuery.
```js
// jQuery
$el.parentsUntil(selector, filter);
// Native
function parentsUntil(el, selector, filter) {
const result = [];
const matchesSelector = el.matches || el.webkitMatchesSelector || el.mozMatchesSelector || el.msMatchesSelector;
// match start from parent
el = el.parentElement;
while (el && !matchesSelector.call(el, selector)) {
if (!filter) {
result.push(el);
} else {
if (matchesSelector.call(el, filter)) {
result.push(el);
}
}
el = el.parentElement;
}
return result;
}
```
- [1.8](#1.8) <a name='1.8'></a> Form
+ Input/Textarea
```js
// jQuery
$('#my-input').val();
// Native
document.querySelector('#my-input').value;
```
+ Get index of e.currentTarget between `.radio`
```js
// jQuery
$(e.currentTarget).index('.radio');
// Native
[].indexOf.call(document.querySelectAll('.radio'), e.currentTarget);
```
- [1.9](#1.9) <a name='1.9'></a> Iframe Contents
`$('iframe').contents()` mengembalikan `contentDocument`
+ Iframe contents
```js
// jQuery
$iframe.contents();
// Native
iframe.contentDocument;
```
+ Iframe Query
```js
// jQuery
$iframe.contents().find('.css');
// Native
iframe.contentDocument.querySelectorAll('.css');
```
**[⬆ back to top](#daftar-isi)**
## CSS Style
- [2.1](#2.1) <a name='2.1'></a> CSS
+ Get style
```js
// jQuery
$el.css("color");
// Native
// PERHATIAN: ada bug disini, dimana fungsi ini akan mengembalikan nilai 'auto' bila nilai dari atribut style adalah 'auto'
const win = el.ownerDocument.defaultView;
// null artinya tidak mengembalikan pseudo styles
win.getComputedStyle(el, null).color;
```
+ Set style
```js
// jQuery
$el.css({ color: "#ff0011" });
// Native
el.style.color = '#ff0011';
```
+ Get/Set Styles
Mohon dicatat jika anda ingin men-set banyak style bersamaan, anda dapat menemukan referensi di metode [setStyles](https://github.com/oneuijs/oui-dom-utils/blob/master/src/index.js#L194) pada package oui-dom-utils
+ Add class
```js
// jQuery
$el.addClass(className);
// Native
el.classList.add(className);
```
+ Remove class
```js
// jQuery
$el.removeClass(className);
// Native
el.classList.remove(className);
```
+ has class
```js
// jQuery
$el.hasClass(className);
// Native
el.classList.contains(className);
```
+ Toggle class
```js
// jQuery
$el.toggleClass(className);
// Native
el.classList.toggle(className);
```
- [2.2](#2.2) <a name='2.2'></a> Width & Height
Secara teori, width dan height identik, contohnya Height:
+ Window height
```js
// window height
$(window).height();
// without scrollbar, behaves like jQuery
window.document.documentElement.clientHeight;
// with scrollbar
window.innerHeight;
```
+ Document height
```js
// jQuery
$(document).height();
// Native
document.documentElement.scrollHeight;
```
+ Element height
```js
// jQuery
$el.height();
// Native
function getHeight(el) {
const styles = this.getComputedStyles(el);
const height = el.offsetHeight;
const borderTopWidth = parseFloat(styles.borderTopWidth);
const borderBottomWidth = parseFloat(styles.borderBottomWidth);
const paddingTop = parseFloat(styles.paddingTop);
const paddingBottom = parseFloat(styles.paddingBottom);
return height - borderBottomWidth - borderTopWidth - paddingTop - paddingBottom;
}
// accurate to integerwhen `border-box`, it's `height`; when `content-box`, it's `height + padding + border`
el.clientHeight;
// accurate to decimalwhen `border-box`, it's `height`; when `content-box`, it's `height + padding + border`
el.getBoundingClientRect().height;
```
- [2.3](#2.3) <a name='2.3'></a> Position & Offset
+ Position
```js
// jQuery
$el.position();
// Native
{ left: el.offsetLeft, top: el.offsetTop }
```
+ Offset
```js
// jQuery
$el.offset();
// Native
function getOffset (el) {
const box = el.getBoundingClientRect();
return {
top: box.top + window.pageYOffset - document.documentElement.clientTop,
left: box.left + window.pageXOffset - document.documentElement.clientLeft
}
}
```
- [2.4](#2.4) <a name='2.4'></a> Scroll Top
```js
// jQuery
$(window).scrollTop();
// Native
(document.documentElement && document.documentElement.scrollTop) || document.body.scrollTop;
```
**[⬆ back to top](#daftar-isi)**
## DOM Manipulation
- [3.1](#3.1) <a name='3.1'></a> Remove
```js
// jQuery
$el.remove();
// Native
el.parentNode.removeChild(el);
```
- [3.2](#3.2) <a name='3.2'></a> Text
+ Get text
```js
// jQuery
$el.text();
// Native
el.textContent;
```
+ Set text
```js
// jQuery
$el.text(string);
// Native
el.textContent = string;
```
- [3.3](#3.3) <a name='3.3'></a> HTML
+ Get HTML
```js
// jQuery
$el.html();
// Native
el.innerHTML;
```
+ Set HTML
```js
// jQuery
$el.html(htmlString);
// Native
el.innerHTML = htmlString;
```
- [3.4](#3.4) <a name='3.4'></a> Append
Menambahkan elemen-anak setelah anak terakhir dari elemen-parent
```js
// jQuery
$el.append("<div id='container'>hello</div>");
// Native
let newEl = document.createElement('div');
newEl.setAttribute('id', 'container');
newEl.innerHTML = 'hello';
el.appendChild(newEl);
```
- [3.5](#3.5) <a name='3.5'></a> Prepend
```js
// jQuery
$el.prepend("<div id='container'>hello</div>");
// Native
let newEl = document.createElement('div');
newEl.setAttribute('id', 'container');
newEl.innerHTML = 'hello';
el.insertBefore(newEl, el.firstChild);
```
- [3.6](#3.6) <a name='3.6'></a> insertBefore
Memasukkan node baru sebelum elemen yang dipilih.
```js
// jQuery
$newEl.insertBefore(queryString);
// Native
const target = document.querySelector(queryString);
target.parentNode.insertBefore(newEl, target);
```
- [3.7](#3.7) <a name='3.7'></a> insertAfter
Memasukkan node baru sesudah elemen yang dipilih.
```js
// jQuery
$newEl.insertAfter(queryString);
// Native
const target = document.querySelector(queryString);
target.parentNode.insertBefore(newEl, target.nextSibling);
```
**[⬆ back to top](#daftar-isi)**
## Ajax
Gantikan dengan [fetch](https://github.com/camsong/fetch-ie8) dan [fetch-jsonp](https://github.com/camsong/fetch-jsonp)
**[⬆ back to top](#daftar-isi)**
## Events
Untuk penggantian secara menyeluruh dengan namespace dan delegation, rujuk ke https://github.com/oneuijs/oui-dom-events
- [5.1](#5.1) <a name='5.1'></a> Bind event dengan menggunakan on
```js
// jQuery
$el.on(eventName, eventHandler);
// Native
el.addEventListener(eventName, eventHandler);
```
- [5.2](#5.2) <a name='5.2'></a> Unbind event dengan menggunakan off
```js
// jQuery
$el.off(eventName, eventHandler);
// Native
el.removeEventListener(eventName, eventHandler);
```
- [5.3](#5.3) <a name='5.3'></a> Trigger
```js
// jQuery
$(el).trigger('custom-event', {key1: 'data'});
// Native
if (window.CustomEvent) {
const event = new CustomEvent('custom-event', {detail: {key1: 'data'}});
} else {
const event = document.createEvent('CustomEvent');
event.initCustomEvent('custom-event', true, true, {key1: 'data'});
}
el.dispatchEvent(event);
```
**[⬆ back to top](#daftar-isi)**
## Utilities
- [6.1](#6.1) <a name='6.1'></a> isArray
```js
// jQuery
$.isArray(range);
// Native
Array.isArray(range);
```
- [6.2](#6.2) <a name='6.2'></a> Trim
```js
// jQuery
$.trim(string);
// Native
string.trim();
```
- [6.3](#6.3) <a name='6.3'></a> Object Assign
Extend, use object.assign polyfill https://github.com/ljharb/object.assign
```js
// jQuery
$.extend({}, defaultOpts, opts);
// Native
Object.assign({}, defaultOpts, opts);
```
- [6.4](#6.4) <a name='6.4'></a> Contains
```js
// jQuery
$.contains(el, child);
// Native
el !== child && el.contains(child);
```
**[⬆ back to top](#daftar-isi)**
## Terjemahan
* [한국어](./README.ko-KR.md)
* [简体中文](./README.zh-CN.md)
* [Bahasa Melayu](./README-my.md)
* [Bahasa Indonesia](./README-id.md)
* [Português(PT-BR)](./README.pt-BR.md)
* [Tiếng Việt Nam](./README-vi.md)
* [Русский](./README-ru.md)
* [Türkçe](./README-tr.md)
## Browser yang di Support
![Chrome](https://raw.github.com/alrra/browser-logos/master/chrome/chrome_48x48.png) | ![Firefox](https://raw.github.com/alrra/browser-logos/master/firefox/firefox_48x48.png) | ![IE](https://raw.github.com/alrra/browser-logos/master/internet-explorer/internet-explorer_48x48.png) | ![Opera](https://raw.github.com/alrra/browser-logos/master/opera/opera_48x48.png) | ![Safari](https://raw.github.com/alrra/browser-logos/master/safari/safari_48x48.png)
--- | --- | --- | --- | --- |
Latest ✔ | Latest ✔ | 10+ ✔ | Latest ✔ | 6.1+ ✔ |
# License
MIT

View File

@ -0,0 +1,651 @@
## Non hai bisogno di jQuery
Il mondo del Frontend si evolve rapidamente oggigiorno, i browsers moderni hanno gia' implementato un'ampia gamma di DOM/BOM API soddisfacenti. Non dobbiamo imparare jQuery dalle fondamenta per la manipolazione del DOM o di eventi. Nel frattempo, grazie al prevalicare di librerie per il frontend come React, Angular a Vue, manipolare il DOM direttamente diventa un anti-pattern, di consequenza jQuery non e' mai stato meno importante. Questo progetto sommarizza la maggior parte dei metodi e implementazioni alternative a jQuery, con il supporto di IE 10+.
## Tabella contenuti
1. [Query Selector](#query-selector)
1. [CSS & Style](#css--style)
1. [Manipolazione DOM](#manipolazione-dom)
1. [Ajax](#ajax)
1. [Eventi](#eventi)
1. [Utilities](#utilities)
1. [Alternative](#alternative)
1. [Traduzioni](#traduzioni)
1. [Supporto Browsers](#supporto-browsers)
## Query Selector
Al posto di comuni selettori come class, id o attributi possiamo usare `document.querySelector` o `document.querySelectorAll` per sostituzioni. La differenza risiede in:
* `document.querySelector` restituisce il primo elemento combiaciante
* `document.querySelectorAll` restituisce tutti gli elementi combiacianti della NodeList. Puo' essere convertito in Array usando `[].slice.call(document.querySelectorAll(selector) || []);`
* Se nessun elemento combiacia, jQuery restituitirebbe `[]` li' dove il DOM API ritornera' `null`. Prestate attenzione al Null Pointer Exception. Potete anche usare `||` per settare valori di default se non trovato, come `document.querySelectorAll(selector) || []`
> Notare: `document.querySelector` e `document.querySelectorAll` sono abbastanza **SLOW**, provate ad usare `getElementById`, `document.getElementsByClassName` o `document.getElementsByTagName` se volete avere un bonus in termini di performance.
- [1.0](#1.0) <a name='1.0'></a> Query da selettore
```js
// jQuery
$('selector');
// Nativo
document.querySelectorAll('selector');
```
- [1.1](#1.1) <a name='1.1'></a> Query da classe
```js
// jQuery
$('.class');
// Nativo
document.querySelectorAll('.class');
// or
document.getElementsByClassName('class');
```
- [1.2](#1.2) <a name='1.2'></a> Query da id
```js
// jQuery
$('#id');
// Nativo
document.querySelector('#id');
// o
document.getElementById('id');
```
- [1.3](#1.3) <a name='1.3'></a> Query da attributo
```js
// jQuery
$('a[target=_blank]');
// Nativo
document.querySelectorAll('a[target=_blank]');
```
- [1.4](#1.4) <a name='1.4'></a> Trovare qualcosa.
+ Trovare nodes
```js
// jQuery
$el.find('li');
// Nativo
el.querySelectorAll('li');
```
+ Trovare body
```js
// jQuery
$('body');
// Nativo
document.body;
```
+ Trovare Attributi
```js
// jQuery
$el.attr('foo');
// Nativo
e.getAttribute('foo');
```
+ Trovare attributo data
```js
// jQuery
$el.data('foo');
// Nativo
// using getAttribute
el.getAttribute('data-foo');
// potete usare `dataset` solo se supportate IE 11+
el.dataset['foo'];
```
- [1.5](#1.5) <a name='1.5'></a> Fratelli/Precedento/Successivo Elemento
+ Elementi fratelli
```js
// jQuery
$el.siblings();
// Nativo
[].filter.call(el.parentNode.children, function(child) {
return child !== el;
});
```
+ Elementi precedenti
```js
// jQuery
$el.prev();
// Nativo
el.previousElementSibling;
```
+ Elementi successivi
```js
// jQuery
$el.next();
// Nativo
el.nextElementSibling;
```
- [1.6](#1.6) <a name='1.6'></a> Il piu' vicino
Restituisce il primo elementi combiaciante il selettore fornito, attraversando dall'elemento corrente fino al document .
```js
// jQuery
$el.closest(queryString);
// Nativo - Solo ultimo, NO IE
el.closest(selector);
// Nativo - IE10+
function closest(el, selector) {
const matchesSelector = el.matches || el.webkitMatchesSelector || el.mozMatchesSelector || el.msMatchesSelector;
while (el) {
if (matchesSelector.call(el, selector)) {
return el;
} else {
el = el.parentElement;
}
}
return null;
}
```
- [1.7](#1.7) <a name='1.7'></a> Fino a parenti
Ottiene il parente di ogni elemento nel set corrente di elementi combiacianti, fino a ma non incluso, l'elemento combiaciante il selettorer, DOM node, o jQuery object.
```js
// jQuery
$el.parentsUntil(selector, filter);
// Nativo
function parentsUntil(el, selector, filter) {
const result = [];
const matchesSelector = el.matches || el.webkitMatchesSelector || el.mozMatchesSelector || el.msMatchesSelector;
// il match parte dal parente
el = el.parentElement;
while (el && !matchesSelector.call(el, selector)) {
if (!filter) {
result.push(el);
} else {
if (matchesSelector.call(el, filter)) {
result.push(el);
}
}
el = el.parentElement;
}
return result;
}
```
- [1.8](#1.8) <a name='1.8'></a> Form
+ Input/Textarea
```js
// jQuery
$('#my-input').val();
// Native
document.querySelector('#my-input').value;
```
+ Get index of e.currentTarget between `.radio`
```js
// jQuery
$(e.currentTarget).index('.radio');
// Nativo
[].indexOf.call(document.querySelectAll('.radio'), e.currentTarget);
```
- [1.9](#1.9) <a name='1.9'></a> Iframe Contents
`$('iframe').contents()` restituisce `contentDocument` per questo specifico iframe
+ Iframe contenuti
```js
// jQuery
$iframe.contents();
// Nativo
iframe.contentDocument;
```
+ Iframe Query
```js
// jQuery
$iframe.contents().find('.css');
// Nativo
iframe.contentDocument.querySelectorAll('.css');
```
**[⬆ back to top](#table-of-contents)**
## CSS & Style
- [2.1](#2.1) <a name='2.1'></a> CSS
+ Ottenere style
```js
// jQuery
$el.css("color");
// Nativo
// NOTA: Bug conosciuto, restituira' 'auto' se il valore di style e' 'auto'
const win = el.ownerDocument.defaultView;
// null significa che non restituira' lo psuedo style
win.getComputedStyle(el, null).color;
```
+ Settare style
```js
// jQuery
$el.css({ color: "#ff0011" });
// Nativo
el.style.color = '#ff0011';
```
+ Ottenere/Settare Styles
Nota che se volete settare styles multipli in una sola volta, potete riferire [setStyles](https://github.com/oneuijs/oui-dom-utils/blob/master/src/index.js#L194) metodo in oui-dom-utils package.
+ Aggiungere classe
```js
// jQuery
$el.addClass(className);
// Nativo
el.classList.add(className);
```
+ Rimouvere class
```js
// jQuery
$el.removeClass(className);
// Nativo
el.classList.remove(className);
```
+ has class
```js
// jQuery
$el.hasClass(className);
// Nativo
el.classList.contains(className);
```
+ Toggle class
```js
// jQuery
$el.toggleClass(className);
// Nativo
el.classList.toggle(className);
```
- [2.2](#2.2) <a name='2.2'></a> Width & Height
Width e Height sono teoricamente identici, prendendo Height come esempio:
+ Window height
```js
// window height
$(window).height();
// senza scrollbar, si comporta comporta jQuery
window.document.documentElement.clientHeight;
// con scrollbar
window.innerHeight;
```
+ Document height
```js
// jQuery
$(document).height();
// Nativo
document.documentElement.scrollHeight;
```
+ Element height
```js
// jQuery
$el.height();
// Nativo
function getHeight(el) {
const styles = this.getComputedStyles(el);
const height = el.offsetHeight;
const borderTopWidth = parseFloat(styles.borderTopWidth);
const borderBottomWidth = parseFloat(styles.borderBottomWidth);
const paddingTop = parseFloat(styles.paddingTop);
const paddingBottom = parseFloat(styles.paddingBottom);
return height - borderBottomWidth - borderTopWidth - paddingTop - paddingBottom;
}
// preciso a interoquando `border-box`, e' `height`; quando `content-box`, e' `height + padding + border`
el.clientHeight;
// preciso a decimalequando `border-box`, e' `height`; quando `content-box`, e' `height + padding + border`
el.getBoundingClientRect().height;
```
- [2.3](#2.3) <a name='2.3'></a> Position & Offset
+ Position
```js
// jQuery
$el.position();
// Nativo
{ left: el.offsetLeft, top: el.offsetTop }
```
+ Offset
```js
// jQuery
$el.offset();
// Nativo
function getOffset (el) {
const box = el.getBoundingClientRect();
return {
top: box.top + window.pageYOffset - document.documentElement.clientTop,
left: box.left + window.pageXOffset - document.documentElement.clientLeft
}
}
```
- [2.4](#2.4) <a name='2.4'></a> Scroll Top
```js
// jQuery
$(window).scrollTop();
// Nativo
(document.documentElement && document.documentElement.scrollTop) || document.body.scrollTop;
```
**[⬆ back to top](#table-of-contents)**
## Manipolazione DOM
- [3.1](#3.1) <a name='3.1'></a> Remove
```js
// jQuery
$el.remove();
// Nativo
el.parentNode.removeChild(el);
```
- [3.2](#3.2) <a name='3.2'></a> Text
+ Get text
```js
// jQuery
$el.text();
// Nativo
el.textContent;
```
+ Set text
```js
// jQuery
$el.text(string);
// Nativo
el.textContent = string;
```
- [3.3](#3.3) <a name='3.3'></a> HTML
+ Ottenere HTML
```js
// jQuery
$el.html();
// Nativo
el.innerHTML;
```
+ Settare HTML
```js
// jQuery
$el.html(htmlString);
// Nativo
el.innerHTML = htmlString;
```
- [3.4](#3.4) <a name='3.4'></a> Append
appendere elemento figlio dopo l'ultimo elemento figlio del genitore
```js
// jQuery
$el.append("<div id='container'>hello</div>");
// Nativo
el.insertAdjacentHTML("beforeend","<div id='container'>hello</div>");
```
- [3.5](#3.5) <a name='3.5'></a> Prepend
```js
// jQuery
$el.prepend("<div id='container'>hello</div>");
// Nativo
el.insertAdjacentHTML("afterbegin","<div id='container'>hello</div>");
```
- [3.6](#3.6) <a name='3.6'></a> insertBefore
Inserire un nuovo node dopo l'elmento selezionato
```js
// jQuery
$newEl.insertBefore(queryString);
// Nativo
const target = document.querySelector(queryString);
target.parentNode.insertBefore(newEl, target);
```
- [3.7](#3.7) <a name='3.7'></a> insertAfter
Insert a new node after the selected elements
```js
// jQuery
$newEl.insertAfter(queryString);
// Nativo
const target = document.querySelector(queryString);
target.parentNode.insertBefore(newEl, target.nextSibling);
```
- [3.8](#3.8) <a name='3.8'></a> is
Restituisce `true` se combacia con l'elemento selezionato
```js
// jQuery - Notare `is` funziona anche con `function` o `elements` non di importanza qui
$el.is(selector);
// Nativo
el.matches(selector);
```
**[⬆ back to top](#table-of-contents)**
## Ajax
Sostituire con [fetch](https://github.com/camsong/fetch-ie8) and [fetch-jsonp](https://github.com/camsong/fetch-jsonp)
**[⬆ back to top](#table-of-contents)**
## Eventi
Per una completa sostituzione con namespace e delegation, riferire a https://github.com/oneuijs/oui-dom-events
- [5.1](#5.1) <a name='5.1'></a> Bind un evento con on
```js
// jQuery
$el.on(eventName, eventHandler);
// Nativo
el.addEventListener(eventName, eventHandler);
```
- [5.2](#5.2) <a name='5.2'></a> Unbind an event with off
```js
// jQuery
$el.off(eventName, eventHandler);
// Nativo
el.removeEventListener(eventName, eventHandler);
```
- [5.3](#5.3) <a name='5.3'></a> Trigger
```js
// jQuery
$(el).trigger('custom-event', {key1: 'data'});
// Nativo
if (window.CustomEvent) {
const event = new CustomEvent('custom-event', {detail: {key1: 'data'}});
} else {
const event = document.createEvent('CustomEvent');
event.initCustomEvent('custom-event', true, true, {key1: 'data'});
}
el.dispatchEvent(event);
```
**[⬆ back to top](#table-of-contents)**
## Utilities
- [6.1](#6.1) <a name='6.1'></a> isArray
```js
// jQuery
$.isArray(range);
// Nativo
Array.isArray(range);
```
- [6.2](#6.2) <a name='6.2'></a> Trim
```js
// jQuery
$.trim(string);
// Nativo
string.trim();
```
- [6.3](#6.3) <a name='6.3'></a> Object Assign
Extend, usa object.assign polyfill https://github.com/ljharb/object.assign
```js
// jQuery
$.extend({}, defaultOpts, opts);
// Nativo
Object.assign({}, defaultOpts, opts);
```
- [6.4](#6.4) <a name='6.4'></a> Contains
```js
// jQuery
$.contains(el, child);
// Nativo
el !== child && el.contains(child);
```
**[⬆ back to top](#table-of-contents)**
## Alternative
* [Forse non hai bisogno di jQuery](http://youmightnotneedjquery.com/) - Esempi di come creare eventi comuni, elementi, ajax etc usando puramente javascript.
* [npm-dom](http://github.com/npm-dom) e [webmodules](http://github.com/webmodules) - Organizzazione dove puoi trovare moduli per il DOM individuale su NPM
## Traduzioni
* [한국어](./README.ko-KR.md)
* [简体中文](./README.zh-CN.md)
* [Bahasa Melayu](./README-my.md)
* [Bahasa Indonesia](./README-id.md)
* [Português(PT-BR)](./README.pt-BR.md)
* [Tiếng Việt Nam](./README-vi.md)
* [Español](./README-es.md)
* [Italiano](./README-it.md)
* [Türkçe](./README-tr.md)
## Supporto Browsers
![Chrome](https://raw.github.com/alrra/browser-logos/master/chrome/chrome_48x48.png) | ![Firefox](https://raw.github.com/alrra/browser-logos/master/firefox/firefox_48x48.png) | ![IE](https://raw.github.com/alrra/browser-logos/master/internet-explorer/internet-explorer_48x48.png) | ![Opera](https://raw.github.com/alrra/browser-logos/master/opera/opera_48x48.png) | ![Safari](https://raw.github.com/alrra/browser-logos/master/safari/safari_48x48.png)
--- | --- | --- | --- | --- |
Ultimo ✔ | Ultimo ✔ | 10+ ✔ | Ultimo ✔ | 6.1+ ✔ |
# Licenza
MIT

View File

@ -0,0 +1,615 @@
## Anda tidak memerlukan jQuery
Mutakhir ini perkembangan dalam persekitaran frontend berlaku begitu pesat sekali. Justeru itu kebanyakan pelayar moden telahpun menyediakan API yang memadai untuk pengaksesan DOM/BOM. Kita tak payah lagi belajar jQuery dari asas untuk memanipulasi DOM dan acara-acara. Projek ini menawarkan perlaksanaan alternatif kepada kebanyakan kaedah-kaedah jQuery yang menyokong IE 10+.
## Isi Kandungan
1. [Pemilihan elemen](#pemilihan-elemen)
1. [CSS & Penggayaan](#css-penggayaan)
1. [Manipulasi DOM](#manipulasi-dom)
1. [Ajax](#ajax)
1. [Events](#events)
1. [Utiliti](#utiliti)
1. [Terjemahan](#terjemahan)
1. [Browser Support](#browser-support)
## Pemilihan Elemen
Pemilihan elemen yang umum seperti class, id atau atribut, biasanya kita boleh pakai `document.querySelector` atau `document.querySelectorAll` sebagai ganti. Bezanya terletak pada
* `document.querySelector` akan mengembalikan elemen pertama sekali yang sepadan dijumpai
* `document.querySelectorAll` akan mengembalikan kesemua elemen yang sepadan dijumpai kedalam sebuah NodeList. Ia boleh ditukar kedalam bentuk array menggunakan `[].slice.call`
* Sekiranya tiada elemen yang sepadan dijumpai, jQuery akan mengembalikan `[]` dimana API DOM pula akan mengembalikan `null`. Sila ambil perhatian pada Null Pointer Exception
> AWAS: `document.querySelector` dan `document.querySelectorAll` agak **LEMBAB** berbanding `getElementById`, `document.getElementsByClassName` atau `document.getElementsByTagName` jika anda menginginkan bonus dari segi prestasi.
- [1.1](#1.1) <a name='1.1'></a> Pemilihan menggunakan class
```js
// jQuery
$('.css');
// Native
document.querySelectorAll('.css');
```
- [1.2](#1.2) <a name='1.2'></a> Pemilihan menggunakan id
```js
// jQuery
$('#id');
// Native
document.querySelector('#id');
```
- [1.3](#1.3) <a name='1.3'></a> Pemilihan menggunakan atribut
```js
// jQuery
$('a[target=_blank]');
// Native
document.querySelectorAll('a[target=_blank]');
```
- [1.4](#1.4) <a name='1.4'></a> Cari sth.
+ Find nodes
```js
// jQuery
$el.find('li');
// Native
el.querySelectorAll('li');
```
+ Cari body
```js
// jQuery
$('body');
// Native
document.body;
```
+ Cari Attribute
```js
// jQuery
$el.attr('foo');
// Native
e.getAttribute('foo');
```
+ Cari atribut data
```js
// jQuery
$el.data('foo');
// Native
// menggunakan getAttribute
el.getAttribute('data-foo');
// anda boleh juga gunakan `dataset` jika ingin pakai IE 11+
el.dataset['foo'];
```
- [1.5](#1.5) <a name='1.5'></a> Sibling/Previous/Next Elements
+ Sibling elements
```js
// jQuery
$el.siblings();
// Native
[].filter.call(el.parentNode.children, function(child) {
return child !== el;
});
```
+ Previous elements
```js
// jQuery
$el.prev();
// Native
el.previousElementSibling;
```
+ Next elements
```js
// next
$el.next();
el.nextElementSibling;
```
- [1.6](#1.6) <a name='1.6'></a> Closest
Return the first matched element by provided selector, traversing from current element to document.
```js
// jQuery
$el.closest(queryString);
// Native
function closest(el, selector) {
const matchesSelector = el.matches || el.webkitMatchesSelector || el.mozMatchesSelector || el.msMatchesSelector;
while (el) {
if (matchesSelector.call(el, selector)) {
return el;
} else {
el = el.parentElement;
}
}
return null;
}
```
- [1.7](#1.7) <a name='1.7'></a> Parents Until
Get the ancestors of each element in the current set of matched elements, up to but not including the element matched by the selector, DOM node, or jQuery object.
```js
// jQuery
$el.parentsUntil(selector, filter);
// Native
function parentsUntil(el, selector, filter) {
const result = [];
const matchesSelector = el.matches || el.webkitMatchesSelector || el.mozMatchesSelector || el.msMatchesSelector;
// match start from parent
el = el.parentElement;
while (el && !matchesSelector.call(el, selector)) {
if (!filter) {
result.push(el);
} else {
if (matchesSelector.call(el, filter)) {
result.push(el);
}
}
el = el.parentElement;
}
return result;
}
```
- [1.8](#1.8) <a name='1.8'></a> Form
+ Input/Textarea
```js
// jQuery
$('#my-input').val();
// Native
document.querySelector('#my-input').value;
```
+ Get index of e.currentTarget between `.radio`
```js
// jQuery
$(e.currentTarget).index('.radio');
// Native
[].indexOf.call(document.querySelectAll('.radio'), e.currentTarget);
```
- [1.9](#1.9) <a name='1.9'></a> Iframe Contents
`$('iframe').contents()` returns `contentDocument` for this specific iframe
+ Iframe contents
```js
// jQuery
$iframe.contents();
// Native
iframe.contentDocument;
```
+ Iframe Query
```js
// jQuery
$iframe.contents().find('.css');
// Native
iframe.contentDocument.querySelectorAll('.css');
```
**[⬆ back to top](#table-of-contents)**
## CSS & Style
- [2.1](#2.1) <a name='2.1'></a> CSS
+ Get style
```js
// jQuery
$el.css("color");
// Native
// NOTE: Known bug, will return 'auto' if style value is 'auto'
const win = el.ownerDocument.defaultView;
// null means not return presudo styles
win.getComputedStyle(el, null).color;
```
+ Set style
```js
// jQuery
$el.css({ color: "#ff0011" });
// Native
el.style.color = '#ff0011';
```
+ Get/Set Styles
Note that if you want to set multiple styles once, you could refer to [setStyles](https://github.com/oneuijs/oui-dom-utils/blob/master/src/index.js#L194) method in oui-dom-utils package.
+ Add class
```js
// jQuery
$el.addClass(className);
// Native
el.classList.add(className);
```
+ Remove class
```js
// jQuery
$el.removeClass(className);
// Native
el.classList.remove(className);
```
+ has class
```js
// jQuery
$el.hasClass(className);
// Native
el.classList.contains(className);
```
+ Toggle class
```js
// jQuery
$el.toggleClass(className);
// Native
el.classList.toggle(className);
```
- [2.2](#2.2) <a name='2.2'></a> Width & Height
Width and Height are theoretically identical, take Height as example:
+ Window height
```js
// window height
$(window).height();
// without scrollbar, behaves like jQuery
window.document.documentElement.clientHeight;
// with scrollbar
window.innerHeight;
```
+ Document height
```js
// jQuery
$(document).height();
// Native
document.documentElement.scrollHeight;
```
+ Element height
```js
// jQuery
$el.height();
// Native
function getHeight(el) {
const styles = this.getComputedStyles(el);
const height = el.offsetHeight;
const borderTopWidth = parseFloat(styles.borderTopWidth);
const borderBottomWidth = parseFloat(styles.borderBottomWidth);
const paddingTop = parseFloat(styles.paddingTop);
const paddingBottom = parseFloat(styles.paddingBottom);
return height - borderBottomWidth - borderTopWidth - paddingTop - paddingBottom;
}
// accurate to integerwhen `border-box`, it's `height`; when `content-box`, it's `height + padding + border`
el.clientHeight;
// accurate to decimalwhen `border-box`, it's `height`; when `content-box`, it's `height + padding + border`
el.getBoundingClientRect().height;
```
- [2.3](#2.3) <a name='2.3'></a> Position & Offset
+ Position
```js
// jQuery
$el.position();
// Native
{ left: el.offsetLeft, top: el.offsetTop }
```
+ Offset
```js
// jQuery
$el.offset();
// Native
function getOffset (el) {
const box = el.getBoundingClientRect();
return {
top: box.top + window.pageYOffset - document.documentElement.clientTop,
left: box.left + window.pageXOffset - document.documentElement.clientLeft
}
}
```
- [2.4](#2.4) <a name='2.4'></a> Scroll Top
```js
// jQuery
$(window).scrollTop();
// Native
(document.documentElement && document.documentElement.scrollTop) || document.body.scrollTop;
```
**[⬆ back to top](#table-of-contents)**
## DOM Manipulation
- [3.1](#3.1) <a name='3.1'></a> Remove
```js
// jQuery
$el.remove();
// Native
el.parentNode.removeChild(el);
```
- [3.2](#3.2) <a name='3.2'></a> Text
+ Get text
```js
// jQuery
$el.text();
// Native
el.textContent;
```
+ Set text
```js
// jQuery
$el.text(string);
// Native
el.textContent = string;
```
- [3.3](#3.3) <a name='3.3'></a> HTML
+ Get HTML
```js
// jQuery
$el.html();
// Native
el.innerHTML;
```
+ Set HTML
```js
// jQuery
$el.html(htmlString);
// Native
el.innerHTML = htmlString;
```
- [3.4](#3.4) <a name='3.4'></a> Append
append child element after the last child of parent element
```js
// jQuery
$el.append("<div id='container'>hello</div>");
// Native
let newEl = document.createElement('div');
newEl.setAttribute('id', 'container');
newEl.innerHTML = 'hello';
el.appendChild(newEl);
```
- [3.5](#3.5) <a name='3.5'></a> Prepend
```js
// jQuery
$el.prepend("<div id='container'>hello</div>");
// Native
let newEl = document.createElement('div');
newEl.setAttribute('id', 'container');
newEl.innerHTML = 'hello';
el.insertBefore(newEl, el.firstChild);
```
- [3.6](#3.6) <a name='3.6'></a> insertBefore
Insert a new node before the selected elements
```js
// jQuery
$newEl.insertBefore(queryString);
// Native
const target = document.querySelector(queryString);
target.parentNode.insertBefore(newEl, target);
```
- [3.7](#3.7) <a name='3.7'></a> insertAfter
Insert a new node after the selected elements
```js
// jQuery
$newEl.insertAfter(queryString);
// Native
const target = document.querySelector(queryString);
target.parentNode.insertBefore(newEl, target.nextSibling);
```
**[⬆ back to top](#table-of-contents)**
## Ajax
Replace with [fetch](https://github.com/camsong/fetch-ie8) and [fetch-jsonp](https://github.com/camsong/fetch-jsonp)
**[⬆ back to top](#table-of-contents)**
## Events
For a complete replacement with namespace and delegation, refer to https://github.com/oneuijs/oui-dom-events
- [5.1](#5.1) <a name='5.1'></a> Bind an event with on
```js
// jQuery
$el.on(eventName, eventHandler);
// Native
el.addEventListener(eventName, eventHandler);
```
- [5.2](#5.2) <a name='5.2'></a> Unbind an event with off
```js
// jQuery
$el.off(eventName, eventHandler);
// Native
el.removeEventListener(eventName, eventHandler);
```
- [5.3](#5.3) <a name='5.3'></a> Trigger
```js
// jQuery
$(el).trigger('custom-event', {key1: 'data'});
// Native
if (window.CustomEvent) {
const event = new CustomEvent('custom-event', {detail: {key1: 'data'}});
} else {
const event = document.createEvent('CustomEvent');
event.initCustomEvent('custom-event', true, true, {key1: 'data'});
}
el.dispatchEvent(event);
```
**[⬆ back to top](#table-of-contents)**
## Utility
- [6.1](#6.1) <a name='6.1'></a> isArray
```js
// jQuery
$.isArray(range);
// Native
Array.isArray(range);
```
- [6.2](#6.2) <a name='6.2'></a> Trim
```js
// jQuery
$.trim(string);
// Native
String.trim(string);
```
- [6.3](#6.3) <a name='6.3'></a> Object Assign
Extend, use object.assign polyfill https://github.com/ljharb/object.assign
```js
// jQuery
$.extend({}, defaultOpts, opts);
// Native
Object.assign({}, defaultOpts, opts);
```
- [6.4](#6.4) <a name='6.4'></a> Contains
```js
// jQuery
$.contains(el, child);
// Native
el !== child && el.contains(child);
```
**[⬆ back to top](#table-of-contents)**
## Terjemahan
* [한국어](./README.ko-KR.md)
* [简体中文](./README.zh-CN.md)
* [English](./README.md)
* [Русский](./README-ru.md)
* [Türkçe](./README-tr.md)
## Sokongan Pelayar
![Chrome](https://raw.github.com/alrra/browser-logos/master/chrome/chrome_48x48.png) | ![Firefox](https://raw.github.com/alrra/browser-logos/master/firefox/firefox_48x48.png) | ![IE](https://raw.github.com/alrra/browser-logos/master/internet-explorer/internet-explorer_48x48.png) | ![Opera](https://raw.github.com/alrra/browser-logos/master/opera/opera_48x48.png) | ![Safari](https://raw.github.com/alrra/browser-logos/master/safari/safari_48x48.png)
--- | --- | --- | --- | --- |
Latest ✔ | Latest ✔ | 10+ ✔ | Latest ✔ | 6.1+ ✔ |
# Lesen
MIT

View File

@ -0,0 +1,650 @@
## Вам не нужен jQuery
В наше время среда фронт энд разработки быстро развивается, современные браузеры уже реализовали значимую часть DOM/BOM APIs и это хорошо. Вам не нужно изучать jQuery с нуля для манипуляцией DOM'ом или обектами событий. В то же время, благодаря лидирующим фронт энд библиотекам, таким как React, Angular и Vue, манипуляция DOM'ом напрямую становится противо шаблонной, jQuery никогда не был менее важен. Этот проект суммирует большинство альтернатив методов jQuery в нативном исполнении с поддержкой IE 10+.
## Содержание
1. [Query Selector](#query-selector)
1. [CSS & Style](#css--style)
1. [Манипуляция DOM](#Манипуляции-dom)
1. [Ajax](#ajax)
1. [События](#События)
1. [Утилиты](#Утилиты)
1. [Альтернативы](#Альтернативы)
1. [Переводы](#Переводы)
1. [Поддержка браузеров](#Поддержка-браузеров)
## Query Selector
Для часто используемых селекторов, таких как class, id или attribute мы можем использовать `document.querySelector` или `document.querySelectorAll` для замены. Разница такова:
* `document.querySelector` возвращает первый совпавший элемент
* `document.querySelectorAll` возвращает все совспавшие элементы как коллекцию узлов(NodeList). Его можно конвертировать в массив используя `[].slice.call(document.querySelectorAll(selector) || []);`
* Если никакие элементы не совпадут, jQuery вернет `[]` где DOM API вернет `null`. Обратите внимание на указатель исключения Null (Null Pointer Exception). Вы так же можете использовать `||` для установки значения по умолчанию если не было найдемо совпадений `document.querySelectorAll(selector) || []`
> Заметка: `document.querySelector` и `document.querySelectorAll` достаточно **МЕДЛЕННЫ**, старайтесь использовать `getElementById`, `document.getElementsByClassName` или `document.getElementsByTagName` если хотите улучшить производительность.
- [1.0](#1.0) <a name='1.0'></a> Query by selector
```js
// jQuery
$('selector');
// Нативно
document.querySelectorAll('selector');
```
- [1.1](#1.1) <a name='1.1'></a> Запрос по классу
```js
// jQuery
$('.class');
// Нативно
document.querySelectorAll('.class');
// или
document.getElementsByClassName('class');
```
- [1.2](#1.2) <a name='1.2'></a> Запрос по ID
```js
// jQuery
$('#id');
// Нативно
document.querySelector('#id');
// или
document.getElementById('id');
```
- [1.3](#1.3) <a name='1.3'></a> Запрос по атрибуту
```js
// jQuery
$('a[target=_blank]');
// Нативно
document.querySelectorAll('a[target=_blank]');
```
- [1.4](#1.4) <a name='1.4'></a> Найти среди потомков
+ Найти nodes
```js
// jQuery
$el.find('li');
// Нативно
el.querySelectorAll('li');
```
+ Найти body
```js
// jQuery
$('body');
// Нативно
document.body;
```
+ Найти атрибуты
```js
// jQuery
$el.attr('foo');
// Нативно
e.getAttribute('foo');
```
+ Найти data attribute
```js
// jQuery
$el.data('foo');
// Нативно
// используя getAttribute
el.getAttribute('data-foo');
// также можно использовать `dataset`, если не требуется поддержка ниже IE 11.
el.dataset['foo'];
```
- [1.5](#1.5) <a name='1.5'></a> Родственные/Предыдущие/Следующие Элементы
+ Родственные элементы
```js
// jQuery
$el.siblings();
// Нативно
[].filter.call(el.parentNode.children, function(child) {
return child !== el;
});
```
+ Предыдущие элементы
```js
// jQuery
$el.prev();
// Нативно
el.previousElementSibling;
```
+ Следующие элементы
```js
// jQuery
$el.next();
// Нативно
el.nextElementSibling;
```
- [1.6](#1.6) <a name='1.6'></a> Closest
Возвращает первый совпавший элемент по предоставленному селектору, обоходя от текущего элементы до документа.
```js
// jQuery
$el.closest(queryString);
// Нативно - Only latest, NO IE
el.closest(selector);
// Нативно - IE10+
function closest(el, selector) {
const matchesSelector = el.matches || el.webkitMatchesSelector || el.mozMatchesSelector || el.msMatchesSelector;
while (el) {
if (matchesSelector.call(el, selector)) {
return el;
} else {
el = el.parentElement;
}
}
return null;
}
```
- [1.7](#1.7) <a name='1.7'></a> Родители до
Получить родителей кажого элемента в текущем сете совпавших элементов, но не включая элемент совпавший с селектором, узел DOM'а, или объект jQuery.
```js
// jQuery
$el.parentsUntil(selector, filter);
// Нативно
function parentsUntil(el, selector, filter) {
const result = [];
const matchesSelector = el.matches || el.webkitMatchesSelector || el.mozMatchesSelector || el.msMatchesSelector;
// Совпадать начиная от родителя
el = el.parentElement;
while (el && !matchesSelector.call(el, selector)) {
if (!filter) {
result.push(el);
} else {
if (matchesSelector.call(el, filter)) {
result.push(el);
}
}
el = el.parentElement;
}
return result;
}
```
- [1.8](#1.8) <a name='1.8'></a> От
+ Input/Textarea
```js
// jQuery
$('#my-input').val();
// Нативно
document.querySelector('#my-input').value;
```
+ получить индекс e.currentTarget между `.radio`
```js
// jQuery
$(e.currentTarget).index('.radio');
// Нативно
[].indexOf.call(document.querySelectAll('.radio'), e.currentTarget);
```
- [1.9](#1.9) <a name='1.9'></a> Контент Iframe
`$('iframe').contents()` возвращает `contentDocument` для именно этого iframe
+ Контент Iframe
```js
// jQuery
$iframe.contents();
// Нативно
iframe.contentDocument;
```
+ Iframe Query
```js
// jQuery
$iframe.contents().find('.css');
// Нативно
iframe.contentDocument.querySelectorAll('.css');
```
**[⬆ Наверх](#Содержание)**
## CSS & Style
- [2.1](#2.1) <a name='2.1'></a> CSS
+ Получить стиль
```js
// jQuery
$el.css("color");
// Нативно
// ЗАМЕТКА: Известная ошика, возвращает 'auto' если значение стиля 'auto'
const win = el.ownerDocument.defaultView;
// null означает не возвращать псевдостили
win.getComputedStyle(el, null).color;
```
+ Присвоение style
```js
// jQuery
$el.css({ color: "#ff0011" });
// Нативно
el.style.color = '#ff0011';
```
+ Получение/Присвоение стилей
Заметьте что если вы хотите присвоить несколько стилей за раз, вы можете сослаться на [setStyles](https://github.com/oneuijs/oui-dom-utils/blob/master/src/index.js#L194) метод в oui-dom-utils package.
+ Добавить класс
```js
// jQuery
$el.addClass(className);
// Нативно
el.classList.add(className);
```
+ Удалить class
```js
// jQuery
$el.removeClass(className);
// Нативно
el.classList.remove(className);
```
+ Имеет класс
```js
// jQuery
$el.hasClass(className);
// Нативно
el.classList.contains(className);
```
+ Переключать класс
```js
// jQuery
$el.toggleClass(className);
// Нативно
el.classList.toggle(className);
```
- [2.2](#2.2) <a name='2.2'></a> Ширина и Высота
Ширина и высота теоритечески идентичны, например возьмем высоту:
+ высота окна
```js
// Высота окна
$(window).height();
// без скроллбара, ведет себя как jQuery
window.document.documentElement.clientHeight;
// вместе с скроллбаром
window.innerHeight;
```
+ высота документа
```js
// jQuery
$(document).height();
// Нативно
document.documentElement.scrollHeight;
```
+ Высота элемента
```js
// jQuery
$el.height();
// Нативно
function getHeight(el) {
const styles = this.getComputedStyles(el);
const height = el.offsetHeight;
const borderTopWidth = parseFloat(styles.borderTopWidth);
const borderBottomWidth = parseFloat(styles.borderBottomWidth);
const paddingTop = parseFloat(styles.paddingTop);
const paddingBottom = parseFloat(styles.paddingBottom);
return height - borderBottomWidth - borderTopWidth - paddingTop - paddingBottom;
}
// С точностью до целого числа(когда `border-box`, это `height`; когда `content-box`, это `height + padding + border`
el.clientHeight;
// с точностью до десятых(когда `border-box`, это `height`; когда `content-box`, это `height + padding + border`
el.getBoundingClientRect().height;
```
- [2.3](#2.3) <a name='2.3'></a> Позиция и смещение
+ Позиция
```js
// jQuery
$el.position();
// Нативно
{ left: el.offsetLeft, top: el.offsetTop }
```
+ Смещение
```js
// jQuery
$el.offset();
// Нативно
function getOffset (el) {
const box = el.getBoundingClientRect();
return {
top: box.top + window.pageYOffset - document.documentElement.clientTop,
left: box.left + window.pageXOffset - document.documentElement.clientLeft
}
}
```
- [2.4](#2.4) <a name='2.4'></a> Прокрутка вверх
```js
// jQuery
$(window).scrollTop();
// Нативно
(document.documentElement && document.documentElement.scrollTop) || document.body.scrollTop;
```
**[⬆ Наверх](#Содержание)**
## Манипуляции DOM
- [3.1](#3.1) <a name='3.1'></a> Remove
```js
// jQuery
$el.remove();
// Нативно
el.parentNode.removeChild(el);
```
- [3.2](#3.2) <a name='3.2'></a> Текст
+ Получить текст
```js
// jQuery
$el.text();
// Нативно
el.textContent;
```
+ Присвоить текст
```js
// jQuery
$el.text(string);
// Нативно
el.textContent = string;
```
- [3.3](#3.3) <a name='3.3'></a> HTML
+ Получить HTML
```js
// jQuery
$el.html();
// Нативно
el.innerHTML;
```
+ Присвоить HTML
```js
// jQuery
$el.html(htmlString);
// Нативно
el.innerHTML = htmlString;
```
- [3.4](#3.4) <a name='3.4'></a> Append
Добавление элемента ребенка после последнего ребенка элемента родителя
```js
// jQuery
$el.append("<div id='container'>hello</div>");
// Нативно
el.insertAdjacentHTML("beforeend","<div id='container'>hello</div>");
```
- [3.5](#3.5) <a name='3.5'></a> Prepend
```js
// jQuery
$el.prepend("<div id='container'>hello</div>");
// Нативно
el.insertAdjacentHTML("afterbegin","<div id='container'>hello</div>");
```
- [3.6](#3.6) <a name='3.6'></a> insertBefore
Вставка нового элемента перед выбранным элементом
```js
// jQuery
$newEl.insertBefore(queryString);
// Нативно
const target = document.querySelector(queryString);
target.parentNode.insertBefore(newEl, target);
```
- [3.7](#3.7) <a name='3.7'></a> insertAfter
Вставка новго элемента после выбранного элемента
```js
// jQuery
$newEl.insertAfter(queryString);
// Нативно
const target = document.querySelector(queryString);
target.parentNode.insertBefore(newEl, target.nextSibling);
```
- [3.8](#3.8) <a name='3.8'></a> is
Возвращает `true` если совпадает с селектором запроса
```js
// jQuery - заметьте что `is` так же работает с `function` или `elements` которые не имют к этому отношения
$el.is(selector);
// Нативно
el.matches(selector);
```
**[⬆ Наверх](#Содержание)**
## Ajax
Заменить с [fetch](https://github.com/camsong/fetch-ie8) и [fetch-jsonp](https://github.com/camsong/fetch-jsonp)
**[⬆ Наверх](#Содержание)**
## События
Для полной замены с пространством имен и делегация, сослаться на [oui-dom-events](https://github.com/oneuijs/oui-dom-events)
- [5.1](#5.1) <a name='5.1'></a> Связать событие используя on
```js
// jQuery
$el.on(eventName, eventHandler);
// Нативно
el.addEventListener(eventName, eventHandler);
```
- [5.2](#5.2) <a name='5.2'></a> Отвязать событие используя off
```js
// jQuery
$el.off(eventName, eventHandler);
// Нативно
el.removeEventListener(eventName, eventHandler);
```
- [5.3](#5.3) <a name='5.3'></a> Trigger
```js
// jQuery
$(el).trigger('custom-event', {key1: 'data'});
// Нативно
if (window.CustomEvent) {
const event = new CustomEvent('custom-event', {detail: {key1: 'data'}});
} else {
const event = document.createEvent('CustomEvent');
event.initCustomEvent('custom-event', true, true, {key1: 'data'});
}
el.dispatchEvent(event);
```
**[⬆ Наверх](#Содержание)**
## Утилиты
- [6.1](#6.1) <a name='6.1'></a> isArray
```js
// jQuery
$.isArray(range);
// Нативно
Array.isArray(range);
```
- [6.2](#6.2) <a name='6.2'></a> Trim
```js
// jQuery
$.trim(string);
// Нативно
string.trim();
```
- [6.3](#6.3) <a name='6.3'></a> Назначение объекта
Дополнительно, используйте полифил object.assign https://github.com/ljharb/object.assign
```js
// jQuery
$.extend({}, defaultOpts, opts);
// Нативно
Object.assign({}, defaultOpts, opts);
```
- [6.4](#6.4) <a name='6.4'></a> Contains
```js
// jQuery
$.contains(el, child);
// Нативно
el !== child && el.contains(child);
```
**[⬆ Наверх](#Содержание)**
## Альтернативы
* [You Might Not Need jQuery](http://youmightnotneedjquery.com/) - Примеры как исполняются частые события, элементы, ajax и тд с ванильным javascript.
* [npm-dom](http://github.com/npm-dom) и [webmodules](http://github.com/webmodules) - Отдельные DOM модули можно найти на NPM
## Переводы
* [한국어](./README.ko-KR.md)
* [简体中文](./README.zh-CN.md)
* [Bahasa Melayu](./README-my.md)
* [Bahasa Indonesia](./README-id.md)
* [Português(PT-BR)](./README.pt-BR.md)
* [Tiếng Việt Nam](./README-vi.md)
* [Español](./README-es.md)
* [Русский](./README-ru.md)
* [Türkçe](./README-tr.md)
## Поддержка браузеров
![Chrome](https://raw.github.com/alrra/browser-logos/master/chrome/chrome_48x48.png) | ![Firefox](https://raw.github.com/alrra/browser-logos/master/firefox/firefox_48x48.png) | ![IE](https://raw.github.com/alrra/browser-logos/master/internet-explorer/internet-explorer_48x48.png) | ![Opera](https://raw.github.com/alrra/browser-logos/master/opera/opera_48x48.png) | ![Safari](https://raw.github.com/alrra/browser-logos/master/safari/safari_48x48.png)
--- | --- | --- | --- | --- |
Latest ✔ | Latest ✔ | 10+ ✔ | Latest ✔ | 6.1+ ✔ |
# License
MIT

View File

@ -0,0 +1,665 @@
## jQuery'e İhtiyacınız Yok [![Build Status](https://travis-ci.org/oneuijs/You-Dont-Need-jQuery.svg)](https://travis-ci.org/oneuijs/You-Dont-Need-jQuery)
Önyüz ortamları bugünlerde çok hızlı gelişiyor, öyle ki modern tarayıcılar DOM/DOM APİ'lere ait önemli gereklilikleri çoktan yerine getirdiler. DOM işleme ve olaylar için, en baştan jQuery ögrenmemize gerek kalmadı. Bu arada, üstünlükleri ile jQuery'i önemsizleştiren ve doğrudan DOM değişikliklerinin bir Anti-pattern olduğunu gösteren, React, Angular ve Vue gibi gelişmiş önyüz kütüphanelerine ayrıca teşekkür ederiz. Bu proje, IE10+ desteği ile coğunluğu jQuery yöntemlerine alternatif olan yerleşik uygulamaları içerir.
## İçerik Tablosu
1. [Sorgu seçiciler](#sorgu-seçiciler)
1. [CSS & Stil](#css--stil)
1. [DOM düzenleme](#dom-düzenleme)
1. [Ajax](#ajax)
1. [Olaylar](#olaylar)
1. [Araçlar](#araçlar)
1. [Alternatifler](#alternatifler)
1. [Çeviriler](#Çeviriler)
1. [Tarayıcı desteği](#tarayıcı-desteği)
## Sorgu seçiciler
Yaygın olan class, id ve özellik seçiciler yerine, `document.querySelector` yada `document.querySelectorAll` kullanabiliriz. Ayrıldıkları nokta:
* `document.querySelector` ilk seçilen öğeyi döndürür
* `document.querySelectorAll` Seçilen tüm öğeleri NodeList olarak geri döndürür. `[].slice.call(document.querySelectorAll(selector) || []);` kullanarak bir diziye dönüştürebilirsiniz.
* Herhangi bir öğenin seçilememesi durumda ise, jQuery `[]` döndürürken, DOM API `null` döndürecektir. Null Pointer istisnası almamak için `||` ile varsayılan değere atama yapabilirsiniz, örnek: `document.querySelectorAll(selector) || []`
> Uyarı: `document.querySelector` ve `document.querySelectorAll` biraz **YAVAŞ** olabilir, Daha hızlısını isterseniz, `getElementById`, `document.getElementsByClassName` yada `document.getElementsByTagName` kullanabilirsiniz.
- [1.0](#1.0) <a name='1.0'></a> Seçici ile sorgu
```js
// jQuery
$('selector');
// Yerleşik
document.querySelectorAll('selector');
```
- [1.1](#1.1) <a name='1.1'></a> Sınıf ile sorgu
```js
// jQuery
$('.class');
// Yerleşik
document.querySelectorAll('.class');
// yada
document.getElementsByClassName('class');
```
- [1.2](#1.2) <a name='1.2'></a> Id ile sorgu
```js
// jQuery
$('#id');
// Yerleşik
document.querySelector('#id');
// yada
document.getElementById('id');
```
- [1.3](#1.3) <a name='1.3'></a> Özellik ile sorgu
```js
// jQuery
$('a[target=_blank]');
// Yerleşik
document.querySelectorAll('a[target=_blank]');
```
- [1.4](#1.4) <a name='1.4'></a> Öğe erişimi
+ Node'a erişim
```js
// jQuery
$el.find('li');
// Yerleşik
el.querySelectorAll('li');
```
+ Body'e erişim
```js
// jQuery
$('body');
// Yerleşik
document.body;
```
+ Özelliğe erişim
```js
// jQuery
$el.attr('foo');
// Yerleşik
el.getAttribute('foo');
```
+ Data özelliğine erişim
```js
// jQuery
$el.data('foo');
// Yerleşik
// getAttribute kullanarak
el.getAttribute('data-foo');
// Eğer IE 11+ kullanıyor iseniz, `dataset` ile de erişebilirsiniz
el.dataset['foo'];
```
- [1.5](#1.5) <a name='1.5'></a> Kardeş/Önceki/Sonraki öğeler
+ Kardeş öğeler
```js
// jQuery
$el.siblings();
// Yerleşik
[].filter.call(el.parentNode.children, function(child) {
return child !== el;
});
```
+ Önceki öğeler
```js
// jQuery
$el.prev();
// Yerleşik
el.previousElementSibling;
```
+ Sonraki öğeler
```js
// jQuery
$el.next();
// Yerleşik
el.nextElementSibling;
```
- [1.6](#1.6) <a name='1.6'></a> En yakın
Verilen seçici ile eşleşen ilk öğeyi döndürür, geçerli öğeden başlayarak document'a kadar geçiş yapar.
```js
// jQuery
$el.closest(selector);
// Yerleşik - Sadece en güncellerde, IE desteklemiyor
el.closest(selector);
// Yerleşik - IE10+
function closest(el, selector) {
const matchesSelector = el.matches || el.webkitMatchesSelector || el.mozMatchesSelector || el.msMatchesSelector;
while (el) {
if (matchesSelector.call(el, selector)) {
return el;
} else {
el = el.parentElement;
}
}
return null;
}
```
- [1.7](#1.7) <a name='1.7'></a> Önceki atalar
Verilen seçici ile eşleşen öğe veya DOM node veya jQuery nesnesi hariç, mevcut öğe ile aradaki tüm önceki ataları bir set dahilinde verir.
```js
// jQuery
$el.parentsUntil(selector, filter);
// Yerleşik
function parentsUntil(el, selector, filter) {
const result = [];
const matchesSelector = el.matches || el.webkitMatchesSelector || el.mozMatchesSelector || el.msMatchesSelector;
// eşleştirme, atadan başlar
el = el.parentElement;
while (el && !matchesSelector.call(el, selector)) {
if (!filter) {
result.push(el);
} else {
if (matchesSelector.call(el, filter)) {
result.push(el);
}
}
el = el.parentElement;
}
return result;
}
```
- [1.8](#1.8) <a name='1.8'></a> Form
+ Input/Textarea
```js
// jQuery
$('#my-input').val();
// Yerleşik
document.querySelector('#my-input').value;
```
+ e.currentTarget ile `.radio` arasındaki dizini verir
```js
// jQuery
$(e.currentTarget).index('.radio');
// Yerleşik
[].indexOf.call(document.querySelectAll('.radio'), e.currentTarget);
```
- [1.9](#1.9) <a name='1.9'></a> Iframe İçeriği
Mevcut Iframe için `$('iframe').contents()` yerine `contentDocument` döndürür.
+ Iframe İçeriği
```js
// jQuery
$iframe.contents();
// Yerleşik
iframe.contentDocument;
```
+ Iframe seçici
```js
// jQuery
$iframe.contents().find('.css');
// Yerleşik
iframe.contentDocument.querySelectorAll('.css');
```
**[⬆ üste dön](#İçerik-tablosu)**
## CSS & Stil
- [2.1](#2.1) <a name='2.1'></a> CSS
+ Stili verir
```js
// jQuery
$el.css("color");
// Yerleşik
// NOT: Bilinen bir hata, eğer stil değeri 'auto' ise 'auto' döndürür
const win = el.ownerDocument.defaultView;
// null sahte tipleri döndürmemesi için
win.getComputedStyle(el, null).color;
```
+ Stil değiştir
```js
// jQuery
$el.css({ color: "#ff0011" });
// Yerleşik
el.style.color = '#ff0011';
```
+ Stil değeri al/değiştir
Eğer aynı anda birden fazla stili değiştirmek istiyor iseniz, oui-dom-utils paketi içindeki [setStyles](https://github.com/oneuijs/oui-dom-utils/blob/master/src/index.js#L194) metoduna göz atınız.
+ Sınıf ekle
```js
// jQuery
$el.addClass(className);
// Yerleşik
el.classList.add(className);
```
+ Sınıf çıkart
```js
// jQuery
$el.removeClass(className);
// Yerleşik
el.classList.remove(className);
```
+ sınfı var mı?
```js
// jQuery
$el.hasClass(className);
// Yerleşik
el.classList.contains(className);
```
+ Sınfı takas et
```js
// jQuery
$el.toggleClass(className);
// Yerleşik
el.classList.toggle(className);
```
- [2.2](#2.2) <a name='2.2'></a> Genişlik ve Yükseklik
Genişlik ve Yükseklik teorik olarak aynı şekilde, örnek olarak Yükseklik veriliyor
+ Window Yüksekliği
```js
// window yüksekliği
$(window).height();
// kaydırma çubuğu olmaksızın, jQuery ile aynı
window.document.documentElement.clientHeight;
// kaydırma çubuğu ile birlikte
window.innerHeight;
```
+ Document yüksekliği
```js
// jQuery
$(document).height();
// Yerleşik
document.documentElement.scrollHeight;
```
+ Öğe yüksekliği
```js
// jQuery
$el.height();
// Yerleşik
function getHeight(el) {
const styles = this.getComputedStyles(el);
const height = el.offsetHeight;
const borderTopWidth = parseFloat(styles.borderTopWidth);
const borderBottomWidth = parseFloat(styles.borderBottomWidth);
const paddingTop = parseFloat(styles.paddingTop);
const paddingBottom = parseFloat(styles.paddingBottom);
return height - borderBottomWidth - borderTopWidth - paddingTop - paddingBottom;
}
// Tamsayı olarak daha doğru olanı`border-box` iken, `height` esas; `content-box` ise, `height + padding + border` esas alınır
el.clientHeight;
// Ondalık olarak daha doğru olanı`border-box` iken, `height` esas; `content-box` ise, `height + padding + border` esas alınır
el.getBoundingClientRect().height;
```
- [2.3](#2.3) <a name='2.3'></a> Pozisyon ve Ara-Açıklığı
+ Pozisyon
```js
// jQuery
$el.position();
// Yerleşik
{ left: el.offsetLeft, top: el.offsetTop }
```
+ Ara-Açıklığı
```js
// jQuery
$el.offset();
// Yerleşik
function getOffset (el) {
const box = el.getBoundingClientRect();
return {
top: box.top + window.pageYOffset - document.documentElement.clientTop,
left: box.left + window.pageXOffset - document.documentElement.clientLeft
}
}
```
- [2.4](#2.4) <a name='2.4'></a> Üste kaydır
```js
// jQuery
$(window).scrollTop();
// Yerleşik
(document.documentElement && document.documentElement.scrollTop) || document.body.scrollTop;
```
**[⬆ üste dön](#İçerik-tablosu)**
## DOM düzenleme
- [3.1](#3.1) <a name='3.1'></a> Çıkartma
```js
// jQuery
$el.remove();
// Yerleşik
el.parentNode.removeChild(el);
```
- [3.2](#3.2) <a name='3.2'></a> Metin
+ Get text
```js
// jQuery
$el.text();
// Yerleşik
el.textContent;
```
+ Set text
```js
// jQuery
$el.text(string);
// Yerleşik
el.textContent = string;
```
- [3.3](#3.3) <a name='3.3'></a> HTML
+ HTML'i alma
```js
// jQuery
$el.html();
// Yerleşik
el.innerHTML;
```
+ HTML atama
```js
// jQuery
$el.html(htmlString);
// Yerleşik
el.innerHTML = htmlString;
```
- [3.4](#3.4) <a name='3.4'></a> Sona ekleme
Ata öğenin son çocuğundan sonra öğe ekleme
```js
// jQuery
$el.append("<div id='container'>hello</div>");
// Yerleşik
el.insertAdjacentHTML("beforeend","<div id='container'>hello</div>");
```
- [3.5](#3.5) <a name='3.5'></a> Öne ekleme
```js
// jQuery
$el.prepend("<div id='container'>hello</div>");
// Yerleşik
el.insertAdjacentHTML("afterbegin","<div id='container'>hello</div>");
```
- [3.6](#3.6) <a name='3.6'></a> Öncesine Ekleme
Seçili öğeden önceki yere yeni öğe ekleme
```js
// jQuery
$newEl.insertBefore(queryString);
// Yerleşik
const target = document.querySelector(queryString);
target.parentNode.insertBefore(newEl, target);
```
- [3.7](#3.7) <a name='3.7'></a> Sonrasına ekleme
Seçili öğeden sonraki yere yeni öğe ekleme
```js
// jQuery
$newEl.insertAfter(queryString);
// Yerleşik
const target = document.querySelector(queryString);
target.parentNode.insertBefore(newEl, target.nextSibling);
```
- [3.8](#3.8) <a name='3.8'></a> eşit mi?
Sorgu seçici ile eşleşiyor ise `true` döner
```js
// jQuery için not: `is` aynı zamanda `function` veya `elements` için de geçerlidir fakat burada bir önemi bulunmuyor
$el.is(selector);
// Yerleşik
el.matches(selector);
```
- [3.9](#3.9) <a name='3.9'></a> Klonlama
Mevcut öğenin bir derin kopyasını oluşturur
```js
// jQuery
$el.clone();
// Yerleşik
el.cloneNode();
// Derin kopya için, `true` parametresi kullanınız
```
**[⬆ üste dön](#İçerik-tablosu)**
## Ajax
[Fetch API](https://fetch.spec.whatwg.org/) ajax için XMLHttpRequest yerine kullanan yeni standarttır. Chrome ve Firefox destekler, eski tarayıcılar için polyfill kullanabilirsiniz.
IE9+ ve üstü için [github/fetch](http://github.com/github/fetch) yada IE8+ ve üstü için [fetch-ie8](https://github.com/camsong/fetch-ie8/), JSONP istekler için [fetch-jsonp](https://github.com/camsong/fetch-jsonp) deneyiniz.
**[⬆ üste dön](#İçerik-tablosu)**
## Olaylar
Namespace ve Delegasyon ile tam olarak değiştirmek için, https://github.com/oneuijs/oui-dom-events sayfasına bakınız
- [5.1](#5.1) <a name='5.1'></a> on ile bir öğeye bağlama
```js
// jQuery
$el.on(eventName, eventHandler);
// Yerleşik
el.addEventListener(eventName, eventHandler);
```
- [5.2](#5.2) <a name='5.2'></a> off ile bir bağlamayı sonlandırma
```js
// jQuery
$el.off(eventName, eventHandler);
// Yerleşik
el.removeEventListener(eventName, eventHandler);
```
- [5.3](#5.3) <a name='5.3'></a> Tetikleyici
```js
// jQuery
$(el).trigger('custom-event', {key1: 'data'});
// Yerleşik
if (window.CustomEvent) {
const event = new CustomEvent('custom-event', {detail: {key1: 'data'}});
} else {
const event = document.createEvent('CustomEvent');
event.initCustomEvent('custom-event', true, true, {key1: 'data'});
}
el.dispatchEvent(event);
```
**[⬆ üste dön](#İçerik-tablosu)**
## Araçlar
- [6.1](#6.1) <a name='6.1'></a> isArray
```js
// jQuery
$.isArray(range);
// Yerleşik
Array.isArray(range);
```
- [6.2](#6.2) <a name='6.2'></a> Trim
```js
// jQuery
$.trim(string);
// Yerleşik
string.trim();
```
- [6.3](#6.3) <a name='6.3'></a> Nesne atama
Türetmek için, object.assign polyfill'ini deneyiniz https://github.com/ljharb/object.assign
```js
// jQuery
$.extend({}, defaultOpts, opts);
// Yerleşik
Object.assign({}, defaultOpts, opts);
```
- [6.4](#6.4) <a name='6.4'></a> İçerme
```js
// jQuery
$.contains(el, child);
// Yerleşik
el !== child && el.contains(child);
```
**[⬆ üste dön](#İçerik-tablosu)**
## Alternatifler
* [jQuery'e İhtiyacınız Yok](http://youmightnotneedjquery.com/) - Yaygın olan olay, öğe ve ajax işlemlerinin yalın Javascript'teki karşılıklarına ait örnekler
* [npm-dom](http://github.com/npm-dom) ve [webmodules](http://github.com/webmodules) - NPM için ayrı DOM modül organizasyonları
## Çeviriler
* [한국어](./README.ko-KR.md)
* [简体中文](./README.zh-CN.md)
* [Bahasa Melayu](./README-my.md)
* [Bahasa Indonesia](./README-id.md)
* [Português(PT-BR)](./README.pt-BR.md)
* [Tiếng Việt Nam](./README-vi.md)
* [Español](./README-es.md)
* [Русский](./README-ru.md)
* [Türkçe](./README-tr.md)
## Tarayıcı Desteği
![Chrome](https://raw.github.com/alrra/browser-logos/master/chrome/chrome_48x48.png) | ![Firefox](https://raw.github.com/alrra/browser-logos/master/firefox/firefox_48x48.png) | ![IE](https://raw.github.com/alrra/browser-logos/master/internet-explorer/internet-explorer_48x48.png) | ![Opera](https://raw.github.com/alrra/browser-logos/master/opera/opera_48x48.png) | ![Safari](https://raw.github.com/alrra/browser-logos/master/safari/safari_48x48.png)
--- | --- | --- | --- | --- |
Latest ✔ | Latest ✔ | 10+ ✔ | Latest ✔ | 6.1+ ✔ |
# Lisans
MIT

View File

@ -0,0 +1,634 @@
## Bạn không cần jQuery nữa đâu
Ngày nay, môi trường lập trình front-end phát triển rất nhanh chóng, các trình duyệt hiện đại đã cung cấp các API đủ tốt để làm việc với DOM/BOM. Bạn không còn cần phải học về jQuery nữa. Đồng thời, nhờ sự ra đời của các thư viện như React, Angular và Vue đã khiến cho việc can thiệp trực tiếp vào DOM trở thành một việc không tốt. jQuery đã không còn quan trọng như trước nữa. Bài viết này tổng hợp những cách để thay thế các hàm của jQuery bằng các hàm được hỗ trợ bởi trình duyệt, và hó cũng hoạt động trên IE 10+
## Danh mục
1. [Query Selector](#query-selector)
1. [CSS & Style](#css--style)
1. [Thao tác với DOM](#thao-tác-với-dom)
1. [Ajax](#ajax)
1. [Events](#events)
1. [Hàm tiện ích](#hàm-tiện-ích)
1. [Ngôn ngữ khác](#ngôn-ngữ-khác)
1. [Các trình duyệt hỗ trợ](#các-trình-duyệt-hỗ-trợ)
## Query Selector
Đối với những selector phổ biến như class, id hoặc thuộc tính thì chúng ta có thể sử dụng `document.querySelector` hoặc `document.querySelectorAll` để thay thế cho jQuery selector. Sự khác biệt của hai hàm này là ở chỗ:
* `document.querySelector` trả về element đầu tiên được tìm thấy
* `document.querySelectorAll` trả về tất cả các element được tìm thấy dưới dạng một instance của NodeList. Nó có thể được convert qua array bằng cách `[].slice.call(document.querySelectorAll(selector) || []);`
* Nếu không có element nào được tìm thấy, thì jQuery sẽ trả về một array rỗng `[]` trong khi đó DOM API sẽ trả về `null`. Hãy chú ý đến Null Pointer Exception. Bạn có thể sử dụng toán tử `||` để đặt giá trị default nếu như không có element nào được tìm thấy, ví dụ như `document.querySelectorAll(selector) || []`
> Chú ý : `document.querySelector``document.querySelectorAll` hoạt động khá **CHẬM**, hãy thử dùng `getElementById`, `document.getElementsByClassName` hoặc `document.getElementsByTagName` nếu bạn muốn đạt hiệu suất tốt hơn.
- [1.0](#1.0) <a name='1.0'></a> Query bằng selector
```js
// jQuery
$('selector');
// Native
document.querySelectorAll('selector');
```
- [1.1](#1.1) <a name='1.1'></a> Query bằng class
```js
// jQuery
$('.class');
// Native
document.querySelectorAll('.class');
// hoặc
document.getElementsByClassName('class');
```
- [1.2](#1.2) <a name='1.2'></a> Query bằng id
```js
// jQuery
$('#id');
// Native
document.querySelector('#id');
// hoặc
document.getElementById('id');
```
- [1.3](#1.3) <a name='1.3'></a> Query bằng thuộc tính
```js
// jQuery
$('a[target=_blank]');
// Native
document.querySelectorAll('a[target=_blank]');
```
- [1.4](#1.4) <a name='1.4'></a> Tìm bất cứ gì.
+ Tìm node
```js
// jQuery
$el.find('li');
// Native
el.querySelectorAll('li');
```
+ Tìm body
```js
// jQuery
$('body');
// Native
document.body;
```
+ lấy thuộc tính
```js
// jQuery
$el.attr('foo');
// Native
e.getAttribute('foo');
```
+ Lấy giá trị của thuộc tính `data`
```js
// jQuery
$el.data('foo');
// Native
// using getAttribute
el.getAttribute('data-foo');
// you can also use `dataset` if only need to support IE 11+
el.dataset['foo'];
```
- [1.5](#1.5) <a name='1.5'></a> Tìm element cùng level/trước/sau
+ Element cùng level
```js
// jQuery
$el.siblings();
// Native
[].filter.call(el.parentNode.children, function(child) {
return child !== el;
});
```
+ Element ở phía trước
```js
// jQuery
$el.prev();
// Native
el.previousElementSibling;
```
+ Element ở phía sau
```js
// next
$el.next();
el.nextElementSibling;
```
- [1.6](#1.6) <a name='1.6'></a> Element gần nhất
Trả về element đầu tiên có selector khớp với yêu cầu khi duyệt từ element hiện tại trở lên tới document.
```js
// jQuery
$el.closest(queryString);
// Native
function closest(el, selector) {
const matchesSelector = el.matches || el.webkitMatchesSelector || el.mozMatchesSelector || el.msMatchesSelector;
while (el) {
if (matchesSelector.call(el, selector)) {
return el;
} else {
el = el.parentElement;
}
}
return null;
}
```
- [1.7](#1.7) <a name='1.7'></a> Tìm parent
Truy ngược một cách đệ quy tổ tiên của element hiện tại, cho đến khi tìm được một element tổ tiên ( element cần tìm ) mà element đó là con trực tiếp của element khớp với selector được cung cấp, Return lại element cần tìm đó.
```js
// jQuery
$el.parentsUntil(selector, filter);
// Native
function parentsUntil(el, selector, filter) {
const result = [];
const matchesSelector = el.matches || el.webkitMatchesSelector || el.mozMatchesSelector || el.msMatchesSelector;
// match start from parent
el = el.parentElement;
while (el && !matchesSelector.call(el, selector)) {
if (!filter) {
result.push(el);
} else {
if (matchesSelector.call(el, filter)) {
result.push(el);
}
}
el = el.parentElement;
}
return result;
}
```
- [1.8](#1.8) <a name='1.8'></a> Form
+ Input/Textarea
```js
// jQuery
$('#my-input').val();
// Native
document.querySelector('#my-input').value;
```
+ Lấy index của e.currentTarget trong danh sách các element khớp với selector `.radio`
```js
// jQuery
$(e.currentTarget).index('.radio');
// Native
[].indexOf.call(document.querySelectAll('.radio'), e.currentTarget);
```
- [1.9](#1.9) <a name='1.9'></a> Nội dung Iframe
`$('iframe').contents()` trả về thuộc tính `contentDocument` của iframe được tìm thấy
+ Nọi dung iframe
```js
// jQuery
$iframe.contents();
// Native
iframe.contentDocument;
```
+ Query Iframe
```js
// jQuery
$iframe.contents().find('.css');
// Native
iframe.contentDocument.querySelectorAll('.css');
```
**[⬆ Trở về đầu](#danh-mục)**
## CSS & Style
- [2.1](#2.1) <a name='2.1'></a> CSS
+ Lấy style
```js
// jQuery
$el.css("color");
// Native
// NOTE: Bug đã được biết, sẽ trả về 'auto' nếu giá trị của style là 'auto'
const win = el.ownerDocument.defaultView;
// null means not return presudo styles
win.getComputedStyle(el, null).color;
```
+ Đặt style
```js
// jQuery
$el.css({ color: "#ff0011" });
// Native
el.style.color = '#ff0011';
```
+ Lấy/Đặt Nhiều style
Nếu bạn muốn đặt nhiều style một lần, bạn có thể sẽ thích phương thức [setStyles](https://github.com/oneuijs/oui-dom-utils/blob/master/src/index.js#L194) trong thư viện oui-dom-utils.
+ Thêm class và element
```js
// jQuery
$el.addClass(className);
// Native
el.classList.add(className);
```
+ Loại bỏ class class ra khỏi element
```js
// jQuery
$el.removeClass(className);
// Native
el.classList.remove(className);
```
+ Kiểm tra xem element có class nào đó hay không
```js
// jQuery
$el.hasClass(className);
// Native
el.classList.contains(className);
```
+ Toggle class
```js
// jQuery
$el.toggleClass(className);
// Native
el.classList.toggle(className);
```
- [2.2](#2.2) <a name='2.2'></a> Chiều rộng, chiều cao
Về mặt lý thuyết thì chiều rộng và chiều cao giống như nhau trong cả jQuery và DOM API:
+ Chiều rộng của window
```js
// window height
$(window).height();
// trừ đi scrollbar
window.document.documentElement.clientHeight;
// Tính luôn scrollbar
window.innerHeight;
```
+ Chiều cao của Document
```js
// jQuery
$(document).height();
// Native
document.documentElement.scrollHeight;
```
+ Chiều cao của element
```js
// jQuery
$el.height();
// Native
function getHeight(el) {
const styles = this.getComputedStyles(el);
const height = el.offsetHeight;
const borderTopWidth = parseFloat(styles.borderTopWidth);
const borderBottomWidth = parseFloat(styles.borderBottomWidth);
const paddingTop = parseFloat(styles.paddingTop);
const paddingBottom = parseFloat(styles.paddingBottom);
return height - borderBottomWidth - borderTopWidth - paddingTop - paddingBottom;
}
// chính xác tới số nguyênkhi có thuộc tính `box-sizing``border-box`, nó là `height`; khi box-sizing là `content-box`, nó là `height + padding + border`
el.clientHeight;
// Chính xác tới số thập phânkhi `box-sizing``border-box`, nó là `height`; khi `box-sizing``content-box`, nó là `height + padding + border`
el.getBoundingClientRect().height;
```
- [2.3](#2.3) <a name='2.3'></a> Position & Offset
+ Position
```js
// jQuery
$el.position();
// Native
{ left: el.offsetLeft, top: el.offsetTop }
```
+ Offset
```js
// jQuery
$el.offset();
// Native
function getOffset (el) {
const box = el.getBoundingClientRect();
return {
top: box.top + window.pageYOffset - document.documentElement.clientTop,
left: box.left + window.pageXOffset - document.documentElement.clientLeft
}
}
```
- [2.4](#2.4) <a name='2.4'></a> Scroll Top
```js
// jQuery
$(window).scrollTop();
// Native
(document.documentElement && document.documentElement.scrollTop) || document.body.scrollTop;
```
**[⬆ Trở về đầu](#danh-mục)**
## Thao tác với DOM
- [3.1](#3.1) <a name='3.1'></a> Loại bỏ
```js
// jQuery
$el.remove();
// Native
el.parentNode.removeChild(el);
```
- [3.2](#3.2) <a name='3.2'></a> Text
+ Lấy text
```js
// jQuery
$el.text();
// Native
el.textContent;
```
+ Đặt giá trị text
```js
// jQuery
$el.text(string);
// Native
el.textContent = string;
```
- [3.3](#3.3) <a name='3.3'></a> HTML
+ Lấy HTML
```js
// jQuery
$el.html();
// Native
el.innerHTML;
```
+ Đặt giá trị HTML
```js
// jQuery
$el.html(htmlString);
// Native
el.innerHTML = htmlString;
```
- [3.4](#3.4) <a name='3.4'></a> Append
append một element sau element con cuối cùng của element cha
```js
// jQuery
$el.append("<div id='container'>hello</div>");
// Native
let newEl = document.createElement('div');
newEl.setAttribute('id', 'container');
newEl.innerHTML = 'hello';
el.appendChild(newEl);
```
- [3.5](#3.5) <a name='3.5'></a> Prepend
```js
// jQuery
$el.prepend("<div id='container'>hello</div>");
// Native
let newEl = document.createElement('div');
newEl.setAttribute('id', 'container');
newEl.innerHTML = 'hello';
el.insertBefore(newEl, el.firstChild);
```
- [3.6](#3.6) <a name='3.6'></a> insertBefore
Chèn một node vào trước element được query.
```js
// jQuery
$newEl.insertBefore(queryString);
// Native
const target = document.querySelector(queryString);
target.parentNode.insertBefore(newEl, target);
```
- [3.7](#3.7) <a name='3.7'></a> insertAfter
Chèn node vào sau element được query
```js
// jQuery
$newEl.insertAfter(queryString);
// Native
const target = document.querySelector(queryString);
target.parentNode.insertBefore(newEl, target.nextSibling);
```
**[⬆ Trở về đầu](#danh-mục)**
## Ajax
Thay thế bằng [fetch](https://github.com/camsong/fetch-ie8) và [fetch-jsonp](https://github.com/camsong/fetch-jsonp)
**[⬆ Trở về đầu](#danh-mục)**
## Events
Để có một sự thay thế đầy đủ nhất, bạn nên sử dụng https://github.com/oneuijs/oui-dom-events
- [5.1](#5.1) <a name='5.1'></a> Bind event bằng on
```js
// jQuery
$el.on(eventName, eventHandler);
// Native
el.addEventListener(eventName, eventHandler);
```
- [5.2](#5.2) <a name='5.2'></a> Unbind event bằng off
```js
// jQuery
$el.off(eventName, eventHandler);
// Native
el.removeEventListener(eventName, eventHandler);
```
- [5.3](#5.3) <a name='5.3'></a> Trigger
```js
// jQuery
$(el).trigger('custom-event', {key1: 'data'});
// Native
if (window.CustomEvent) {
const event = new CustomEvent('custom-event', {detail: {key1: 'data'}});
} else {
const event = document.createEvent('CustomEvent');
event.initCustomEvent('custom-event', true, true, {key1: 'data'});
}
el.dispatchEvent(event);
```
**[⬆ Trở về đầu](#danh-mục)**
## Hàm tiện ích
- [6.1](#6.1) <a name='6.1'></a> isArray
```js
// jQuery
$.isArray(range);
// Native
Array.isArray(range);
```
- [6.2](#6.2) <a name='6.2'></a> Trim
```js
// jQuery
$.trim(string);
// Native
string.trim();
```
- [6.3](#6.3) <a name='6.3'></a> Object Assign
Mở rộng, sử dụng object.assign https://github.com/ljharb/object.assign
```js
// jQuery
$.extend({}, defaultOpts, opts);
// Native
Object.assign({}, defaultOpts, opts);
```
- [6.4](#6.4) <a name='6.4'></a> Contains
```js
// jQuery
$.contains(el, child);
// Native
el !== child && el.contains(child);
```
**[⬆ Trở về đầu](#danh-mục)**
## Ngôn ngữ khác
* [한국어](./README.ko-KR.md)
* [简体中文](./README.zh-CN.md)
* [Bahasa Melayu](./README-my.md)
* [Português(PT-BR)](./README.pt-BR.md)
* [Tiếng Việt Nam](./README-vi.md)
* [Русский](./README-ru.md)
* [Türkçe](./README-tr.md)
## Các trình duyệt hỗ trợ
![Chrome](https://raw.github.com/alrra/browser-logos/master/chrome/chrome_48x48.png) | ![Firefox](https://raw.github.com/alrra/browser-logos/master/firefox/firefox_48x48.png) | ![IE](https://raw.github.com/alrra/browser-logos/master/internet-explorer/internet-explorer_48x48.png) | ![Opera](https://raw.github.com/alrra/browser-logos/master/opera/opera_48x48.png) | ![Safari](https://raw.github.com/alrra/browser-logos/master/safari/safari_48x48.png)
--- | --- | --- | --- | --- |
Latest ✔ | Latest ✔ | 10+ ✔ | Latest ✔ | 6.1+ ✔ |
# Giấy phép
MIT

View File

@ -0,0 +1,709 @@
## You Don't Need jQuery
오늘날 프론트엔드 개발 환경은 급격히 진화하고 있고, 모던 브라우저들은 이미 충분히 많은 DOM/BOM API들을 구현했습니다. 우리는 jQuery를 DOM 처리나 이벤트를 위해 처음부터 배울 필요가 없습니다. React, Angular, Vue같은 프론트엔드 라이브러리들이 주도권을 차지하는 동안 DOM을 바로 처리하는 것은 안티패턴이 되었고, jQuery의 중요성은 줄어들었습니다. 이 프로젝트는 대부분의 jQuery 메소드의 대안을 IE 10+ 이상을 지원하는 네이티브 구현으로 소개합니다.
## 목차
1. [Query Selector](#query-selector)
1. [CSS & Style](#css--style)
1. [DOM 조작](#dom-조작)
1. [Ajax](#ajax)
1. [이벤트](#이벤트)
1. [유틸리티](#유틸리티)
1. [대안방법](#대안방법)
1. [번역](#번역)
1. [브라우저 지원](#브라우저-지원)
## Query Selector
평범한 class, id, attribute같은 selecotor는 `document.querySelector``document.querySelectorAll`으로 대체할 수 있습니다.
* `document.querySelector`는 처음 매칭된 엘리먼트를 반환합니다.
* `document.querySelectorAll`는 모든 매칭된 엘리먼트를 NodeList로 반환합니다. `[].slice.call`을 사용해서 Array로 변환할 수 있습니다.
* 만약 매칭된 엘리멘트가 없으면 jQuery는 `[]` 를 반환하지만 DOM API는 `null`을 반환합니다. Null Pointer Exception에 주의하세요.
> 안내: `document.querySelector``document.querySelectorAll`는 꽤 **느립니다**, `getElementById``document.getElementsByClassName`, `document.getElementsByTagName`를 사용하면 퍼포먼스가 향상을 기대할 수 있습니다.
- [1.0](#1.0) <a name='1.0'></a> selector로 찾기
```js
// jQuery
$('selector');
// Native
document.querySelectorAll('selector');
```
- [1.1](#1.1) <a name='1.1'></a> class로 찾기
```js
// jQuery
$('.class');
// Native
document.querySelectorAll('.class');
// or
document.getElementsByClassName('class');
```
- [1.2](#1.2) <a name='1.2'></a> id로 찾기
```js
// jQuery
$('#id');
// Native
document.querySelector('#id');
// or
document.getElementById('id');
```
- [1.3](#1.3) <a name='1.3'></a> 속성(attribute)으로 찾기
```js
// jQuery
$('a[target=_blank]');
// Native
document.querySelectorAll('a[target=_blank]');
```
- [1.4](#1.4) <a name='1.4'></a> 자식에서 찾기
```js
// jQuery
$el.find('li');
// Native
el.querySelectorAll('li');
```
- [1.5](#1.5) <a name='1.5'></a> 형제/이전/다음 엘리먼트 찾기
+ 형제 엘리먼트
```js
// jQuery
$el.siblings();
// Native
[].filter.call(el.parentNode.children, function(child) {
return child !== el;
});
```
+ 이전 엘리먼트
```js
// jQuery
$el.prev();
// Native
el.previousElementSibling;
```
+ 다음 엘리먼트
```js
// jQuery
$el.next();
// Native
el.nextElementSibling;
```
- [1.6](#1.6) <a name='1.6'></a> Closest
현재 엘리먼트부터 document로 이동하면서 주어진 셀렉터와 일치하는 가장 가까운 엘리먼트를 반환합니다.
```js
// jQuery
$el.closest(selector);
// Native - 최신 브라우저만, IE는 미지원
el.closest(selector);
// Native - IE10 이상
function closest(el, selector) {
const matchesSelector = el.matches || el.webkitMatchesSelector || el.mozMatchesSelector || el.msMatchesSelector;
while (el) {
if (matchesSelector.call(el, selector)) {
return el;
} else {
el = el.parentElement;
}
}
return null;
}
```
- [1.7](#1.7) <a name='1.7'></a> Parents Until
주어진 셀렉터에 매칭되는 엘리먼트를 찾기까지 부모 태그들을 위로 올라가며 탐색하여 저장해두었다가 DOM 노드 또는 jQuery object로 반환합니다.
```js
// jQuery
$el.parentsUntil(selector, filter);
// Native
function parentsUntil(el, selector, filter) {
const result = [];
const matchesSelector = el.matches || el.webkitMatchesSelector || el.mozMatchesSelector || el.msMatchesSelector;
// match start from parent
el = el.parentElement;
while (el && !matchesSelector.call(el, selector)) {
if (!filter) {
result.push(el);
} else {
if (matchesSelector.call(el, filter)) {
result.push(el);
}
}
el = el.parentElement;
}
return result;
}
```
- [1.8](#1.8) <a name='1.8'></a> Form
+ Input/Textarea
```js
// jQuery
$('#my-input').val();
// Native
document.querySelector('#my-input').value;
```
+ e.currentTarget이 `.radio`의 몇번째인지 구하기
```js
// jQuery
$(e.currentTarget).index('.radio');
// Native
[].indexOf.call(document.querySelectAll('.radio'), e.currentTarget);
```
- [1.9](#1.9) <a name='1.9'></a> Iframe Contents
`$('iframe').contents()`는 iframe에 한정해서 `contentDocument`를 반환합니다.
+ Iframe contents
```js
// jQuery
$iframe.contents();
// Native
iframe.contentDocument;
```
+ Iframe에서 찾기
```js
// jQuery
$iframe.contents().find('.css');
// Native
iframe.contentDocument.querySelectorAll('.css');
```
- [1.10](#1.10) <a name='1.10'></a> body 얻기
```js
// jQuery
$('body');
// Native
document.body;
```
- [1.11](#1.11) <a name='1.11'></a> 속성 얻기 및 설정
+ 속성 얻기
```js
// jQuery
$el.attr('foo');
// Native
el.getAttribute('foo');
```
+ 속성 설정하기
```js
// jQuery, DOM 변형 없이 메모리에서 작동됩니다.
$el.attr('foo', 'bar');
// Native
el.setAttribute('foo', 'bar');
```
+ `data-` 속성 얻기
```js
// jQuery
$el.data('foo');
// Native (`getAttribute` 사용)
el.getAttribute('data-foo');
// Native (IE 11 이상의 지원만 필요하다면 `dataset`을 사용)
el.dataset['foo'];
```
**[⬆ 목차로 돌아가기](#목차)**
## CSS & Style
- [2.1](#2.1) <a name='2.1'></a> CSS
+ style값 얻기
```js
// jQuery
$el.css("color");
// Native
// NOTE: 알려진 버그로, style값이 'auto'이면 'auto'를 반환합니다.
const win = el.ownerDocument.defaultView;
// null은 가상 스타일은 반환하지 않음을 의미합니다.
win.getComputedStyle(el, null).color;
```
+ style값 설정하기
```js
// jQuery
$el.css({ color: "#ff0011" });
// Native
el.style.color = '#ff0011';
```
+ Style값들을 동시에 얻거나 설정하기
만약 한번에 여러 style값을 바꾸고 싶다면 oui-dom-utils 패키지의 [setStyles](https://github.com/oneuijs/oui-dom-utils/blob/master/src/index.js#L194)를 사용해보세요.
+ class 추가하기
```js
// jQuery
$el.addClass(className);
// Native
el.classList.add(className);
```
+ class 제거하기
```js
// jQuery
$el.removeClass(className);
// Native
el.classList.remove(className);
```
+ class를 포함하고 있는지 검사하기
```js
// jQuery
$el.hasClass(className);
// Native
el.classList.contains(className);
```
+ class 토글하기
```js
// jQuery
$el.toggleClass(className);
// Native
el.classList.toggle(className);
```
- [2.2](#2.2) <a name='2.2'></a> 폭과 높이
폭과 높이는 이론상 동일합니다. 높이로 예를 들겠습니다.
+ Window의 높이
```js
// window 높이
$(window).height();
// jQuery처럼 스크롤바를 제외하기
window.document.documentElement.clientHeight;
// 스크롤바 포함
window.innerHeight;
```
+ 문서 높이
```js
// jQuery
$(document).height();
// Native
document.documentElement.scrollHeight;
```
+ Element 높이
```js
// jQuery
$el.height();
// Native
function getHeight(el) {
const styles = this.getComputedStyles(el);
const height = el.offsetHeight;
const borderTopWidth = parseFloat(styles.borderTopWidth);
const borderBottomWidth = parseFloat(styles.borderBottomWidth);
const paddingTop = parseFloat(styles.paddingTop);
const paddingBottom = parseFloat(styles.paddingBottom);
return height - borderBottomWidth - borderTopWidth - paddingTop - paddingBottom;
}
// 정수로 정확하게(`border-box`일 때 이 값은 `height`이고, `content-box`일 때, 이 값은 `height + padding + border`
el.clientHeight;
// 실수로 정확하게(`border-box`일 때 이 값은 `height`이고, `content-box`일 때, 이 값은 `height + padding + border`
el.getBoundingClientRect().height;
```
- [2.3](#2.3) <a name='2.3'></a> Position & Offset
+ Position
```js
// jQuery
$el.position();
// Native
{ left: el.offsetLeft, top: el.offsetTop }
```
+ Offset
```js
// jQuery
$el.offset();
// Native
function getOffset (el) {
const box = el.getBoundingClientRect();
return {
top: box.top + window.pageYOffset - document.documentElement.clientTop,
left: box.left + window.pageXOffset - document.documentElement.clientLeft
}
}
```
- [2.4](#2.4) <a name='2.4'></a> Scroll Top
```js
// jQuery
$(window).scrollTop();
// Native
(document.documentElement && document.documentElement.scrollTop) || document.body.scrollTop;
```
**[⬆ 목차로 돌아가기](#목차)**
## DOM 조작
- [3.1](#3.1) <a name='3.1'></a> 제거
```js
// jQuery
$el.remove();
// Native
el.parentNode.removeChild(el);
```
- [3.2](#3.2) <a name='3.2'></a> Text
+ text 가져오기
```js
// jQuery
$el.text();
// Native
el.textContent;
```
+ text 설정하기
```js
// jQuery
$el.text(string);
// Native
el.textContent = string;
```
- [3.3](#3.3) <a name='3.3'></a> HTML
+ HTML 가져오기
```js
// jQuery
$el.html();
// Native
el.innerHTML;
```
+ HTML 설정하기
```js
// jQuery
$el.html(htmlString);
// Native
el.innerHTML = htmlString;
```
- [3.4](#3.4) <a name='3.4'></a> 해당 엘리먼트의 자식들 뒤에 넣기(Append)
부모 엘리먼트의 마지막 자식으로 엘리먼트를 추가합니다.
```js
// jQuery
$el.append("<div id='container'>hello</div>");
// Native
el.insertAdjacentHTML("beforeend","<div id='container'>hello</div>");
```
- [3.5](#3.5) <a name='3.5'></a> 해당 엘리먼트의 자식들 앞에 넣기(Prepend)
```js
// jQuery
$el.prepend("<div id='container'>hello</div>");
// Native
el.insertAdjacentHTML("afterbegin","<div id='container'>hello</div>");
```
- [3.6](#3.6) <a name='3.6'></a> 해당 엘리먼트 앞에 넣기(insertBefore)
새 노드를 선택한 엘리먼트 앞에 넣습니다.
```js
// jQuery
$newEl.insertBefore(queryString);
// Native
const target = document.querySelector(queryString);
target.parentNode.insertBefore(newEl, target);
```
- [3.7](#3.7) <a name='3.7'></a> 해당 엘리먼트 뒤에 넣기(insertAfter)
새 노드를 선택한 엘리먼트 뒤에 넣습니다.
```js
// jQuery
$newEl.insertAfter(queryString);
// Native
const target = document.querySelector(queryString);
target.parentNode.insertBefore(newEl, target.nextSibling);
```
- [3.8](#3.8) <a name='3.8'></a> is
query selector와 일치하면 `true` 를 반환합니다.
```js
// jQuery
$el.is(selector);
// Native
el.matches(selector);
```
- [3.9](#3.9) <a name='3.9'></a> clone
엘리먼트의 복제본을 만듭니다.
```js
// jQuery
$el.clone();
// Native
el.cloneNode();
// Deep clone은 파라미터를 `true` 로 설정하세요.
```
- [3.10](#3.10) <a name='3.10'></a> empty
모든 자식 노드를 제거합니다.
```js
// jQuery
$el.empty();
// Native
el.innerHTML = '';
```
**[⬆ 목차로 돌아가기](#목차)**
## Ajax
[Fetch API](https://fetch.spec.whatwg.org/) 는 XMLHttpRequest를 ajax로 대체하는 새로운 표준 입니다. Chrome과 Firefox에서 작동하며, polyfill을 이용해서 구형 브라우저에서 작동되도록 만들 수도 있습니다.
IE9 이상에서 지원하는 [github/fetch](http://github.com/github/fetch) 혹은 IE8 이상에서 지원하는 [fetch-ie8](https://github.com/camsong/fetch-ie8/), JSONP 요청을 만드는 [fetch-jsonp](https://github.com/camsong/fetch-jsonp)를 이용해보세요.
**[⬆ 목차로 돌아가기](#목차)**
## 이벤트
namespace와 delegation을 포함해서 완전히 갈아 엎길 원하시면 https://github.com/oneuijs/oui-dom-events 를 고려해보세요.
- [5.1](#5.1) <a name='5.1'></a> 이벤트 Bind 걸기
```js
// jQuery
$el.on(eventName, eventHandler);
// Native
el.addEventListener(eventName, eventHandler);
```
- [5.2](#5.2) <a name='5.2'></a> 이벤트 Bind 풀기
```js
// jQuery
$el.off(eventName, eventHandler);
// Native
el.removeEventListener(eventName, eventHandler);
```
- [5.3](#5.3) <a name='5.3'></a> 이벤트 발생시키기(Trigger)
```js
// jQuery
$(el).trigger('custom-event', {key1: 'data'});
// Native
if (window.CustomEvent) {
const event = new CustomEvent('custom-event', {detail: {key1: 'data'}});
} else {
const event = document.createEvent('CustomEvent');
event.initCustomEvent('custom-event', true, true, {key1: 'data'});
}
el.dispatchEvent(event);
```
**[⬆ 목차로 돌아가기](#목차)**
## 유틸리티
- [6.1](#6.1) <a name='6.1'></a> 배열인지 검사(isArray)
```js
// jQuery
$.isArray(range);
// Native
Array.isArray(range);
```
- [6.2](#6.2) <a name='6.2'></a> 앞뒤 공백 지우기(Trim)
```js
// jQuery
$.trim(string);
// Native
string.trim();
```
- [6.3](#6.3) <a name='6.3'></a> Object Assign
사용하려면 object.assign polyfill을 사용하세요. https://github.com/ljharb/object.assign
```js
// jQuery
$.extend({}, defaultOpts, opts);
// Native
Object.assign({}, defaultOpts, opts);
```
- [6.4](#6.4) <a name='6.4'></a> Contains
```js
// jQuery
$.contains(el, child);
// Native
el !== child && el.contains(child);
```
- [6.5](#6.5) <a name='6.5'></a> inArray
```js
// jQuery
$.inArray(item, array);
// Native
array.indexOf(item);
```
- [6.6](#6.6) <a name='6.6'></a> map
```js
// jQuery
$.map(array, function(value, index) {
});
// Native
Array.map(function(value, index) {
});
```
**[⬆ 목차로 돌아가기](#목차)**
## 대안방법
* [You Might Not Need jQuery](http://youmightnotneedjquery.com/) - 일반 자바스크립트로 공통이벤트, 엘리먼트, ajax 등을 다루는 방법 예제.
* [npm-dom](http://github.com/npm-dom) 과 [webmodules](http://github.com/webmodules) - 개별 DOM모듈을 NPM에서 찾을 수 있습니다.
## 번역
* [한국어](./README.ko-KR.md)
* [简体中文](./README.zh-CN.md)
* [Bahasa Melayu](./README-my.md)
* [Bahasa Indonesia](./README-id.md)
* [Português(PT-BR)](./README.pt-BR.md)
* [Tiếng Việt Nam](./README-vi.md)
* [Español](./README-es.md)
* [Русский](./README-ru.md)
* [Türkçe](./README-tr.md)
* [Italian](./README-it.md)
## 브라우저 지원
![Chrome](https://raw.github.com/alrra/browser-logos/master/chrome/chrome_48x48.png) | ![Firefox](https://raw.github.com/alrra/browser-logos/master/firefox/firefox_48x48.png) | ![IE](https://raw.github.com/alrra/browser-logos/master/internet-explorer/internet-explorer_48x48.png) | ![Opera](https://raw.github.com/alrra/browser-logos/master/opera/opera_48x48.png) | ![Safari](https://raw.github.com/alrra/browser-logos/master/safari/safari_48x48.png)
--- | --- | --- | --- | --- |
Latest ✔ | Latest ✔ | 10+ ✔ | Latest ✔ | 6.1+ ✔ |
# License
MIT

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,628 @@
> #### You Don't Need jQuery
Você não precisa de jQuery
---
Ambientes Frontend evoluem rapidamente nos dias de hoje, navegadores modernos já implementaram uma grande parte das APIs DOM/BOM que são boas o suficiente. Nós não temos que aprender jQuery a partir do zero para manipulação do DOM ou eventos. Nesse meio tempo, graças a bibliotecas frontend como React, Angular e Vue, a manipulação direta do DOM torna-se um anti-padrão, jQuery é menos importante do que nunca. Este projeto resume a maioria das alternativas dos métodos jQuery em implementação nativa, com suporte ao IE 10+.
## Tabela de conteúdos
1. [Query Selector](#query-selector)
1. [CSS & Estilo](#css--estilo)
1. [Manipulação do DOM](#manipulação-do-dom)
1. [Ajax](#ajax)
1. [Eventos](#eventos)
1. [Utilitários](#utilitários)
1. [Suporte dos Navegadores](#suporte-dos-navegadores)
## Query Selector
No lugar de seletores comuns como classe, id ou atributo podemos usar `document.querySelector` ou `document.querySelectorAll` para substituição. As diferenças são:
* `document.querySelector` retorna o primeiro elemento correspondente
* `document.querySelectorAll` retorna todos os elementos correspondentes como NodeList. Pode ser convertido para Array usando `[].slice.call(document.querySelectorAll(selector) || []);`
* Se não tiver elementos correspondentes, jQuery retornaria `[]` considerando que a DOM API irá retornar `null`. Preste atenção ao Null Pointer Exception. Você também pode usar `||` para definir um valor padrão caso nenhum elemento seja encontrado, como `document.querySelectorAll(selector) || []`
> Aviso: `document.querySelector` e `document.querySelectorAll` são bastante **LENTOS**, tente usar `getElementById`, `document.getElementsByClassName` ou `document.getElementsByTagName` se você quer ter uma maior performance.
- [1.0](#1.0) <a name='1.0'></a> Query por seletor
```js
// jQuery
$('selector');
// Nativo
document.querySelectorAll('selector');
```
- [1.1](#1.1) <a name='1.1'></a> Query por classe
```js
// jQuery
$('.class');
// Nativo
document.querySelectorAll('.class');
// ou
document.getElementsByClassName('class');
```
- [1.2](#1.2) <a name='1.2'></a> Query por id
```js
// jQuery
$('#id');
// Nativo
document.querySelector('#id');
// ou
document.getElementById('id');
```
- [1.3](#1.3) <a name='1.3'></a> Query por atributo
```js
// jQuery
$('a[target=_blank]');
// Nativo
document.querySelectorAll('a[target=_blank]');
```
- [1.4](#1.4) <a name='1.4'></a> Find sth.
+ Busca por nós
```js
// jQuery
$el.find('li');
// Nativo
el.querySelectorAll('li');
```
+ Buscar `body`
```js
// jQuery
$('body');
// Nativo
document.body;
```
+ Buscar atributos
```js
// jQuery
$el.attr('foo');
// Nativo
e.getAttribute('foo');
```
+ Buscar atributos `data-`
```js
// jQuery
$el.data('foo');
// Nativo
// usando getAttribute
el.getAttribute('data-foo');
// você também pode usar `dataset` se você precisar suportar apenas IE 11+
el.dataset['foo'];
```
- [1.5](#1.5) <a name='1.5'></a> Sibling/Previous/Next Elements
+ Sibling elements
```js
// jQuery
$el.siblings();
// Nativo
[].filter.call(el.parentNode.children, function(child) {
return child !== el;
});
```
+ Previous elements
```js
// jQuery
$el.prev();
// Nativo
el.previousElementSibling;
```
+ Next elements
```js
// jQuery
$el.next();
// Nativo
el.nextElementSibling;
```
- [1.6](#1.6) <a name='1.6'></a> Closest
Retorna o primeiro elemento que corresponda ao seletor, partindo do elemento atual para o document.
```js
// jQuery
$el.closest(queryString);
// Nativo
function closest(el, selector) {
const matchesSelector = el.matches || el.webkitMatchesSelector || el.mozMatchesSelector || el.msMatchesSelector;
while (el) {
if (matchesSelector.call(el, selector)) {
return el;
} else {
el = el.parentElement;
}
}
return null;
}
```
- [1.7](#1.7) <a name='1.7'></a> Parents Until
Obtém os ancestrais de cada elemento no atual conjunto de elementos combinados, mas não inclui o elemento correspondente pelo seletor, nó do DOM, ou objeto jQuery.
```js
// jQuery
$el.parentsUntil(selector, filter);
// Nativo
function parentsUntil(el, selector, filter) {
const result = [];
const matchesSelector = el.matches || el.webkitMatchesSelector || el.mozMatchesSelector || el.msMatchesSelector;
// match start from parent
el = el.parentElement;
while (el && !matchesSelector.call(el, selector)) {
if (!filter) {
result.push(el);
} else {
if (matchesSelector.call(el, filter)) {
result.push(el);
}
}
el = el.parentElement;
}
return result;
}
```
- [1.8](#1.8) <a name='1.8'></a> Form
+ Input/Textarea
```js
// jQuery
$('#my-input').val();
// Nativo
document.querySelector('#my-input').value;
```
+ Obter o índice do e.currentTarget entre `.radio`
```js
// jQuery
$(e.currentTarget).index('.radio');
// Nativo
[].indexOf.call(document.querySelectAll('.radio'), e.currentTarget);
```
- [1.9](#1.9) <a name='1.9'></a> Iframe Contents
`$('iframe').contents()` retorna `contentDocument` para este iframe específico
+ Iframe contents
```js
// jQuery
$iframe.contents();
// Nativo
iframe.contentDocument;
```
+ Iframe Query
```js
// jQuery
$iframe.contents().find('.css');
// Nativo
iframe.contentDocument.querySelectorAll('.css');
```
**[⬆ ir para o topo](#tabela-de-conteúdos)**
## CSS & Estilo
- [2.1](#2.1) <a name='2.1'></a> CSS
+ Obter estilo
```js
// jQuery
$el.css("color");
// Nativo
// AVISO: Bug conhecido, irá retornar 'auto' se o valor do estilo for 'auto'
const win = el.ownerDocument.defaultView;
// null significa não retornar estilos
win.getComputedStyle(el, null).color;
```
+ Definir Estilo
```js
// jQuery
$el.css({ color: "#ff0011" });
// Nativo
el.style.color = '#ff0011';
```
+ Get/Set Styles
Observe que se você deseja setar vários estilos de uma vez, você pode optar por [setStyles](https://github.com/oneuijs/oui-dom-utils/blob/master/src/index.js#L194) método no pacote oui-dom-utils.
+ Adicionar classe
```js
// jQuery
$el.addClass(className);
// Nativo
el.classList.add(className);
```
+ Remover classe
```js
// jQuery
$el.removeClass(className);
// Nativo
el.classList.remove(className);
```
+ Verificar classe
```js
// jQuery
$el.hasClass(className);
// Nativo
el.classList.contains(className);
```
+ Toggle class
```js
// jQuery
$el.toggleClass(className);
// Nativo
el.classList.toggle(className);
```
- [2.2](#2.2) <a name='2.2'></a> Largura e Altura
`width` e `height` são teoricamente idênticos, vamos pegar `height` como exemplo:
+ Altura da janela
```jsc
// window height
$(window).height();
// sem scrollbar, se comporta como jQuery
window.document.documentElement.clientHeight;
// com scrollbar
window.innerHeight;
```
+ Altura do Documento
```js
// jQuery
$(document).height();
// Nativo
document.documentElement.scrollHeight;
```
+ Altura do Elemento
```js
// jQuery
$el.height();
// Nativo
function getHeight(el) {
const styles = this.getComputedStyles(el);
const height = el.offsetHeight;
const borderTopWidth = parseFloat(styles.borderTopWidth);
const borderBottomWidth = parseFloat(styles.borderBottomWidth);
const paddingTop = parseFloat(styles.paddingTop);
const paddingBottom = parseFloat(styles.paddingBottom);
return height - borderBottomWidth - borderTopWidth - paddingTop - paddingBottom;
}
// preciso para inteiroquando `border-box`, é `height`; quando `content-box`, é `height + padding + border`
el.clientHeight;
// preciso para decimalquando `border-box`, é `height`; quando `content-box`, é `height + padding + border`
el.getBoundingClientRect().height;
```
- [2.3](#2.3) <a name='2.3'></a> Position & Offset
+ Position
```js
// jQuery
$el.position();
// Nativo
{ left: el.offsetLeft, top: el.offsetTop }
```
+ Offset
```js
// jQuery
$el.offset();
// Nativo
function getOffset (el) {
const box = el.getBoundingClientRect();
return {
top: box.top + window.pageYOffset - document.documentElement.clientTop,
left: box.left + window.pageXOffset - document.documentElement.clientLeft
}
}
```
- [2.4](#2.4) <a name='2.4'></a> Rolar para o topo
```js
// jQuery
$(window).scrollTop();
// Nativo
(document.documentElement && document.documentElement.scrollTop) || document.body.scrollTop;
```
**[⬆ ir para o topo](#tabela-de-conteúdos)**
## Manipulação do Dom
- [3.1](#3.1) <a name='3.1'></a> Remover
```js
// jQuery
$el.remove();
// Nativo
el.parentNode.removeChild(el);
```
- [3.2](#3.2) <a name='3.2'></a> Texto
+ Obter texto
```js
// jQuery
$el.text();
// Nativo
el.textContent;
```
+ Definir texto
```js
// jQuery
$el.text(string);
// Nativo
el.textContent = string;
```
- [3.3](#3.3) <a name='3.3'></a> HTML
+ Obter HTML
```js
// jQuery
$el.html();
// Nativo
el.innerHTML;
```
+ Definir HTML
```js
// jQuery
$el.html(htmlString);
// Nativo
el.innerHTML = htmlString;
```
- [3.4](#3.4) <a name='3.4'></a> Append
Incluir elemento filho após o último filho do elemento pai.
```js
// jQuery
$el.append("<div id='container'>hello</div>");
// Nativo
let newEl = document.createElement('div');
newEl.setAttribute('id', 'container');
newEl.innerHTML = 'hello';
el.appendChild(newEl);
```
- [3.5](#3.5) <a name='3.5'></a> Prepend
```js
// jQuery
$el.prepend("<div id='container'>hello</div>");
// Nativo
let newEl = document.createElement('div');
newEl.setAttribute('id', 'container');
newEl.innerHTML = 'hello';
el.insertBefore(newEl, el.firstChild);
```
- [3.6](#3.6) <a name='3.6'></a> insertBefore
Insere um novo nó antes dos elementos selecionados.
```js
// jQuery
$newEl.insertBefore(queryString);
// Nativo
const target = document.querySelector(queryString);
target.parentNode.insertBefore(newEl, target);
```
- [3.7](#3.7) <a name='3.7'></a> insertAfter
Insere um novo nó após os elementos selecionados.
```js
// jQuery
$newEl.insertAfter(queryString);
// Nativo
const target = document.querySelector(queryString);
target.parentNode.insertBefore(newEl, target.nextSibling);
```
**[⬆ ir para o topo](#tabela-de-conteúdos)**
## Ajax
Substitua por [fetch](https://github.com/camsong/fetch-ie8) e [fetch-jsonp](https://github.com/camsong/fetch-jsonp)
**[⬆ ir para o topo](#tabela-de-conteúdos)**
## Eventos
Para uma substituição completa com namespace e delegation, consulte https://github.com/oneuijs/oui-dom-events
- [5.1](#5.1) <a name='5.1'></a> `Bind` num evento com `on`
```js
// jQuery
$el.on(eventName, eventHandler);
// Nativo
el.addEventListener(eventName, eventHandler);
```
- [5.2](#5.2) <a name='5.2'></a> `Unbind` num evento com `off`
```js
// jQuery
$el.off(eventName, eventHandler);
// Nativo
el.removeEventListener(eventName, eventHandler);
```
- [5.3](#5.3) <a name='5.3'></a> Trigger
```js
// jQuery
$(el).trigger('custom-event', {key1: 'data'});
// Nativo
if (window.CustomEvent) {
const event = new CustomEvent('custom-event', {detail: {key1: 'data'}});
} else {
const event = document.createEvent('CustomEvent');
event.initCustomEvent('custom-event', true, true, {key1: 'data'});
}
el.dispatchEvent(event);
```
**[⬆ ir para o topo](#tabela-de-conteúdos)**
## Utilitários
- [6.1](#6.1) <a name='6.1'></a> isArray
```js
// jQuery
$.isArray(range);
// Nativo
Array.isArray(range);
```
- [6.2](#6.2) <a name='6.2'></a> Trim
```js
// jQuery
$.trim(string);
// Nativo
string.trim();
```
- [6.3](#6.3) <a name='6.3'></a> Object Assign
Use o polyfill `object.assign` para eetender um Object: https://github.com/ljharb/object.assign
```js
// jQuery
$.extend({}, defaultOpts, opts);
// Nativo
Object.assign({}, defaultOpts, opts);
```
- [6.4](#6.4) <a name='6.4'></a> Contains
```js
// jQuery
$.contains(el, child);
// Nativo
el !== child && el.contains(child);
```
**[⬆ ir para o topo](#tabela-de-conteúdos)**
## Suporte dos Navegadores
![Chrome](https://raw.github.com/alrra/browser-logos/master/chrome/chrome_48x48.png) | ![Firefox](https://raw.github.com/alrra/browser-logos/master/firefox/firefox_48x48.png) | ![IE](https://raw.github.com/alrra/browser-logos/master/internet-explorer/internet-explorer_48x48.png) | ![Opera](https://raw.github.com/alrra/browser-logos/master/opera/opera_48x48.png) | ![Safari](https://raw.github.com/alrra/browser-logos/master/safari/safari_48x48.png)
--- | --- | --- | --- | --- |
Latest ✔ | Latest ✔ | 10+ ✔ | Latest ✔ | 6.1+ ✔ |
# Licença
MIT

View File

@ -0,0 +1,656 @@
## You Don't Need jQuery
前端发展很快,现代浏览器原生 API 已经足够好用。我们并不需要为了操作 DOM、Event 等再学习一下 jQuery 的 API。同时由于 React、Angular、Vue 等框架的流行,直接操作 DOM 不再是好的模式jQuery 使用场景大大减少。本项目总结了大部分 jQuery API 替代的方法,暂时只支持 IE10+ 以上浏览器。
## 目录
1. [Query Selector](#query-selector)
1. [CSS & Style](#css--style)
1. [DOM Manipulation](#dom-manipulation)
1. [Ajax](#ajax)
1. [Events](#events)
1. [Utilities](#utilities)
1. [Alternatives](#alternatives)
1. [Translations](#translations)
1. [Browser Support](#browser-support)
## Query Selector
常用的 class、id、属性 选择器都可以使用 `document.querySelector``document.querySelectorAll` 替代。区别是
* `document.querySelector` 返回第一个匹配的 Element
* `document.querySelectorAll` 返回所有匹配的 Element 组成的 NodeList。它可以通过 `[].slice.call()` 把它转成 Array
* 如果匹配不到任何 ElementjQuery 返回空数组 `[]`,但 `document.querySelector` 返回 `null`,注意空指针异常。当找不到时,也可以使用 `||` 设置默认的值,如 `document.querySelectorAll(selector) || []`
> 注意:`document.querySelector` 和 `document.querySelectorAll` 性能很**差**。如果想提高性能,尽量使用 `document.getElementById`、`document.getElementsByClassName` 或 `document.getElementsByTagName`
- [1.0](#1.0) <a name='1.0'></a> Query by selector
```js
// jQuery
$('selector');
// Native
document.querySelectorAll('selector');
```
- [1.1](#1.1) <a name='1.1'></a> Query by class
```js
// jQuery
$('.css');
// Native
document.querySelectorAll('.css');
// or
document.getElementsByClassName('css');
```
- [1.2](#1.2) <a name='1.2'></a> Query by id
```js
// jQuery
$('#id');
// Native
document.querySelector('#id');
// or
document.getElementById('id');
```
- [1.3](#1.3) <a name='1.3'></a> Query by attribute
```js
// jQuery
$('a[target=_blank]');
// Native
document.querySelectorAll('a[target=_blank]');
```
- [1.4](#1.4) <a name='1.4'></a> Find sth.
+ Find nodes
```js
// jQuery
$el.find('li');
// Native
el.querySelectorAll('li');
```
+ Find body
```js
// jQuery
$('body');
// Native
document.body;
```
+ Find Attribute
```js
// jQuery
$el.attr('foo');
// Native
e.getAttribute('foo');
```
+ Find data attribute
```js
// jQuery
$el.data('foo');
// Native
// using getAttribute
el.getAttribute('data-foo');
// you can also use `dataset` if only need to support IE 11+
el.dataset['foo'];
```
- [1.5](#1.5) <a name='1.5'></a> Sibling/Previous/Next Elements
+ Sibling elements
```js
// jQuery
$el.siblings();
// Native
[].filter.call(el.parentNode.children, function(child) {
return child !== el;
});
```
+ Previous elements
```js
// jQuery
$el.prev();
// Native
el.previousElementSibling;
```
+ Next elements
```js
// next
$el.next();
el.nextElementSibling;
```
- [1.6](#1.6) <a name='1.6'></a> Closest
Closest 获得匹配选择器的第一个祖先元素,从当前元素开始沿 DOM 树向上。
```js
// jQuery
$el.closest(queryString);
// Native
function closest(el, selector) {
const matchesSelector = el.matches || el.webkitMatchesSelector || el.mozMatchesSelector || el.msMatchesSelector;
while (el) {
if (matchesSelector.call(el, selector)) {
return el;
} else {
el = el.parentElement;
}
}
return null;
}
```
- [1.7](#1.7) <a name='1.7'></a> Parents Until
获取当前每一个匹配元素集的祖先,不包括匹配元素的本身。
```js
// jQuery
$el.parentsUntil(selector, filter);
// Native
function parentsUntil(el, selector, filter) {
const result = [];
const matchesSelector = el.matches || el.webkitMatchesSelector || el.mozMatchesSelector || el.msMatchesSelector;
// match start from parent
el = el.parentElement;
while (el && !matchesSelector.call(el, selector)) {
if (!filter) {
result.push(el);
} else {
if (matchesSelector.call(el, filter)) {
result.push(el);
}
}
el = el.parentElement;
}
return result;
}
```
- [1.8](#1.8) <a name='1.8'></a> Form
+ Input/Textarea
```js
// jQuery
$('#my-input').val();
// Native
document.querySelector('#my-input').value;
```
+ Get index of e.currentTarget between `.radio`
```js
// jQuery
$(e.currentTarget).index('.radio');
// Native
[].indexOf.call(document.querySelectAll('.radio'), e.currentTarget);
```
- [1.9](#1.9) <a name='1.9'></a> Iframe Contents
jQuery 对象的 iframe `contents()` 返回的是 iframe 内的 `document`
+ Iframe contents
```js
// jQuery
$iframe.contents();
// Native
iframe.contentDocument;
```
+ Iframe Query
```js
// jQuery
$iframe.contents().find('.css');
// Native
iframe.contentDocument.querySelectorAll('.css');
```
**[⬆ 回到顶部](#目录)**
## CSS & Style
- [2.1](#2.1) <a name='2.1'></a> CSS
+ Get style
```js
// jQuery
$el.css("color");
// Native
// 注意:此处为了解决当 style 值为 auto 时,返回 auto 的问题
const win = el.ownerDocument.defaultView;
// null 的意思是不返回伪类元素
win.getComputedStyle(el, null).color;
```
+ Set style
```js
// jQuery
$el.css({ color: "#ff0011" });
// Native
el.style.color = '#ff0011';
```
+ Get/Set Styles
注意,如果想一次设置多个 style可以参考 oui-dom-utils 中 [setStyles](https://github.com/oneuijs/oui-dom-utils/blob/master/src/index.js#L194) 方法
+ Add class
```js
// jQuery
$el.addClass(className);
// Native
el.classList.add(className);
```
+ Remove class
```js
// jQuery
$el.removeClass(className);
// Native
el.classList.remove(className);
```
+ has class
```js
// jQuery
$el.hasClass(className);
// Native
el.classList.contains(className);
```
+ Toggle class
```js
// jQuery
$el.toggleClass(className);
// Native
el.classList.toggle(className);
```
- [2.2](#2.2) <a name='2.2'></a> Width & Height
Width 与 Height 获取方法相同,下面以 Height 为例:
+ Window height
```js
// jQuery
$(window).height();
// Native
// 不含 scrollbar与 jQuery 行为一致
window.document.documentElement.clientHeight;
// 含 scrollbar
window.innerHeight;
```
+ Document height
```js
// jQuery
$(document).height();
// Native
document.documentElement.scrollHeight;
```
+ Element height
```js
// jQuery
$el.height();
// Native
// 与 jQuery 一致(一直为 content 区域的高度)
function getHeight(el) {
const styles = this.getComputedStyles(el);
const height = el.offsetHeight;
const borderTopWidth = parseFloat(styles.borderTopWidth);
const borderBottomWidth = parseFloat(styles.borderBottomWidth);
const paddingTop = parseFloat(styles.paddingTop);
const paddingBottom = parseFloat(styles.paddingBottom);
return height - borderBottomWidth - borderTopWidth - paddingTop - paddingBottom;
}
// 精确到整数border-box 时为 height 值content-box 时为 height + padding + border 值)
el.clientHeight;
// 精确到小数border-box 时为 height 值content-box 时为 height + padding + border 值)
el.getBoundingClientRect().height;
```
+ Iframe height
$iframe .contents() 方法返回 iframe 的 contentDocument
```js
// jQuery
$('iframe').contents().height();
// Native
iframe.contentDocument.documentElement.scrollHeight;
```
- [2.3](#2.3) <a name='2.3'></a> Position & Offset
+ Position
```js
// jQuery
$el.position();
// Native
{ left: el.offsetLeft, top: el.offsetTop }
```
+ Offset
```js
// jQuery
$el.offset();
// Native
function getOffset (el) {
const box = el.getBoundingClientRect();
return {
top: box.top + window.pageYOffset - document.documentElement.clientTop,
left: box.left + window.pageXOffset - document.documentElement.clientLeft
}
}
```
- [2.4](#2.4) <a name='2.4'></a> Scroll Top
```js
// jQuery
$(window).scrollTop();
// Native
(document.documentElement && document.documentElement.scrollTop) || document.body.scrollTop;
```
**[⬆ 回到顶部](#目录)**
## DOM Manipulation
- [3.1](#3.1) <a name='3.1'></a> Remove
```js
// jQuery
$el.remove();
// Native
el.parentNode.removeChild(el);
```
- [3.2](#3.2) <a name='3.2'></a> Text
+ Get text
```js
// jQuery
$el.text();
// Native
el.textContent;
```
+ Set text
```js
// jQuery
$el.text(string);
// Native
el.textContent = string;
```
- [3.3](#3.3) <a name='3.3'></a> HTML
+ Get HTML
```js
// jQuery
$el.html();
// Native
el.innerHTML;
```
+ Set HTML
```js
// jQuery
$el.html(htmlString);
// Native
el.innerHTML = htmlString;
```
- [3.4](#3.4) <a name='3.4'></a> Append
Append 插入到子节点的末尾
```js
// jQuery
$el.append("<div id='container'>hello</div>");
// Native
let newEl = document.createElement('div');
newEl.setAttribute('id', 'container');
newEl.innerHTML = 'hello';
el.appendChild(newEl);
```
- [3.5](#3.5) <a name='3.5'></a> Prepend
```js
// jQuery
$el.prepend("<div id='container'>hello</div>");
// Native
let newEl = document.createElement('div');
newEl.setAttribute('id', 'container');
newEl.innerHTML = 'hello';
el.insertBefore(newEl, el.firstChild);
```
- [3.6](#3.6) <a name='3.6'></a> insertBefore
在选中元素前插入新节点
```js
// jQuery
$newEl.insertBefore(queryString);
// Native
const target = document.querySelector(queryString);
target.parentNode.insertBefore(newEl, target);
```
- [3.7](#3.7) <a name='3.7'></a> insertAfter
在选中元素后插入新节点
```js
// jQuery
$newEl.insertAfter(queryString);
// Native
const target = document.querySelector(queryString);
target.parentNode.insertBefore(newEl, target.nextSibling);
```
**[⬆ 回到顶部](#目录)**
## Ajax
用 [fetch](https://github.com/camsong/fetch-ie8) 和 [fetch-jsonp](https://github.com/camsong/fetch-jsonp) 替代
**[⬆ 回到顶部](#目录)**
## Events
完整地替代命名空间和事件代理,链接到 https://github.com/oneuijs/oui-dom-events
- [5.1](#5.1) <a name='5.1'></a> Bind an event with on
```js
// jQuery
$el.on(eventName, eventHandler);
// Native
el.addEventListener(eventName, eventHandler);
```
- [5.2](#5.2) <a name='5.2'></a> Unbind an event with off
```js
// jQuery
$el.off(eventName, eventHandler);
// Native
el.removeEventListener(eventName, eventHandler);
```
- [5.3](#5.3) <a name='5.3'></a> Trigger
```js
// jQuery
$(el).trigger('custom-event', {key1: 'data'});
// Native
if (window.CustomEvent) {
const event = new CustomEvent('custom-event', {detail: {key1: 'data'}});
} else {
const event = document.createEvent('CustomEvent');
event.initCustomEvent('custom-event', true, true, {key1: 'data'});
}
el.dispatchEvent(event);
```
**[⬆ 回到顶部](#目录)**
## Utilities
- [6.1](#6.1) <a name='6.1'></a> isArray
```js
// jQuery
$.isArray(range);
// Native
Array.isArray(range);
```
- [6.2](#6.2) <a name='6.2'></a> Trim
```js
// jQuery
$.trim(string);
// Native
string.trim();
```
- [6.3](#6.3) <a name='6.3'></a> Object Assign
继承,使用 object.assign polyfill https://github.com/ljharb/object.assign
```js
// jQuery
$.extend({}, defaultOpts, opts);
// Native
Object.assign({}, defaultOpts, opts);
```
- [6.4](#6.4) <a name='6.4'></a> Contains
```js
// jQuery
$.contains(el, child);
// Native
el !== child && el.contains(child);
```
**[⬆ 回到顶部](#目录)**
## Alternatives
* [你可能不需要 jQuery (You Might Not Need jQuery)](http://youmightnotneedjquery.com/) - 如何使用原生 JavaScript 实现通用事件元素ajax 等用法。
* [npm-dom](http://github.com/npm-dom) 以及 [webmodules](http://github.com/webmodules) - 在 NPM 上提供独立 DOM 模块的组织
## Translations
* [한국어](./README.ko-KR.md)
* [简体中文](./README.zh-CN.md)
* [Bahasa Melayu](./README-my.md)
* [Bahasa Indonesia](./README-id.md)
* [Português(PT-BR)](./README.pt-BR.md)
* [Tiếng Việt Nam](./README-vi.md)
* [Español](./README-es.md)
* [Русский](./README-ru.md)
* [Türkçe](./README-tr.md)
* [Italian](./README-it.md)
## Browser Support
![Chrome](https://raw.github.com/alrra/browser-logos/master/chrome/chrome_48x48.png) | ![Firefox](https://raw.github.com/alrra/browser-logos/master/firefox/firefox_48x48.png) | ![IE](https://raw.github.com/alrra/browser-logos/master/internet-explorer/internet-explorer_48x48.png) | ![Opera](https://raw.github.com/alrra/browser-logos/master/opera/opera_48x48.png) | ![Safari](https://raw.github.com/alrra/browser-logos/master/safari/safari_48x48.png)
--- | --- | --- | --- | --- |
Latest ✔ | Latest ✔ | 10+ ✔ | Latest ✔ | 6.1+ ✔ |
# License
MIT

View File

@ -0,0 +1 @@
gitdir: ../.git/modules/You-Dont-Need-jQuery

View File

@ -0,0 +1,92 @@
// Karma configuration
// Generated on Sun Nov 22 2015 22:10:47 GMT+0800 (CST)
require('babel-core/register');
module.exports = function(config) {
config.set({
// base path that will be used to resolve all patterns (eg. files, exclude)
basePath: '.',
// frameworks to use
// available frameworks: https://npmjs.org/browse/keyword/karma-adapter
frameworks: ['mocha'],
// list of files / patterns to load in the browser
files: [
'./test/**/*.spec.js'
],
// list of files to exclude
exclude: [
],
// preprocess matching files before serving them to the browser
// available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor
preprocessors: {
'test/**/*.spec.js': ['webpack', 'sourcemap']
},
// test results reporter to use
// possible values: 'dots', 'progress'
// available reporters: https://npmjs.org/browse/keyword/karma-reporter
reporters: ['progress'],
coverageReporter: {
reporters: [
{type: 'text'},
{type: 'html', dir: 'coverage'},
]
},
webpackMiddleware: {
stats: 'minimal'
},
webpack: {
cache: true,
devtool: 'inline-source-map',
module: {
loaders: [{
test: /\.jsx?$/,
loader: 'babel-loader',
exclude: /node_modules/
}],
postLoaders: [{
test: /\.js/,
exclude: /(test|node_modules)/,
loader: 'istanbul-instrumenter'
}],
},
resolve: {
extensions: ['', '.js', '.jsx']
}
},
// web server port
port: 9876,
// enable / disable colors in the output (reporters and logs)
colors: true,
// level of logging
// possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG
logLevel: config.LOG_INFO,
// enable / disable watching file and executing tests whenever any file changes
autoWatch: true,
// start these browsers
// available browser launchers: https://npmjs.org/browse/keyword/karma-launcher
browsers: ['Firefox'],
// Continuous Integration mode
// if true, Karma captures browsers, runs the tests and exits
// singleRun: false,
// Concurrency level
// how many browser should be started simultanous
// concurrency: Infinity,
// plugins: ['karma-phantomjs-launcher', 'karma-sourcemap-loader', 'karma-webpack']
})
}

View File

@ -0,0 +1,53 @@
{
"name": "You-Dont-Need-jQuery",
"version": "1.0.0",
"description": "Examples of how to do query, style, dom, ajax, event etc like jQuery with plain javascript.",
"scripts": {
"test": "karma start --single-run",
"tdd": "karma start --auto-watch --no-single-run",
"test-cov": "karma start --auto-watch --single-run --reporters progress,coverage",
"lint": "eslint src test"
},
"dependencies": {},
"devDependencies": {
"babel-cli": "^6.2.0",
"babel-core": "^6.1.21",
"babel-eslint": "^4.1.5",
"babel-loader": "^6.2.0",
"babel-preset-es2015": "^6.1.18",
"babel-preset-stage-0": "^6.1.18",
"chai": "^3.4.1",
"eslint": "^1.9.0",
"eslint-config-airbnb": "^1.0.0",
"eslint-plugin-react": "^3.10.0",
"isparta": "^4.0.0",
"istanbul-instrumenter-loader": "^0.1.3",
"jquery": "^2.1.4",
"karma": "^0.13.15",
"karma-coverage": "^0.5.3",
"karma-firefox-launcher": "^0.1.7",
"karma-mocha": "^0.2.1",
"karma-sourcemap-loader": "^0.3.6",
"karma-webpack": "^1.7.0",
"mocha": "^2.3.4",
"webpack": "^1.12.9"
},
"repository": {
"type": "git",
"url": "https://github.com/oneuijs/You-Dont-Need-jQuery.git"
},
"keywords": [
"convertion guide",
"jQuery",
"es6",
"es2015",
"babel",
"OneUI Group"
],
"author": "OneUI Group",
"license": "MIT",
"bugs": {
"url": "https://github.com/oneuijs/You-Dont-Need-jQuery/issues"
},
"homepage": "https://github.com/oneuijs/You-Dont-Need-jQuery"
}

View File

@ -0,0 +1,13 @@
# Test cases for all the tips
## Usage
run all tests once
```
npm run test
```
run tests on TDD(Test Driven Development) mode
```
npm run tdd
```

View File

@ -0,0 +1 @@
// test for CSS related

View File

@ -0,0 +1 @@
// test for CSS and style related

View File

@ -0,0 +1,71 @@
// tests for Query Selector related
import { expect } from 'chai';
import $ from 'jquery';
describe('query selector', () => {
describe('basic', () => {
beforeEach(() => {
document.body.innerHTML = `
<ul id='query-selector-test1' class='list'>
<li data-role='red' class='item-i red item'>I</li>
<li data-role='blue' class='item-ii blue item'>II</li>
<li>III</li>
<li>
<ul id='nested-ul'>
<li data-role='red' class='item-i-i red item'>III.I</li>
<li data-role='blue' class='item-i-ii blue item'>III.II</li>
</ul>
</li>
</ul>
`;
});
afterEach(() => {
const el = document.querySelector('#query-selector-test1');
el.parentNode.removeChild(el);
});
it('1.0 Query by selector', () => {
const $els = $('li.item[data-role="red"]');
const els = document.querySelectorAll('li.item[data-role="red"]');
expect($els.length).to.equal(2);
[].forEach.call($els, function($el, i) {
expect($el).to.equal(els[i]);
});
});
it('1.1 Query by class', () => {
const $els = $('.item');
const els = document.getElementsByClassName('item');
[].forEach.call($els, function($el, i) {
expect($el).to.equal(els[i]);
});
});
it('1.2 Query by id', () => {
expect($('#nested-ul')[0]).to.equal(document.getElementById('nested-ul'));
});
it('1.3 Query by attribute', () => {
const $els = $('[data-role="blue"]');
const els = document.querySelectorAll('[data-role="blue"]');
expect($els.length).to.equal(2);
[].forEach.call($els, function($el, i) {
expect($el).to.equal(els[i]);
});
});
it('1.4 Query in descendents', () => {
const $els = $('#query-selector-test1').find('.item');
const els = document.getElementById('query-selector-test1').querySelectorAll('.item');
expect($els.length).to.equal(4);
[].forEach.call($els, function($el, i) {
expect($el).to.equal(els[i]);
});
});
});
});

View File

@ -0,0 +1 @@
// test for Utilities related

View File

@ -0,0 +1,9 @@
submodules
# Please enter the commit message for your changes. Lines starting
# with '#' will be ignored, and an empty message aborts the commit.
# On branch master
# Changes to be committed:
# new file: .gitmodules
# new file: You-Dont-Need-jQuery
# new file: jstips
#

View File

@ -0,0 +1 @@
ref: refs/heads/master

View File

@ -0,0 +1,11 @@
[core]
repositoryformatversion = 0
filemode = true
bare = false
logallrefupdates = true
ignorecase = true
precomposeunicode = true
[submodule "jstips"]
url = https://github.com/loverajoel/jstips
[submodule "You-Dont-Need-jQuery"]
url = https://github.com/oneuijs/You-Dont-Need-jQuery

View File

@ -0,0 +1 @@
Unnamed repository; edit this file 'description' to name the repository.

View File

@ -0,0 +1,15 @@
#!/bin/sh
#
# An example hook script to check the commit log message taken by
# applypatch from an e-mail message.
#
# The hook should exit with non-zero status after issuing an
# appropriate message if it wants to stop the commit. The hook is
# allowed to edit the commit message file.
#
# To enable this hook, rename this file to "applypatch-msg".
. git-sh-setup
commitmsg="$(git rev-parse --git-path hooks/commit-msg)"
test -x "$commitmsg" && exec "$commitmsg" ${1+"$@"}
:

View File

@ -0,0 +1,24 @@
#!/bin/sh
#
# An example hook script to check the commit log message.
# Called by "git commit" with one argument, the name of the file
# that has the commit message. The hook should exit with non-zero
# status after issuing an appropriate message if it wants to stop the
# commit. The hook is allowed to edit the commit message file.
#
# To enable this hook, rename this file to "commit-msg".
# Uncomment the below to add a Signed-off-by line to the message.
# Doing this in a hook is a bad idea in general, but the prepare-commit-msg
# hook is more suited to it.
#
# SOB=$(git var GIT_AUTHOR_IDENT | sed -n 's/^\(.*>\).*$/Signed-off-by: \1/p')
# grep -qs "^$SOB" "$1" || echo "$SOB" >> "$1"
# This example catches duplicate Signed-off-by lines.
test "" = "$(grep '^Signed-off-by: ' "$1" |
sort | uniq -c | sed -e '/^[ ]*1[ ]/d')" || {
echo >&2 Duplicate Signed-off-by lines.
exit 1
}

View File

@ -0,0 +1,8 @@
#!/bin/sh
#
# An example hook script to prepare a packed repository for use over
# dumb transports.
#
# To enable this hook, rename this file to "post-update".
exec git update-server-info

View File

@ -0,0 +1,14 @@
#!/bin/sh
#
# An example hook script to verify what is about to be committed
# by applypatch from an e-mail message.
#
# The hook should exit with non-zero status after issuing an
# appropriate message if it wants to stop the commit.
#
# To enable this hook, rename this file to "pre-applypatch".
. git-sh-setup
precommit="$(git rev-parse --git-path hooks/pre-commit)"
test -x "$precommit" && exec "$precommit" ${1+"$@"}
:

View File

@ -0,0 +1,49 @@
#!/bin/sh
#
# An example hook script to verify what is about to be committed.
# Called by "git commit" with no arguments. The hook should
# exit with non-zero status after issuing an appropriate message if
# it wants to stop the commit.
#
# To enable this hook, rename this file to "pre-commit".
if git rev-parse --verify HEAD >/dev/null 2>&1
then
against=HEAD
else
# Initial commit: diff against an empty tree object
against=4b825dc642cb6eb9a060e54bf8d69288fbee4904
fi
# If you want to allow non-ASCII filenames set this variable to true.
allownonascii=$(git config --bool hooks.allownonascii)
# Redirect output to stderr.
exec 1>&2
# Cross platform projects tend to avoid non-ASCII filenames; prevent
# them from being added to the repository. We exploit the fact that the
# printable range starts at the space character and ends with tilde.
if [ "$allownonascii" != "true" ] &&
# Note that the use of brackets around a tr range is ok here, (it's
# even required, for portability to Solaris 10's /usr/bin/tr), since
# the square bracket bytes happen to fall in the designated range.
test $(git diff --cached --name-only --diff-filter=A -z $against |
LC_ALL=C tr -d '[ -~]\0' | wc -c) != 0
then
cat <<\EOF
Error: Attempt to add a non-ASCII file name.
This can cause problems if you want to work with people on other platforms.
To be portable it is advisable to rename the file.
If you know what you are doing you can disable this check using:
git config hooks.allownonascii true
EOF
exit 1
fi
# If there are whitespace errors, print the offending file names and fail.
exec git diff-index --check --cached $against --

View File

@ -0,0 +1,53 @@
#!/bin/sh
# An example hook script to verify what is about to be pushed. Called by "git
# push" after it has checked the remote status, but before anything has been
# pushed. If this script exits with a non-zero status nothing will be pushed.
#
# This hook is called with the following parameters:
#
# $1 -- Name of the remote to which the push is being done
# $2 -- URL to which the push is being done
#
# If pushing without using a named remote those arguments will be equal.
#
# Information about the commits which are being pushed is supplied as lines to
# the standard input in the form:
#
# <local ref> <local sha1> <remote ref> <remote sha1>
#
# This sample shows how to prevent push of commits where the log message starts
# with "WIP" (work in progress).
remote="$1"
url="$2"
z40=0000000000000000000000000000000000000000
while read local_ref local_sha remote_ref remote_sha
do
if [ "$local_sha" = $z40 ]
then
# Handle delete
:
else
if [ "$remote_sha" = $z40 ]
then
# New branch, examine all commits
range="$local_sha"
else
# Update to existing branch, examine new commits
range="$remote_sha..$local_sha"
fi
# Check for WIP commit
commit=`git rev-list -n 1 --grep '^WIP' "$range"`
if [ -n "$commit" ]
then
echo >&2 "Found WIP commit in $local_ref, not pushing"
exit 1
fi
fi
done
exit 0

View File

@ -0,0 +1,169 @@
#!/bin/sh
#
# Copyright (c) 2006, 2008 Junio C Hamano
#
# The "pre-rebase" hook is run just before "git rebase" starts doing
# its job, and can prevent the command from running by exiting with
# non-zero status.
#
# The hook is called with the following parameters:
#
# $1 -- the upstream the series was forked from.
# $2 -- the branch being rebased (or empty when rebasing the current branch).
#
# This sample shows how to prevent topic branches that are already
# merged to 'next' branch from getting rebased, because allowing it
# would result in rebasing already published history.
publish=next
basebranch="$1"
if test "$#" = 2
then
topic="refs/heads/$2"
else
topic=`git symbolic-ref HEAD` ||
exit 0 ;# we do not interrupt rebasing detached HEAD
fi
case "$topic" in
refs/heads/??/*)
;;
*)
exit 0 ;# we do not interrupt others.
;;
esac
# Now we are dealing with a topic branch being rebased
# on top of master. Is it OK to rebase it?
# Does the topic really exist?
git show-ref -q "$topic" || {
echo >&2 "No such branch $topic"
exit 1
}
# Is topic fully merged to master?
not_in_master=`git rev-list --pretty=oneline ^master "$topic"`
if test -z "$not_in_master"
then
echo >&2 "$topic is fully merged to master; better remove it."
exit 1 ;# we could allow it, but there is no point.
fi
# Is topic ever merged to next? If so you should not be rebasing it.
only_next_1=`git rev-list ^master "^$topic" ${publish} | sort`
only_next_2=`git rev-list ^master ${publish} | sort`
if test "$only_next_1" = "$only_next_2"
then
not_in_topic=`git rev-list "^$topic" master`
if test -z "$not_in_topic"
then
echo >&2 "$topic is already up-to-date with master"
exit 1 ;# we could allow it, but there is no point.
else
exit 0
fi
else
not_in_next=`git rev-list --pretty=oneline ^${publish} "$topic"`
/usr/bin/perl -e '
my $topic = $ARGV[0];
my $msg = "* $topic has commits already merged to public branch:\n";
my (%not_in_next) = map {
/^([0-9a-f]+) /;
($1 => 1);
} split(/\n/, $ARGV[1]);
for my $elem (map {
/^([0-9a-f]+) (.*)$/;
[$1 => $2];
} split(/\n/, $ARGV[2])) {
if (!exists $not_in_next{$elem->[0]}) {
if ($msg) {
print STDERR $msg;
undef $msg;
}
print STDERR " $elem->[1]\n";
}
}
' "$topic" "$not_in_next" "$not_in_master"
exit 1
fi
exit 0
################################################################
This sample hook safeguards topic branches that have been
published from being rewound.
The workflow assumed here is:
* Once a topic branch forks from "master", "master" is never
merged into it again (either directly or indirectly).
* Once a topic branch is fully cooked and merged into "master",
it is deleted. If you need to build on top of it to correct
earlier mistakes, a new topic branch is created by forking at
the tip of the "master". This is not strictly necessary, but
it makes it easier to keep your history simple.
* Whenever you need to test or publish your changes to topic
branches, merge them into "next" branch.
The script, being an example, hardcodes the publish branch name
to be "next", but it is trivial to make it configurable via
$GIT_DIR/config mechanism.
With this workflow, you would want to know:
(1) ... if a topic branch has ever been merged to "next". Young
topic branches can have stupid mistakes you would rather
clean up before publishing, and things that have not been
merged into other branches can be easily rebased without
affecting other people. But once it is published, you would
not want to rewind it.
(2) ... if a topic branch has been fully merged to "master".
Then you can delete it. More importantly, you should not
build on top of it -- other people may already want to
change things related to the topic as patches against your
"master", so if you need further changes, it is better to
fork the topic (perhaps with the same name) afresh from the
tip of "master".
Let's look at this example:
o---o---o---o---o---o---o---o---o---o "next"
/ / / /
/ a---a---b A / /
/ / / /
/ / c---c---c---c B /
/ / / \ /
/ / / b---b C \ /
/ / / / \ /
---o---o---o---o---o---o---o---o---o---o---o "master"
A, B and C are topic branches.
* A has one fix since it was merged up to "next".
* B has finished. It has been fully merged up to "master" and "next",
and is ready to be deleted.
* C has not merged to "next" at all.
We would want to allow C to be rebased, refuse A, and encourage
B to be deleted.
To compute (1):
git rev-list ^master ^topic next
git rev-list ^master next
if these match, topic has not merged in next at all.
To compute (2):
git rev-list master..topic
if this is empty, it is fully merged to "master".

View File

@ -0,0 +1,36 @@
#!/bin/sh
#
# An example hook script to prepare the commit log message.
# Called by "git commit" with the name of the file that has the
# commit message, followed by the description of the commit
# message's source. The hook's purpose is to edit the commit
# message file. If the hook fails with a non-zero status,
# the commit is aborted.
#
# To enable this hook, rename this file to "prepare-commit-msg".
# This hook includes three examples. The first comments out the
# "Conflicts:" part of a merge commit.
#
# The second includes the output of "git diff --name-status -r"
# into the message, just before the "git status" output. It is
# commented because it doesn't cope with --amend or with squashed
# commits.
#
# The third example adds a Signed-off-by line to the message, that can
# still be edited. This is rarely a good idea.
case "$2,$3" in
merge,)
/usr/bin/perl -i.bak -ne 's/^/# /, s/^# #/#/ if /^Conflicts/ .. /#/; print' "$1" ;;
# ,|template,)
# /usr/bin/perl -i.bak -pe '
# print "\n" . `git diff --cached --name-status -r`
# if /^#/ && $first++ == 0' "$1" ;;
*) ;;
esac
# SOB=$(git var GIT_AUTHOR_IDENT | sed -n 's/^\(.*>\).*$/Signed-off-by: \1/p')
# grep -qs "^$SOB" "$1" || echo "$SOB" >> "$1"

View File

@ -0,0 +1,128 @@
#!/bin/sh
#
# An example hook script to blocks unannotated tags from entering.
# Called by "git receive-pack" with arguments: refname sha1-old sha1-new
#
# To enable this hook, rename this file to "update".
#
# Config
# ------
# hooks.allowunannotated
# This boolean sets whether unannotated tags will be allowed into the
# repository. By default they won't be.
# hooks.allowdeletetag
# This boolean sets whether deleting tags will be allowed in the
# repository. By default they won't be.
# hooks.allowmodifytag
# This boolean sets whether a tag may be modified after creation. By default
# it won't be.
# hooks.allowdeletebranch
# This boolean sets whether deleting branches will be allowed in the
# repository. By default they won't be.
# hooks.denycreatebranch
# This boolean sets whether remotely creating branches will be denied
# in the repository. By default this is allowed.
#
# --- Command line
refname="$1"
oldrev="$2"
newrev="$3"
# --- Safety check
if [ -z "$GIT_DIR" ]; then
echo "Don't run this script from the command line." >&2
echo " (if you want, you could supply GIT_DIR then run" >&2
echo " $0 <ref> <oldrev> <newrev>)" >&2
exit 1
fi
if [ -z "$refname" -o -z "$oldrev" -o -z "$newrev" ]; then
echo "usage: $0 <ref> <oldrev> <newrev>" >&2
exit 1
fi
# --- Config
allowunannotated=$(git config --bool hooks.allowunannotated)
allowdeletebranch=$(git config --bool hooks.allowdeletebranch)
denycreatebranch=$(git config --bool hooks.denycreatebranch)
allowdeletetag=$(git config --bool hooks.allowdeletetag)
allowmodifytag=$(git config --bool hooks.allowmodifytag)
# check for no description
projectdesc=$(sed -e '1q' "$GIT_DIR/description")
case "$projectdesc" in
"Unnamed repository"* | "")
echo "*** Project description file hasn't been set" >&2
exit 1
;;
esac
# --- Check types
# if $newrev is 0000...0000, it's a commit to delete a ref.
zero="0000000000000000000000000000000000000000"
if [ "$newrev" = "$zero" ]; then
newrev_type=delete
else
newrev_type=$(git cat-file -t $newrev)
fi
case "$refname","$newrev_type" in
refs/tags/*,commit)
# un-annotated tag
short_refname=${refname##refs/tags/}
if [ "$allowunannotated" != "true" ]; then
echo "*** The un-annotated tag, $short_refname, is not allowed in this repository" >&2
echo "*** Use 'git tag [ -a | -s ]' for tags you want to propagate." >&2
exit 1
fi
;;
refs/tags/*,delete)
# delete tag
if [ "$allowdeletetag" != "true" ]; then
echo "*** Deleting a tag is not allowed in this repository" >&2
exit 1
fi
;;
refs/tags/*,tag)
# annotated tag
if [ "$allowmodifytag" != "true" ] && git rev-parse $refname > /dev/null 2>&1
then
echo "*** Tag '$refname' already exists." >&2
echo "*** Modifying a tag is not allowed in this repository." >&2
exit 1
fi
;;
refs/heads/*,commit)
# branch
if [ "$oldrev" = "$zero" -a "$denycreatebranch" = "true" ]; then
echo "*** Creating a branch is not allowed in this repository" >&2
exit 1
fi
;;
refs/heads/*,delete)
# delete branch
if [ "$allowdeletebranch" != "true" ]; then
echo "*** Deleting a branch is not allowed in this repository" >&2
exit 1
fi
;;
refs/remotes/*,commit)
# tracking branch
;;
refs/remotes/*,delete)
# delete tracking branch
if [ "$allowdeletebranch" != "true" ]; then
echo "*** Deleting a tracking branch is not allowed in this repository" >&2
exit 1
fi
;;
*)
# Anything else (is there anything else?)
echo "*** Update hook: unknown type of update to ref $refname of type $newrev_type" >&2
exit 1
;;
esac
# --- Finished
exit 0

Binary file not shown.

View File

@ -0,0 +1,6 @@
# git ls-files --others --exclude-from=.git/info/exclude
# Lines that start with '#' are comments.
# For a project mostly in C, the following would be a good set of
# exclude patterns (uncomment them if you want to use them):
# *.[oa]
# *~

View File

@ -0,0 +1,2 @@
0000000000000000000000000000000000000000 d3e073baf592c56614c68ead9e2cd0a3880140cd joshaber <joshaber@gmail.com> 1452185922 -0500 commit (initial): first
d3e073baf592c56614c68ead9e2cd0a3880140cd d2b0ad9cbc6f6c4372e8956e5cc5af771b2342e5 joshaber <joshaber@gmail.com> 1452186239 -0500 commit: submodules

View File

@ -0,0 +1,2 @@
0000000000000000000000000000000000000000 d3e073baf592c56614c68ead9e2cd0a3880140cd joshaber <joshaber@gmail.com> 1452185922 -0500 commit (initial): first
d3e073baf592c56614c68ead9e2cd0a3880140cd d2b0ad9cbc6f6c4372e8956e5cc5af771b2342e5 joshaber <joshaber@gmail.com> 1452186239 -0500 commit: submodules

View File

@ -0,0 +1 @@
ref: refs/heads/master

View File

@ -0,0 +1 @@
2e9bbc77d60f20eb462ead5b2ac7405b62b9b90a

View File

@ -0,0 +1,14 @@
[core]
repositoryformatversion = 0
filemode = true
bare = false
logallrefupdates = true
worktree = ../../../You-Dont-Need-jQuery
ignorecase = true
precomposeunicode = true
[remote "origin"]
url = https://github.com/oneuijs/You-Dont-Need-jQuery
fetch = +refs/heads/*:refs/remotes/origin/*
[branch "master"]
remote = origin
merge = refs/heads/master

View File

@ -0,0 +1 @@
Unnamed repository; edit this file 'description' to name the repository.

View File

@ -0,0 +1,15 @@
#!/bin/sh
#
# An example hook script to check the commit log message taken by
# applypatch from an e-mail message.
#
# The hook should exit with non-zero status after issuing an
# appropriate message if it wants to stop the commit. The hook is
# allowed to edit the commit message file.
#
# To enable this hook, rename this file to "applypatch-msg".
. git-sh-setup
commitmsg="$(git rev-parse --git-path hooks/commit-msg)"
test -x "$commitmsg" && exec "$commitmsg" ${1+"$@"}
:

View File

@ -0,0 +1,24 @@
#!/bin/sh
#
# An example hook script to check the commit log message.
# Called by "git commit" with one argument, the name of the file
# that has the commit message. The hook should exit with non-zero
# status after issuing an appropriate message if it wants to stop the
# commit. The hook is allowed to edit the commit message file.
#
# To enable this hook, rename this file to "commit-msg".
# Uncomment the below to add a Signed-off-by line to the message.
# Doing this in a hook is a bad idea in general, but the prepare-commit-msg
# hook is more suited to it.
#
# SOB=$(git var GIT_AUTHOR_IDENT | sed -n 's/^\(.*>\).*$/Signed-off-by: \1/p')
# grep -qs "^$SOB" "$1" || echo "$SOB" >> "$1"
# This example catches duplicate Signed-off-by lines.
test "" = "$(grep '^Signed-off-by: ' "$1" |
sort | uniq -c | sed -e '/^[ ]*1[ ]/d')" || {
echo >&2 Duplicate Signed-off-by lines.
exit 1
}

View File

@ -0,0 +1,8 @@
#!/bin/sh
#
# An example hook script to prepare a packed repository for use over
# dumb transports.
#
# To enable this hook, rename this file to "post-update".
exec git update-server-info

View File

@ -0,0 +1,14 @@
#!/bin/sh
#
# An example hook script to verify what is about to be committed
# by applypatch from an e-mail message.
#
# The hook should exit with non-zero status after issuing an
# appropriate message if it wants to stop the commit.
#
# To enable this hook, rename this file to "pre-applypatch".
. git-sh-setup
precommit="$(git rev-parse --git-path hooks/pre-commit)"
test -x "$precommit" && exec "$precommit" ${1+"$@"}
:

View File

@ -0,0 +1,49 @@
#!/bin/sh
#
# An example hook script to verify what is about to be committed.
# Called by "git commit" with no arguments. The hook should
# exit with non-zero status after issuing an appropriate message if
# it wants to stop the commit.
#
# To enable this hook, rename this file to "pre-commit".
if git rev-parse --verify HEAD >/dev/null 2>&1
then
against=HEAD
else
# Initial commit: diff against an empty tree object
against=4b825dc642cb6eb9a060e54bf8d69288fbee4904
fi
# If you want to allow non-ASCII filenames set this variable to true.
allownonascii=$(git config --bool hooks.allownonascii)
# Redirect output to stderr.
exec 1>&2
# Cross platform projects tend to avoid non-ASCII filenames; prevent
# them from being added to the repository. We exploit the fact that the
# printable range starts at the space character and ends with tilde.
if [ "$allownonascii" != "true" ] &&
# Note that the use of brackets around a tr range is ok here, (it's
# even required, for portability to Solaris 10's /usr/bin/tr), since
# the square bracket bytes happen to fall in the designated range.
test $(git diff --cached --name-only --diff-filter=A -z $against |
LC_ALL=C tr -d '[ -~]\0' | wc -c) != 0
then
cat <<\EOF
Error: Attempt to add a non-ASCII file name.
This can cause problems if you want to work with people on other platforms.
To be portable it is advisable to rename the file.
If you know what you are doing you can disable this check using:
git config hooks.allownonascii true
EOF
exit 1
fi
# If there are whitespace errors, print the offending file names and fail.
exec git diff-index --check --cached $against --

View File

@ -0,0 +1,53 @@
#!/bin/sh
# An example hook script to verify what is about to be pushed. Called by "git
# push" after it has checked the remote status, but before anything has been
# pushed. If this script exits with a non-zero status nothing will be pushed.
#
# This hook is called with the following parameters:
#
# $1 -- Name of the remote to which the push is being done
# $2 -- URL to which the push is being done
#
# If pushing without using a named remote those arguments will be equal.
#
# Information about the commits which are being pushed is supplied as lines to
# the standard input in the form:
#
# <local ref> <local sha1> <remote ref> <remote sha1>
#
# This sample shows how to prevent push of commits where the log message starts
# with "WIP" (work in progress).
remote="$1"
url="$2"
z40=0000000000000000000000000000000000000000
while read local_ref local_sha remote_ref remote_sha
do
if [ "$local_sha" = $z40 ]
then
# Handle delete
:
else
if [ "$remote_sha" = $z40 ]
then
# New branch, examine all commits
range="$local_sha"
else
# Update to existing branch, examine new commits
range="$remote_sha..$local_sha"
fi
# Check for WIP commit
commit=`git rev-list -n 1 --grep '^WIP' "$range"`
if [ -n "$commit" ]
then
echo >&2 "Found WIP commit in $local_ref, not pushing"
exit 1
fi
fi
done
exit 0

View File

@ -0,0 +1,169 @@
#!/bin/sh
#
# Copyright (c) 2006, 2008 Junio C Hamano
#
# The "pre-rebase" hook is run just before "git rebase" starts doing
# its job, and can prevent the command from running by exiting with
# non-zero status.
#
# The hook is called with the following parameters:
#
# $1 -- the upstream the series was forked from.
# $2 -- the branch being rebased (or empty when rebasing the current branch).
#
# This sample shows how to prevent topic branches that are already
# merged to 'next' branch from getting rebased, because allowing it
# would result in rebasing already published history.
publish=next
basebranch="$1"
if test "$#" = 2
then
topic="refs/heads/$2"
else
topic=`git symbolic-ref HEAD` ||
exit 0 ;# we do not interrupt rebasing detached HEAD
fi
case "$topic" in
refs/heads/??/*)
;;
*)
exit 0 ;# we do not interrupt others.
;;
esac
# Now we are dealing with a topic branch being rebased
# on top of master. Is it OK to rebase it?
# Does the topic really exist?
git show-ref -q "$topic" || {
echo >&2 "No such branch $topic"
exit 1
}
# Is topic fully merged to master?
not_in_master=`git rev-list --pretty=oneline ^master "$topic"`
if test -z "$not_in_master"
then
echo >&2 "$topic is fully merged to master; better remove it."
exit 1 ;# we could allow it, but there is no point.
fi
# Is topic ever merged to next? If so you should not be rebasing it.
only_next_1=`git rev-list ^master "^$topic" ${publish} | sort`
only_next_2=`git rev-list ^master ${publish} | sort`
if test "$only_next_1" = "$only_next_2"
then
not_in_topic=`git rev-list "^$topic" master`
if test -z "$not_in_topic"
then
echo >&2 "$topic is already up-to-date with master"
exit 1 ;# we could allow it, but there is no point.
else
exit 0
fi
else
not_in_next=`git rev-list --pretty=oneline ^${publish} "$topic"`
/usr/bin/perl -e '
my $topic = $ARGV[0];
my $msg = "* $topic has commits already merged to public branch:\n";
my (%not_in_next) = map {
/^([0-9a-f]+) /;
($1 => 1);
} split(/\n/, $ARGV[1]);
for my $elem (map {
/^([0-9a-f]+) (.*)$/;
[$1 => $2];
} split(/\n/, $ARGV[2])) {
if (!exists $not_in_next{$elem->[0]}) {
if ($msg) {
print STDERR $msg;
undef $msg;
}
print STDERR " $elem->[1]\n";
}
}
' "$topic" "$not_in_next" "$not_in_master"
exit 1
fi
exit 0
################################################################
This sample hook safeguards topic branches that have been
published from being rewound.
The workflow assumed here is:
* Once a topic branch forks from "master", "master" is never
merged into it again (either directly or indirectly).
* Once a topic branch is fully cooked and merged into "master",
it is deleted. If you need to build on top of it to correct
earlier mistakes, a new topic branch is created by forking at
the tip of the "master". This is not strictly necessary, but
it makes it easier to keep your history simple.
* Whenever you need to test or publish your changes to topic
branches, merge them into "next" branch.
The script, being an example, hardcodes the publish branch name
to be "next", but it is trivial to make it configurable via
$GIT_DIR/config mechanism.
With this workflow, you would want to know:
(1) ... if a topic branch has ever been merged to "next". Young
topic branches can have stupid mistakes you would rather
clean up before publishing, and things that have not been
merged into other branches can be easily rebased without
affecting other people. But once it is published, you would
not want to rewind it.
(2) ... if a topic branch has been fully merged to "master".
Then you can delete it. More importantly, you should not
build on top of it -- other people may already want to
change things related to the topic as patches against your
"master", so if you need further changes, it is better to
fork the topic (perhaps with the same name) afresh from the
tip of "master".
Let's look at this example:
o---o---o---o---o---o---o---o---o---o "next"
/ / / /
/ a---a---b A / /
/ / / /
/ / c---c---c---c B /
/ / / \ /
/ / / b---b C \ /
/ / / / \ /
---o---o---o---o---o---o---o---o---o---o---o "master"
A, B and C are topic branches.
* A has one fix since it was merged up to "next".
* B has finished. It has been fully merged up to "master" and "next",
and is ready to be deleted.
* C has not merged to "next" at all.
We would want to allow C to be rebased, refuse A, and encourage
B to be deleted.
To compute (1):
git rev-list ^master ^topic next
git rev-list ^master next
if these match, topic has not merged in next at all.
To compute (2):
git rev-list master..topic
if this is empty, it is fully merged to "master".

View File

@ -0,0 +1,36 @@
#!/bin/sh
#
# An example hook script to prepare the commit log message.
# Called by "git commit" with the name of the file that has the
# commit message, followed by the description of the commit
# message's source. The hook's purpose is to edit the commit
# message file. If the hook fails with a non-zero status,
# the commit is aborted.
#
# To enable this hook, rename this file to "prepare-commit-msg".
# This hook includes three examples. The first comments out the
# "Conflicts:" part of a merge commit.
#
# The second includes the output of "git diff --name-status -r"
# into the message, just before the "git status" output. It is
# commented because it doesn't cope with --amend or with squashed
# commits.
#
# The third example adds a Signed-off-by line to the message, that can
# still be edited. This is rarely a good idea.
case "$2,$3" in
merge,)
/usr/bin/perl -i.bak -ne 's/^/# /, s/^# #/#/ if /^Conflicts/ .. /#/; print' "$1" ;;
# ,|template,)
# /usr/bin/perl -i.bak -pe '
# print "\n" . `git diff --cached --name-status -r`
# if /^#/ && $first++ == 0' "$1" ;;
*) ;;
esac
# SOB=$(git var GIT_AUTHOR_IDENT | sed -n 's/^\(.*>\).*$/Signed-off-by: \1/p')
# grep -qs "^$SOB" "$1" || echo "$SOB" >> "$1"

View File

@ -0,0 +1,128 @@
#!/bin/sh
#
# An example hook script to blocks unannotated tags from entering.
# Called by "git receive-pack" with arguments: refname sha1-old sha1-new
#
# To enable this hook, rename this file to "update".
#
# Config
# ------
# hooks.allowunannotated
# This boolean sets whether unannotated tags will be allowed into the
# repository. By default they won't be.
# hooks.allowdeletetag
# This boolean sets whether deleting tags will be allowed in the
# repository. By default they won't be.
# hooks.allowmodifytag
# This boolean sets whether a tag may be modified after creation. By default
# it won't be.
# hooks.allowdeletebranch
# This boolean sets whether deleting branches will be allowed in the
# repository. By default they won't be.
# hooks.denycreatebranch
# This boolean sets whether remotely creating branches will be denied
# in the repository. By default this is allowed.
#
# --- Command line
refname="$1"
oldrev="$2"
newrev="$3"
# --- Safety check
if [ -z "$GIT_DIR" ]; then
echo "Don't run this script from the command line." >&2
echo " (if you want, you could supply GIT_DIR then run" >&2
echo " $0 <ref> <oldrev> <newrev>)" >&2
exit 1
fi
if [ -z "$refname" -o -z "$oldrev" -o -z "$newrev" ]; then
echo "usage: $0 <ref> <oldrev> <newrev>" >&2
exit 1
fi
# --- Config
allowunannotated=$(git config --bool hooks.allowunannotated)
allowdeletebranch=$(git config --bool hooks.allowdeletebranch)
denycreatebranch=$(git config --bool hooks.denycreatebranch)
allowdeletetag=$(git config --bool hooks.allowdeletetag)
allowmodifytag=$(git config --bool hooks.allowmodifytag)
# check for no description
projectdesc=$(sed -e '1q' "$GIT_DIR/description")
case "$projectdesc" in
"Unnamed repository"* | "")
echo "*** Project description file hasn't been set" >&2
exit 1
;;
esac
# --- Check types
# if $newrev is 0000...0000, it's a commit to delete a ref.
zero="0000000000000000000000000000000000000000"
if [ "$newrev" = "$zero" ]; then
newrev_type=delete
else
newrev_type=$(git cat-file -t $newrev)
fi
case "$refname","$newrev_type" in
refs/tags/*,commit)
# un-annotated tag
short_refname=${refname##refs/tags/}
if [ "$allowunannotated" != "true" ]; then
echo "*** The un-annotated tag, $short_refname, is not allowed in this repository" >&2
echo "*** Use 'git tag [ -a | -s ]' for tags you want to propagate." >&2
exit 1
fi
;;
refs/tags/*,delete)
# delete tag
if [ "$allowdeletetag" != "true" ]; then
echo "*** Deleting a tag is not allowed in this repository" >&2
exit 1
fi
;;
refs/tags/*,tag)
# annotated tag
if [ "$allowmodifytag" != "true" ] && git rev-parse $refname > /dev/null 2>&1
then
echo "*** Tag '$refname' already exists." >&2
echo "*** Modifying a tag is not allowed in this repository." >&2
exit 1
fi
;;
refs/heads/*,commit)
# branch
if [ "$oldrev" = "$zero" -a "$denycreatebranch" = "true" ]; then
echo "*** Creating a branch is not allowed in this repository" >&2
exit 1
fi
;;
refs/heads/*,delete)
# delete branch
if [ "$allowdeletebranch" != "true" ]; then
echo "*** Deleting a branch is not allowed in this repository" >&2
exit 1
fi
;;
refs/remotes/*,commit)
# tracking branch
;;
refs/remotes/*,delete)
# delete tracking branch
if [ "$allowdeletebranch" != "true" ]; then
echo "*** Deleting a tracking branch is not allowed in this repository" >&2
exit 1
fi
;;
*)
# Anything else (is there anything else?)
echo "*** Update hook: unknown type of update to ref $refname of type $newrev_type" >&2
exit 1
;;
esac
# --- Finished
exit 0

View File

@ -0,0 +1,6 @@
# git ls-files --others --exclude-from=.git/info/exclude
# Lines that start with '#' are comments.
# For a project mostly in C, the following would be a good set of
# exclude patterns (uncomment them if you want to use them):
# *.[oa]
# *~

View File

@ -0,0 +1 @@
0000000000000000000000000000000000000000 2e9bbc77d60f20eb462ead5b2ac7405b62b9b90a joshaber <joshaber@gmail.com> 1452186236 -0500 clone: from https://github.com/oneuijs/You-Dont-Need-jQuery

View File

@ -0,0 +1 @@
0000000000000000000000000000000000000000 2e9bbc77d60f20eb462ead5b2ac7405b62b9b90a joshaber <joshaber@gmail.com> 1452186236 -0500 clone: from https://github.com/oneuijs/You-Dont-Need-jQuery

View File

@ -0,0 +1 @@
0000000000000000000000000000000000000000 2e9bbc77d60f20eb462ead5b2ac7405b62b9b90a joshaber <joshaber@gmail.com> 1452186236 -0500 clone: from https://github.com/oneuijs/You-Dont-Need-jQuery

View File

@ -0,0 +1,2 @@
# pack-refs with: peeled fully-peeled
2e9bbc77d60f20eb462ead5b2ac7405b62b9b90a refs/remotes/origin/master

View File

@ -0,0 +1 @@
2e9bbc77d60f20eb462ead5b2ac7405b62b9b90a

View File

@ -0,0 +1 @@
ref: refs/remotes/origin/master

View File

@ -0,0 +1 @@
ref: refs/heads/master

View File

@ -0,0 +1 @@
9f0218b7652b622afea799a4723490c43e1af1fe

View File

@ -0,0 +1,14 @@
[core]
repositoryformatversion = 0
filemode = true
bare = false
logallrefupdates = true
worktree = ../../../jstips
ignorecase = true
precomposeunicode = true
[remote "origin"]
url = https://github.com/loverajoel/jstips
fetch = +refs/heads/*:refs/remotes/origin/*
[branch "master"]
remote = origin
merge = refs/heads/master

View File

@ -0,0 +1 @@
Unnamed repository; edit this file 'description' to name the repository.

View File

@ -0,0 +1 @@
.git

View File

@ -0,0 +1,15 @@
#!/bin/sh
#
# An example hook script to check the commit log message taken by
# applypatch from an e-mail message.
#
# The hook should exit with non-zero status after issuing an
# appropriate message if it wants to stop the commit. The hook is
# allowed to edit the commit message file.
#
# To enable this hook, rename this file to "applypatch-msg".
. git-sh-setup
commitmsg="$(git rev-parse --git-path hooks/commit-msg)"
test -x "$commitmsg" && exec "$commitmsg" ${1+"$@"}
:

View File

@ -0,0 +1,24 @@
#!/bin/sh
#
# An example hook script to check the commit log message.
# Called by "git commit" with one argument, the name of the file
# that has the commit message. The hook should exit with non-zero
# status after issuing an appropriate message if it wants to stop the
# commit. The hook is allowed to edit the commit message file.
#
# To enable this hook, rename this file to "commit-msg".
# Uncomment the below to add a Signed-off-by line to the message.
# Doing this in a hook is a bad idea in general, but the prepare-commit-msg
# hook is more suited to it.
#
# SOB=$(git var GIT_AUTHOR_IDENT | sed -n 's/^\(.*>\).*$/Signed-off-by: \1/p')
# grep -qs "^$SOB" "$1" || echo "$SOB" >> "$1"
# This example catches duplicate Signed-off-by lines.
test "" = "$(grep '^Signed-off-by: ' "$1" |
sort | uniq -c | sed -e '/^[ ]*1[ ]/d')" || {
echo >&2 Duplicate Signed-off-by lines.
exit 1
}

View File

@ -0,0 +1,8 @@
#!/bin/sh
#
# An example hook script to prepare a packed repository for use over
# dumb transports.
#
# To enable this hook, rename this file to "post-update".
exec git update-server-info

View File

@ -0,0 +1,14 @@
#!/bin/sh
#
# An example hook script to verify what is about to be committed
# by applypatch from an e-mail message.
#
# The hook should exit with non-zero status after issuing an
# appropriate message if it wants to stop the commit.
#
# To enable this hook, rename this file to "pre-applypatch".
. git-sh-setup
precommit="$(git rev-parse --git-path hooks/pre-commit)"
test -x "$precommit" && exec "$precommit" ${1+"$@"}
:

View File

@ -0,0 +1,49 @@
#!/bin/sh
#
# An example hook script to verify what is about to be committed.
# Called by "git commit" with no arguments. The hook should
# exit with non-zero status after issuing an appropriate message if
# it wants to stop the commit.
#
# To enable this hook, rename this file to "pre-commit".
if git rev-parse --verify HEAD >/dev/null 2>&1
then
against=HEAD
else
# Initial commit: diff against an empty tree object
against=4b825dc642cb6eb9a060e54bf8d69288fbee4904
fi
# If you want to allow non-ASCII filenames set this variable to true.
allownonascii=$(git config --bool hooks.allownonascii)
# Redirect output to stderr.
exec 1>&2
# Cross platform projects tend to avoid non-ASCII filenames; prevent
# them from being added to the repository. We exploit the fact that the
# printable range starts at the space character and ends with tilde.
if [ "$allownonascii" != "true" ] &&
# Note that the use of brackets around a tr range is ok here, (it's
# even required, for portability to Solaris 10's /usr/bin/tr), since
# the square bracket bytes happen to fall in the designated range.
test $(git diff --cached --name-only --diff-filter=A -z $against |
LC_ALL=C tr -d '[ -~]\0' | wc -c) != 0
then
cat <<\EOF
Error: Attempt to add a non-ASCII file name.
This can cause problems if you want to work with people on other platforms.
To be portable it is advisable to rename the file.
If you know what you are doing you can disable this check using:
git config hooks.allownonascii true
EOF
exit 1
fi
# If there are whitespace errors, print the offending file names and fail.
exec git diff-index --check --cached $against --

View File

@ -0,0 +1,53 @@
#!/bin/sh
# An example hook script to verify what is about to be pushed. Called by "git
# push" after it has checked the remote status, but before anything has been
# pushed. If this script exits with a non-zero status nothing will be pushed.
#
# This hook is called with the following parameters:
#
# $1 -- Name of the remote to which the push is being done
# $2 -- URL to which the push is being done
#
# If pushing without using a named remote those arguments will be equal.
#
# Information about the commits which are being pushed is supplied as lines to
# the standard input in the form:
#
# <local ref> <local sha1> <remote ref> <remote sha1>
#
# This sample shows how to prevent push of commits where the log message starts
# with "WIP" (work in progress).
remote="$1"
url="$2"
z40=0000000000000000000000000000000000000000
while read local_ref local_sha remote_ref remote_sha
do
if [ "$local_sha" = $z40 ]
then
# Handle delete
:
else
if [ "$remote_sha" = $z40 ]
then
# New branch, examine all commits
range="$local_sha"
else
# Update to existing branch, examine new commits
range="$remote_sha..$local_sha"
fi
# Check for WIP commit
commit=`git rev-list -n 1 --grep '^WIP' "$range"`
if [ -n "$commit" ]
then
echo >&2 "Found WIP commit in $local_ref, not pushing"
exit 1
fi
fi
done
exit 0

View File

@ -0,0 +1,169 @@
#!/bin/sh
#
# Copyright (c) 2006, 2008 Junio C Hamano
#
# The "pre-rebase" hook is run just before "git rebase" starts doing
# its job, and can prevent the command from running by exiting with
# non-zero status.
#
# The hook is called with the following parameters:
#
# $1 -- the upstream the series was forked from.
# $2 -- the branch being rebased (or empty when rebasing the current branch).
#
# This sample shows how to prevent topic branches that are already
# merged to 'next' branch from getting rebased, because allowing it
# would result in rebasing already published history.
publish=next
basebranch="$1"
if test "$#" = 2
then
topic="refs/heads/$2"
else
topic=`git symbolic-ref HEAD` ||
exit 0 ;# we do not interrupt rebasing detached HEAD
fi
case "$topic" in
refs/heads/??/*)
;;
*)
exit 0 ;# we do not interrupt others.
;;
esac
# Now we are dealing with a topic branch being rebased
# on top of master. Is it OK to rebase it?
# Does the topic really exist?
git show-ref -q "$topic" || {
echo >&2 "No such branch $topic"
exit 1
}
# Is topic fully merged to master?
not_in_master=`git rev-list --pretty=oneline ^master "$topic"`
if test -z "$not_in_master"
then
echo >&2 "$topic is fully merged to master; better remove it."
exit 1 ;# we could allow it, but there is no point.
fi
# Is topic ever merged to next? If so you should not be rebasing it.
only_next_1=`git rev-list ^master "^$topic" ${publish} | sort`
only_next_2=`git rev-list ^master ${publish} | sort`
if test "$only_next_1" = "$only_next_2"
then
not_in_topic=`git rev-list "^$topic" master`
if test -z "$not_in_topic"
then
echo >&2 "$topic is already up-to-date with master"
exit 1 ;# we could allow it, but there is no point.
else
exit 0
fi
else
not_in_next=`git rev-list --pretty=oneline ^${publish} "$topic"`
/usr/bin/perl -e '
my $topic = $ARGV[0];
my $msg = "* $topic has commits already merged to public branch:\n";
my (%not_in_next) = map {
/^([0-9a-f]+) /;
($1 => 1);
} split(/\n/, $ARGV[1]);
for my $elem (map {
/^([0-9a-f]+) (.*)$/;
[$1 => $2];
} split(/\n/, $ARGV[2])) {
if (!exists $not_in_next{$elem->[0]}) {
if ($msg) {
print STDERR $msg;
undef $msg;
}
print STDERR " $elem->[1]\n";
}
}
' "$topic" "$not_in_next" "$not_in_master"
exit 1
fi
exit 0
################################################################
This sample hook safeguards topic branches that have been
published from being rewound.
The workflow assumed here is:
* Once a topic branch forks from "master", "master" is never
merged into it again (either directly or indirectly).
* Once a topic branch is fully cooked and merged into "master",
it is deleted. If you need to build on top of it to correct
earlier mistakes, a new topic branch is created by forking at
the tip of the "master". This is not strictly necessary, but
it makes it easier to keep your history simple.
* Whenever you need to test or publish your changes to topic
branches, merge them into "next" branch.
The script, being an example, hardcodes the publish branch name
to be "next", but it is trivial to make it configurable via
$GIT_DIR/config mechanism.
With this workflow, you would want to know:
(1) ... if a topic branch has ever been merged to "next". Young
topic branches can have stupid mistakes you would rather
clean up before publishing, and things that have not been
merged into other branches can be easily rebased without
affecting other people. But once it is published, you would
not want to rewind it.
(2) ... if a topic branch has been fully merged to "master".
Then you can delete it. More importantly, you should not
build on top of it -- other people may already want to
change things related to the topic as patches against your
"master", so if you need further changes, it is better to
fork the topic (perhaps with the same name) afresh from the
tip of "master".
Let's look at this example:
o---o---o---o---o---o---o---o---o---o "next"
/ / / /
/ a---a---b A / /
/ / / /
/ / c---c---c---c B /
/ / / \ /
/ / / b---b C \ /
/ / / / \ /
---o---o---o---o---o---o---o---o---o---o---o "master"
A, B and C are topic branches.
* A has one fix since it was merged up to "next".
* B has finished. It has been fully merged up to "master" and "next",
and is ready to be deleted.
* C has not merged to "next" at all.
We would want to allow C to be rebased, refuse A, and encourage
B to be deleted.
To compute (1):
git rev-list ^master ^topic next
git rev-list ^master next
if these match, topic has not merged in next at all.
To compute (2):
git rev-list master..topic
if this is empty, it is fully merged to "master".

View File

@ -0,0 +1,36 @@
#!/bin/sh
#
# An example hook script to prepare the commit log message.
# Called by "git commit" with the name of the file that has the
# commit message, followed by the description of the commit
# message's source. The hook's purpose is to edit the commit
# message file. If the hook fails with a non-zero status,
# the commit is aborted.
#
# To enable this hook, rename this file to "prepare-commit-msg".
# This hook includes three examples. The first comments out the
# "Conflicts:" part of a merge commit.
#
# The second includes the output of "git diff --name-status -r"
# into the message, just before the "git status" output. It is
# commented because it doesn't cope with --amend or with squashed
# commits.
#
# The third example adds a Signed-off-by line to the message, that can
# still be edited. This is rarely a good idea.
case "$2,$3" in
merge,)
/usr/bin/perl -i.bak -ne 's/^/# /, s/^# #/#/ if /^Conflicts/ .. /#/; print' "$1" ;;
# ,|template,)
# /usr/bin/perl -i.bak -pe '
# print "\n" . `git diff --cached --name-status -r`
# if /^#/ && $first++ == 0' "$1" ;;
*) ;;
esac
# SOB=$(git var GIT_AUTHOR_IDENT | sed -n 's/^\(.*>\).*$/Signed-off-by: \1/p')
# grep -qs "^$SOB" "$1" || echo "$SOB" >> "$1"

View File

@ -0,0 +1,128 @@
#!/bin/sh
#
# An example hook script to blocks unannotated tags from entering.
# Called by "git receive-pack" with arguments: refname sha1-old sha1-new
#
# To enable this hook, rename this file to "update".
#
# Config
# ------
# hooks.allowunannotated
# This boolean sets whether unannotated tags will be allowed into the
# repository. By default they won't be.
# hooks.allowdeletetag
# This boolean sets whether deleting tags will be allowed in the
# repository. By default they won't be.
# hooks.allowmodifytag
# This boolean sets whether a tag may be modified after creation. By default
# it won't be.
# hooks.allowdeletebranch
# This boolean sets whether deleting branches will be allowed in the
# repository. By default they won't be.
# hooks.denycreatebranch
# This boolean sets whether remotely creating branches will be denied
# in the repository. By default this is allowed.
#
# --- Command line
refname="$1"
oldrev="$2"
newrev="$3"
# --- Safety check
if [ -z "$GIT_DIR" ]; then
echo "Don't run this script from the command line." >&2
echo " (if you want, you could supply GIT_DIR then run" >&2
echo " $0 <ref> <oldrev> <newrev>)" >&2
exit 1
fi
if [ -z "$refname" -o -z "$oldrev" -o -z "$newrev" ]; then
echo "usage: $0 <ref> <oldrev> <newrev>" >&2
exit 1
fi
# --- Config
allowunannotated=$(git config --bool hooks.allowunannotated)
allowdeletebranch=$(git config --bool hooks.allowdeletebranch)
denycreatebranch=$(git config --bool hooks.denycreatebranch)
allowdeletetag=$(git config --bool hooks.allowdeletetag)
allowmodifytag=$(git config --bool hooks.allowmodifytag)
# check for no description
projectdesc=$(sed -e '1q' "$GIT_DIR/description")
case "$projectdesc" in
"Unnamed repository"* | "")
echo "*** Project description file hasn't been set" >&2
exit 1
;;
esac
# --- Check types
# if $newrev is 0000...0000, it's a commit to delete a ref.
zero="0000000000000000000000000000000000000000"
if [ "$newrev" = "$zero" ]; then
newrev_type=delete
else
newrev_type=$(git cat-file -t $newrev)
fi
case "$refname","$newrev_type" in
refs/tags/*,commit)
# un-annotated tag
short_refname=${refname##refs/tags/}
if [ "$allowunannotated" != "true" ]; then
echo "*** The un-annotated tag, $short_refname, is not allowed in this repository" >&2
echo "*** Use 'git tag [ -a | -s ]' for tags you want to propagate." >&2
exit 1
fi
;;
refs/tags/*,delete)
# delete tag
if [ "$allowdeletetag" != "true" ]; then
echo "*** Deleting a tag is not allowed in this repository" >&2
exit 1
fi
;;
refs/tags/*,tag)
# annotated tag
if [ "$allowmodifytag" != "true" ] && git rev-parse $refname > /dev/null 2>&1
then
echo "*** Tag '$refname' already exists." >&2
echo "*** Modifying a tag is not allowed in this repository." >&2
exit 1
fi
;;
refs/heads/*,commit)
# branch
if [ "$oldrev" = "$zero" -a "$denycreatebranch" = "true" ]; then
echo "*** Creating a branch is not allowed in this repository" >&2
exit 1
fi
;;
refs/heads/*,delete)
# delete branch
if [ "$allowdeletebranch" != "true" ]; then
echo "*** Deleting a branch is not allowed in this repository" >&2
exit 1
fi
;;
refs/remotes/*,commit)
# tracking branch
;;
refs/remotes/*,delete)
# delete tracking branch
if [ "$allowdeletebranch" != "true" ]; then
echo "*** Deleting a tracking branch is not allowed in this repository" >&2
exit 1
fi
;;
*)
# Anything else (is there anything else?)
echo "*** Update hook: unknown type of update to ref $refname of type $newrev_type" >&2
exit 1
;;
esac
# --- Finished
exit 0

Binary file not shown.

View File

@ -0,0 +1,6 @@
# git ls-files --others --exclude-from=.git/info/exclude
# Lines that start with '#' are comments.
# For a project mostly in C, the following would be a good set of
# exclude patterns (uncomment them if you want to use them):
# *.[oa]
# *~

View File

@ -0,0 +1 @@
0000000000000000000000000000000000000000 9f0218b7652b622afea799a4723490c43e1af1fe joshaber <joshaber@gmail.com> 1452186187 -0500 clone: from https://github.com/loverajoel/jstips

View File

@ -0,0 +1 @@
0000000000000000000000000000000000000000 9f0218b7652b622afea799a4723490c43e1af1fe joshaber <joshaber@gmail.com> 1452186187 -0500 clone: from https://github.com/loverajoel/jstips

View File

@ -0,0 +1 @@
0000000000000000000000000000000000000000 9f0218b7652b622afea799a4723490c43e1af1fe joshaber <joshaber@gmail.com> 1452186187 -0500 clone: from https://github.com/loverajoel/jstips

View File

@ -0,0 +1,2 @@
# pack-refs with: peeled fully-peeled
9f0218b7652b622afea799a4723490c43e1af1fe refs/remotes/origin/master

View File

@ -0,0 +1 @@
9f0218b7652b622afea799a4723490c43e1af1fe

View File

@ -0,0 +1 @@
ref: refs/remotes/origin/master

View File

@ -0,0 +1 @@
x<01><>A E]sŠ¹€†JbL¯Â0h1Š÷—M÷ݽü¼Ÿ—Z­e€ñî2zÎ@ÎràÌ< ˆÆzm] $¢Ãi+¢âol­Ã§í[äÜáqÐú®±|o©Õ'GhîáªIk5×Ó?ô“Gõ*}ê·š5«

View File

@ -0,0 +1 @@
d2b0ad9cbc6f6c4372e8956e5cc5af771b2342e5

View File

@ -0,0 +1,20 @@
# How to submit your tip
To submit a tip to the list, fork the repository and add your tip to the top of the list of tips in the `README.md` file. You may want to use a [topic branch](https://github.com/dchelimsky/rspec/wiki/Topic-Branches) for each tip.
Use the format below when writing your tip. Your tip should be readable in less than two minutes. You may add links to other sites or videos that give more insight if you wish.
Once your tip is ready, [issue a pull request](https://help.github.com/articles/using-pull-requests/) and your tip will be reviewed. Every day one tip will be merged from the available pull requests.
# Tip format
## #01(number) - Title
> yyyy-mm-dd(date) by @username
This is my awesome tip!
# Notes
Leave the date and the tip number empty. When we decide merge the pull request you will add them and squash your commits.
Remember: New tips must be added to the *top* of the list of [tips](https://github.com/loverajoel/jstips#tips-list) in the `README.md` file.

Some files were not shown because too many files have changed in this diff Show More