diff --git a/src/gsdom.js b/src/gsdom.js index c09e8b2..95d4b31 100644 --- a/src/gsdom.js +++ b/src/gsdom.js @@ -1,335 +1,397 @@ window.$_ = (() => { 'use strict'; /** - * Création du constructeur + * La classe GSDom est une classe écrite en pur Javascript qui permet de simplifier la manipulation du DOM. + * + * @class GSDom * * @example - * # Tous les `a` class `link` contenu dans un `div` id `main` - * $_("a.link", "div#main"); - * - * @param {String} selector Sélecteur utilisé - * @param {HTMLElement} scope Racine de la recherche - */ - let Constructor = function (selector, scope) { - if (!selector) { - return; - } - if (selector === 'document') { - this.elems = [document, ]; - } else if (selector === 'window') { - this.elems = [window, ]; - } else { - let root = scope ? scope : document; - this.elems = root.querySelectorAll(selector); - } - }; - /** - * Application d'une fonction sur chacun des éléments - * + * // Ajout d'une classe `my_class` à tous lel `a` + * $_("a").addClass("my_class"); * @example - * $_(".class").each((item, index) => { - * // Do something with item et index - * }); - * - * @param {Function} callback La fonction de rappel - */ - Constructor.prototype.each = function (callback) { - if (!callback || typeof callback !== 'function') { - return; - } - this.elems.forEach((element, index) => { - callback(element, index); - }); - return this; - }; - /** - * Ajout d'une classe aux éléments sélectionnés - * + * // Ajout d'une classe `my_class` à tous les `a` enfants de `div#main` + * $_("a", "div#main").addClass("my_class"); * @example - * $_("p","div#main").addClass("myClass"); - * - * @param {String} className Le nom de la classe à ajouter - * @returns {this} Chainage - */ - Constructor.prototype.addClass = function (className) { - this.each(item => { - item.classList.add(className); - }); - return this; - }; - /** - * Suppression d'une classe aux éléments sélectionnés - * + * // Ajout d'une classe `my_class` à tous les `a` enfants de l'élément `my_scope` du DOM + * let my_scope = document.querySelector("div#main"); + * $_("a", my_scope).addClass("my_class"); * @example - * $_("p","div#main").removeClass("myClass"); + * // Instanciation de GSDom avec un élément du DOM et ajout d'une classe `my_class` à cet élément + * let element = document.querySelector("p#intro"); + * $_(element).addClass("my_class"); * - * @param {String} className Le nom de la classe à ajouter - * @returns {this} Chainage + * @param {(String|HTMLElement)} selector Sélecteur utilisé ou un élément du DOM (scope est alors ignoré) + * @param {(String|HTMLElement)} [scope=document] Sélecteur utilisé (le 1er élément trouvé est utilisé) ou un élément du DOM */ - Constructor.prototype.removeClass = function (className) { - this.each(item => { - item.classList.remove(className); - }); - return this; - }; - /** - * Remplace une classe par une autre dans les éléments sélectionnés - * - * @example - * $_("p","div#main").replaceClass("myOldClass", "myNewClass"); - * - * @param {String} oldClass Nom de la classe à remplacer - * @param {String} newClass Nom de la classe de remplacement - * @returns {this} Chainage - */ - Constructor.prototype.replaceClass = function (oldClass, newClass) { - this.each(item => { - item.classList.replace(oldClass, newClass); - }); - return this; - }; - /** - * Définit un attribut et sa valeur - * - * @example - * $_("input.class").setAttr("readonly", ""); - * - * @param {String} attr Nom de l'attribut - * @param {String} value Valeur de l'attribut - * @returns {this} Chainage - */ - Constructor.prototype.setAttr = function (attr, value) { - this.each(item => { - item.setAttribute(attr, value); - }); - return this; - }; - /** - * Supprime un attribut dans les éléments sélectionnés - * - * @example - * $_(input.class).delAttr("readonly"); - * - * @param {String} attr Nom de l'attribut à supprimer - * @returns {this} Chainage - */ - Constructor.prototype.delAttr = function (attr) { - this.each(item => { - item.removeAttribute(attr); - }); - return this; - }; - /** - * Ajoute l'attribut hidden aux éléments sélectionnés - * - * @example $_("span.class").setHidden(); - * - * @returns {this} Chainage - */ - Constructor.prototype.setHidden = function () { - this.setAttr('hidden', ''); - return this; - }; - /** - * Ajoute l'attribut readonly aux éléments sélectionnés - * - * @example - * $_("input.class").setReadOnly(); - * - * @returns {this} Chainage - */ - Constructor.prototype.setReadOnly = function () { - this.setAttr('readonly', ''); - return this; - }; - /** - * Ajoute l'attribut disabled aux éléments sélectionnés - * - * @example - * $_("input.class").setDisabled(); - * - * @returns {this} Chainage - */ - Constructor.prototype.setDisabled = function () { - this.setAttr('disabled', ''); - return this; - }; - /** - * Supprime l'attribut hidden aux éléments sélectionnés - * - * @example - * $_("span.class").delHidden(); - * - * @returns {this} Chainage - */ - Constructor.prototype.delHidden = function () { - this.delAttr('hidden'); - return this; - }; - /** - * Supprime l'attribut readonly aux éléments sélectionnés - * - * @example - * $_("input.class").delReadOnly(); - * - * @returns {this} Chainage - */ - Constructor.prototype.delReadOnly = function () { - this.delAttr('readonly'); - return this; - }; - /** - * Supprime l'attribut disabled aux éléments sélectionnés - * - * @example - * $_("input.class").delDisabled(); - * - * @returns {this} Chainage - */ - Constructor.prototype.delDisabled = function () { - this.delAttr('disabled'); - return this; - }; - /** - * switche l'attribut hidden des éléments sélectionnés - * - * @example - * $_("span.class").toggleHidden(); - * - * @returns {this} Chainage - */ - Constructor.prototype.toggleHidden = function () { - this.each(item => { - if (item.hasAttribute('hidden')) { - item.removeAttribute('hidden'); - } else { - item.setAttribute('hidden', ''); + class GSDom { + constructor(selector, scope) { + this.shortversion = '2.0.0'; + this.longversion = 'GSDom 2.0.0 by Séb'; + if (!selector) { + // On ne va pas plus loin s'il n'y a pas de sélecteur + return; } - }); - return this; - }; - /** - * switche l'attribut readonly des éléments sélectionnés - * - * @example - * $_("input.class").toggleReadOnly(); - * - * @returns {this} Chainage - */ - Constructor.prototype.toggleReadOnly = function () { - this.each(item => { - if (item.hasAttribute('readonly')) { - item.removeAttribute('readonly'); + if (selector === 'document') { + // Cas particulier pour document + this.elems = [document, ]; + } else if (selector === 'window') { + // CAs particulier pour window + this.elems = [window, ]; } else { - item.setAttribute('readonly', ''); + if (selector instanceof HTMLElement) { + // Cas où un élément du DOM est fourni + this.elems = [selector, ]; + } else { + // Cas ou un sélecteur est fourni + let root = false; + if (!scope) { + // Si pas de scope, on utilise le document + root = document; + } else { + if (!((scope instanceof HTMLElement)) && (typeof scope === 'string')) { + // Si le scope est un selecteur, on utilise le premier élément de DOM correspondant + root = document.querySelector(scope); + } else { + // On utilise l'élément du DOM fourni + root = scope; + } + } + if (root) + this.elems = root.querySelectorAll(selector); + else + this.elems = []; + } } - }); - return this; - }; - /** - * switche l'attribut disabled des éléments sélectionnés - * - * @example - * $_("input.class").toggleDisabled(); - * - * @returns {this} Chainage - */ - Constructor.prototype.toggleDisabled = function () { - this.each(item => { - if (item.hasAttribute('disabled')) { - item.removeAttribute('disabled'); - } else { - item.setAttribute('disabled', ''); + } + /** + * Parcours de tous les éléments sélectionnés + * + * @example + * //appliquer une fonction sur tous les éléments ayant `my_class` + * $_(".my_class").each((item, index) => { + * // Do something with item et index + * }); + * + * @param {eachCallback} callback La fonction de rappel + */ + each(callback) { + if (!callback || typeof callback !== 'function') { + return; } - }); - return this; + this.elems.forEach((element, index) => { + callback(element, index); + }); + return this; + } + /** + * Fonction de rappel la méthode each() + * @callback eachCallback + * @see {@link #each} + * @param {HTMLElement} element L'élément du DOM concerné + * @param {number} index L'index de l'élément + */ + + /** + * Ajout d'une classe aux éléments sélectionnés + * + * @example + * $_("p","div#main").addClass("my_class"); + * + * @param {String} className Le nom de la classe à ajouter + * @returns {this} Chainage + */ + addClass(className) { + this.each(item => { + item.classList.add(className); + }); + return this; + } + /** + * Suppression d'une classe aux éléments sélectionnés + * + * @example + * $_("p","div#main").removeClass("my_class"); + * + * @param {String} className Le nom de la classe à ajouter + * @returns {this} Chainage + */ + removeClass(className) { + this.each(item => { + item.classList.remove(className); + }); + return this; + } + /** + * Suppression de toutes les classes des éléments sélectionnés + * + * @example + * $_("p","div#main").removeAllClasses("myClass"); + * + * @returns {this} Chainage + */ + removeAllClasses() { + this.each(item => { + item.className = ""; + }); + return this; + } + /** + * Remplace une classe par une autre parmi les éléments sélectionnés + * + * @example + * $_("p","div#main").replaceClass("my_old_class", "my_new_class"); + * + * @param {String} oldClass Nom de la classe à remplacer + * @param {String} newClass Nom de la classe de remplacement + * @returns {this} Chainage + */ + replaceClass(oldClass, newClass) { + this.each(item => { + item.classList.replace(oldClass, newClass); + }); + return this; + } + /** + * Définit un attribut et sa valeur + * + * @example + * $_("input.my_class").setAttr("readonly", ""); + * + * @param {String} attr Nom de l'attribut + * @param {String} value Valeur de l'attribut + * @returns {this} Chainage + */ + setAttr(attr, value) { + this.each(item => { + item.setAttribute(attr, value); + }); + return this; + } + /** + * Supprime un attribut dans les éléments sélectionnés + * + * @example + * $_(input.my_class).delAttr("readonly"); + * + * @param {String} attr Nom de l'attribut à supprimer + * @returns {this} Chainage + */ + delAttr(attr) { + this.each(item => { + item.removeAttribute(attr); + }); + return this; + } + /** + * Ajoute l'attribut hidden aux éléments sélectionnés + * + * @example $_("span.my_class").setHidden(); + * + * @returns {this} Chainage + */ + setHidden() { + this.setAttr('hidden', ''); + return this; + } + /** + * Ajoute l'attribut `readonly` aux éléments sélectionnés + * + * @example + * $_("input.my_class").setReadOnly(); + * + * @returns {this} Chainage + */ + setReadOnly() { + this.setAttr('readonly', ''); + return this; + } + /** + * Ajoute l'attribut `disabled` aux éléments sélectionnés + * + * @example + * $_("input.my_class").setDisabled(); + * + * @returns {this} Chainage + */ + setDisabled() { + this.setAttr('disabled', ''); + return this; + } + /** + * Supprime l'attribut `hidden` aux éléments sélectionnés + * + * @example + * $_("span.my_class").delHidden(); + * + * @returns {this} Chainage + */ + delHidden() { + this.delAttr('hidden'); + return this; + } + /** + * Supprime l'attribut `readonly` aux éléments sélectionnés + * + * @example + * $_("input.my_class").delReadOnly(); + * + * @returns {this} Chainage + */ + delReadOnly() { + this.delAttr('readonly'); + return this; + } + /** + * Supprime l'attribut `disabled` aux éléments sélectionnés + * + * @example + * $_("input.my_class").delDisabled(); + * + * @returns {this} Chainage + */ + delDisabled() { + this.delAttr('disabled'); + return this; + } + /** + * switche l'attribut `hidden` des éléments sélectionnés + * + * @example + * $_("span.my_class").toggleHidden(); + * + * @returns {this} Chainage + */ + toggleHidden() { + this.each(item => { + if (item.hasAttribute('hidden')) { + item.removeAttribute('hidden'); + } else { + item.setAttribute('hidden', ''); + } + }); + return this; + } + /** + * switche l'attribut `readonly` des éléments sélectionnés + * + * @example + * $_("input.my_class").toggleReadOnly(); + * + * @returns {this} Chainage + */ + toggleReadOnly() { + this.each(item => { + if (item.hasAttribute('readonly')) { + item.removeAttribute('readonly'); + } else { + item.setAttribute('readonly', ''); + } + }); + return this; + } + /** + * switche l'attribut `disabled` des éléments sélectionnés + * + * @example + * $_("input.my_class").toggleDisabled(); + * + * @returns {this} Chainage + */ + toggleDisabled() { + this.each(item => { + if (item.hasAttribute('disabled')) { + item.removeAttribute('disabled'); + } else { + item.setAttribute('disabled', ''); + } + }); + return this; + } + /** + * Ajoute un gestionnaire d'événement aux éléments sélectionnés + * + * @example + * $_("button#event").on("mouseover", (evt, el) => { + * // Do something with evt and el + * }, false); + * + * @param {String} type Nom de l'événement + * @param {evtCallback} callback Gestionnaire de l'événement + * @param {Boolean} useCapture Propagation de l'événement + */ + on(type, callback, useCapture) { + this.each(item => { + item.removeEventListener(type, callback, useCapture || false); + item.addEventListener(type, evt => { + callback(evt, item); + }, useCapture || false); + }); + return this; + } + /** + * Ajout d'un gestionnaire d'événement 'click' pour les éléments sélectionnés + * + * @example + * $_("button#event").onClick( (evt, el) => { + * // Do something with evt and el + * }, false); + * + * @param {evtCallback} callback Gestionnaire de l'événement + * @param {Boolean} useCapture Propagation de l'événement + */ + onClick(callback, useCapture) { + this.on('click', callback, useCapture || false); + return this; + } + /** + * Fonction de rappel des méthodes on() et onClick() + * @callback evtCallback + * @see {@link #on} + * @see {@link #onclick} + * @param {Event} evt L'événement qui s'est produit + * @param {HTMLElement} item L'élément du DOM concerné par lévénement + */ + + /** + * Retourne si un élément a été trouvé + * + * @example + * let found = $_("#main").found(); + * + * @returns {Boolean} `true` si un élément au moins du DOM trouvé. `false` sinon + */ + found() { + return this.elems.length > 0; + } + /** + * Retourne le premier élément trouvé + * + * @example + * let htmlElement = $_("p.paragraphe").first(); + * + * @param {Boolean} [isHTMLElement=false] `true` pour obtenir un élément du DOM, `false` pour un Objet GSDom + * @returns {HTMLElement} l'élément du DOM trouvé + */ + first(isHTMLElement) { + return this.found() ? (isHTMLElement === true ? this.elems[0] : new GSDom(this.elems[0])) : false; + } + /** + * Retourne le dernier élément trouvé + * + * @example + * let htmlElement = $_("p.paragraphe").last(); + * + * @param {Boolean} [isHTMLElement=false] `true` pour obtenir un élément du DOM, `false` pour un Objet GSDom + * @returns {(GSDom|HTMLElement)} L'élément du DOM trouvé ou un Objet GSDom correspondant pour chainage + */ + last(isHTMLElement) { + return this.found() ? (isHTMLElement === true ? this.elems[this.elems.length - 1] : new GSDom(this.elems[this.elems.length - 1])) : false; + } + version(long) { + return long === true ? this.longversion : this.shortversion; + } + } + return (selector, root) => { + return new GSDom(selector, root); }; - /** - * Ajout d'un gestionnaire d'événement aux éléments sélectionnés - * - * @example - * $_("button#event").on("mouseover", (evt, el) => { - * // Do something with evt and el - * }, false); - * - * @param {String} type Nom de l'événement - * @param {Function} callback Gestionnaire de l'événement - * @param {Boolean} useCapture Propagation de l'événement - */ - Constructor.prototype.on = function (type, callback, useCapture) { - this.each(item => { - item.removeEventListener(type, callback, useCapture || false); - item.addEventListener(type, (evt, el) => { - callback(evt, el); - }, useCapture || false); - }); - return this; - }; - /** - * Ajout d'un gestionnaire d'événement 'click' pour les éléments sélectionnés - * - * @example - * $_("button#event").onClick( (evt, el) => { - * // Do something with evt and el - * }, false); - * - * @param {Function} callback Gestionnaire de l'événement - * @param {Boolean} useCapture Propagation de l'événement - */ - Constructor.prototype.onClick = function (callback, useCapture) { - this.on('click', callback, useCapture || false); - return this; - }; - /** - * Retourne si un élément a été trouvé - * - * @example - * let found = $_("#main").found(); - * - * @returns {Boolean} `true` si un élément au moins du DOM trouvé. `false` sinon - */ - Constructor.prototype.found = function () { - return this.elems.length > 0; - }; - /** - * Retourne le premier élément trouvé - * - * @example - * let htmlElement = $_("p.paragraphe").first(); - * - * @returns {HTMLElement} l'élément du DOM trouvé - */ - Constructor.prototype.first = function () { - return this.found() ? this.elems[0] : false; - }; - /** - * Retourne le dernier élément trouvé - * - * @example - * let htmlElement = $_("p.paragraphe").last(); - * - * @returns {HTMLElement} L'élément du DOM trouvé - */ - Constructor.prototype.last = function () { - return this.found() ? this.elems[this.elems.length - 1] : false; - }; - /** - * Instantiation d'un nouveau constructeur - * - * @internal - * - * @param {String} selector Sélecteur utilisé - * @param {HTMLElement} scope Racine de la recherche - */ - let gsd = (selector, root) => { - return new Constructor(selector, root); - }; - /** - * Version de la librairie - */ - gsd.version = 'GSD 1.1.1 by Séb'; - /** - * @return Retour de la librairie - */ - return gsd; })(); \ No newline at end of file