"Thinking in AngularJS" si j'ai un fond jQuery?

Supposons que je connaisse le développement des applications côté client dans jQuery , mais maintenant, j'aimerais commencer à utiliser AngularJS . Pouvez-vous décrire le changement de paradigme nécessaire? Voici quelques questions qui pourraient vous aider à définir une réponse:

  • Comment puis-je architecte et concevoir des applications Web côté client différemment? Quelle est la plus grande différence?
  • Que dois-je arrêter de faire / utiliser? Que dois-je commencer à utiliser / utiliser à la place?
  • Existe-t-il des considérations / restrictions côté serveur?

Je ne cherche pas une comparaison détaillée entre jQuery et AngularJS .

1. Ne concevez pas votre page, puis modifiez-la avec les manipulations DOM

Dans jQuery, vous concevez une page, puis vous la rendez dynamique. C'est parce que jQuery a été conçu pour l'augmentation et s'est développé incroyablement à partir de cette base simple.

Mais dans AngularJS, vous devez commencer à partir de la base de votre architecture à l'esprit. Au lieu de commencer par penser «j'ai ce morceau de DOM et je veux le faire faire X», vous devez commencer par ce que vous voulez accomplir, puis concevoir votre application, puis enfin concevoir votre vue.

2. Ne pas augmenter jQuery avec AngularJS

De même, ne commencez pas par l'idée que jQuery ne soit X, Y et Z, alors je vais simplement ajouter AngularJS en plus de cela pour les modèles et les contrôleurs. C'est vraiment tentant lorsque vous commencez juste, c'est pourquoi je recommande toujours que les nouveaux développeurs AngularJS n'utilisent pas jQuery du tout, au moins jusqu'à ce qu'ils s'habituent à faire de la "voie angulaire".

J'ai vu de nombreux développeurs ici et sur la liste de diffusion créer ces solutions élaborées avec les plugins jQuery de 150 ou 200 lignes de code qu'ils collent ensuite dans AngularJS avec une collection de rappels et $apply s qui sont déroutants et compliqués; Mais ils finissent par fonctionner! Le problème est que, dans la plupart des cas, le plugin jQuery pourrait être réécrit dans AngularJS dans une fraction du code, où soudain, tout devient compréhensible et direct.

La ligne de fond est la suivante: lors de la solution, commencez par "penser en AngularJS"; Si vous ne pouvez pas penser à une solution, demandez à la communauté; Si après tout cela, il n'y a pas de solution facile, alors n'hésitez pas à joindre le jQuery. Mais ne laissez pas jQuery devenir une béquille ou vous ne maîtriserez jamais AngularJS.

3. Toujours penser en termes d'architecture

Tout d'abord, savoir que les applications d'une seule page sont des applications . Ce ne sont pas des pages Web. Nous devons donc penser à un développeur côté serveur en plus de penser à un développeur client. Nous devons réfléchir à la façon de diviser notre application en composants individuels, extensibles et vérifiables.

Alors, comment faites-vous cela? Comment pensez-vous dans AngularJS? Voici quelques principes généraux, en contraste avec jQuery.

La vue est le "record officiel"

Dans jQuery, nous modifions par programme la vue. Nous pourrions avoir un menu déroulant défini comme un ul comme ça:

 <ul class="main-menu"> <li class="active"> <a href="#/home">Home</a> </li> <li> <a href="#/menu1">Menu 1</a> <ul> <li><a href="#/sm1">Submenu 1</a></li> <li><a href="#/sm2">Submenu 2</a></li> <li><a href="#/sm3">Submenu 3</a></li> </ul> </li> <li> <a href="#/home">Menu 2</a> </li> </ul> 

Dans jQuery, dans notre logique d'application, nous l'activons avec quelque chose comme:

 $('.main-menu').dropdownMenu(); 

Lorsque nous regardons la vue, il n'est pas immédiatement évident qu'il y ait des fonctionnalités ici. Pour les petites applications, c'est très bien. Mais pour les applications non triviales, les choses deviennent rapidement confuses et difficiles à maintenir.

Dans AngularJS, cependant, la vue est le registre officiel des fonctionnalités basées sur la vue. Notre déclaration ul ressemblerait à ceci:

 <ul class="main-menu" dropdown-menu> ... </ul> 

Ces deux font la même chose, mais dans la version AngularJS, tout le monde qui regarde le modèle sait ce qu'il devrait arriver. Chaque fois qu'un nouveau membre de l'équipe de développement arrive à bord, elle peut se pencher sur cela et savoir qu'il existe une directive appelée dropdownMenu opère sur elle; Elle n'a pas besoin d'intuir la bonne réponse ou de filtrer tout code. La vue nous a expliqué ce qu'il fallait se produire. Beaucoup plus propre.

Les développeurs nouveaux chez AngularJS posent souvent une question comme: je trouve tous les liens d'un type spécifique et j'ajoute une directive sur eux. Le développeur est toujours étonné lorsque nous répondons: vous ne le faites pas. Mais la raison pour laquelle vous ne le faites pas, c'est que c'est comme une demi-jQuery, une demi-angulaire et non un bon. Le problème ici est que le développeur essaye de "faire jQuery" dans le contexte d'AngularJS. Cela ne marchera jamais bien. La vue est le document officiel. En dehors d'une directive (plus sur ceci ci-dessous), vous n'avez jamais changé jamais le DOM. Et les directives sont appliquées dans la vue , donc l'intention est claire.

Rappelez-vous: ne pas concevoir, puis marquer. Vous devez architecte, puis concevez.

Reliure des données

C'est de loin l'une des fonctionnalités les plus impressionnantes d'AngularJS et réduit considérablement la nécessité de faire les types de manipulations DOM que j'ai mentionnées dans la section précédente. AngularJS mettra automatiquement à jour votre vue de sorte que vous ne devez pas le faire! Dans jQuery, nous répondons aux événements, puis nous mettons à jour le contenu. Quelque chose comme:

 $.ajax({ url: '/myEndpoint.json', success: function ( data, status ) { $('ul#log').append('<li>Data Received!</li>'); } }); 

Pour une vue qui ressemble à ceci:

 <ul class="messages" id="log"> </ul> 

En plus de mélanger les préoccupations, nous avons également les mêmes problèmes d'intention que je l'ai déjà mentionné. Mais surtout, nous avons dû faire référence et mettre à jour manuellement un noeud DOM. Et si nous voulons supprimer une entrée de journal, nous devons coder sur le DOM pour cela aussi. Comment tester la logique en dehors du DOM? Et si nous voulons changer la présentation?

C'est un peu désordonné et un peu fragile. Mais dans AngularJS, nous pouvons le faire:

 $http( '/myEndpoint.json' ).then( function ( response ) { $scope.log.push( { msg: 'Data Received!' } ); }); 

Et notre point de vue peut ressembler à ceci:

 <ul class="messages"> <li ng-repeat="entry in log">{{ entry.msg }}</li> </ul> 

Mais pour cette question, notre point de vue pourrait ressembler à ceci:

 <div class="messages"> <div class="alert" ng-repeat="entry in log"> {{ entry.msg }} </div> </div> 

Et maintenant, au lieu d'utiliser une liste non ordonnée, nous utilisons des boîtes d'alerte Bootstrap. Et nous n'avons jamais eu à changer le code du contrôleur! Mais plus important encore, peu importe ou comment le journal est mis à jour, la vue changera aussi. Automatiquement. Soigné!

Bien que je ne l'ai pas montré ici, la liaison des données est bidirectionnelle. Ainsi, ces messages de journal peuvent également être modifiables dans la vue en faisant ceci: <input ng-model="entry.msg" /> . Et il y avait beaucoup de joie.

Couche de modèle distincte

Dans jQuery, le DOM est comme le modèle. Mais dans AngularJS, nous avons une couche de modèle distincte que nous pouvons gérer de toutes les façons que nous voulons, complètement indépendamment de la vue. Cela contribue à la liaison des données ci-dessus, maintient la séparation des préoccupations et présente une plus grande stabilité. D'autres réponses ont mentionné ce point, alors je vais simplement laisser cela.

Séparation des préoccupations

Et tous les éléments ci-dessus s'inscrivent dans ce thème: garder vos préoccupations séparées. Votre point de vue sert d'enregistrement officiel de ce qui est censé se produire (pour la plupart); Votre modèle représente vos données; Vous avez une couche de service pour effectuer des tâches réutilisables; Vous effectuez une manipulation DOM et augmentez votre vision avec des directives; Et vous collez tout cela avec les contrôleurs. Cela a également été mentionné dans d'autres réponses, et la seule chose que j'aimerais ajouter concerne la testabilité, dont je discute dans une autre section ci-dessous.

Injection de dépendance

Pour nous aider à séparer les préoccupations, on utilise l'injection de dépendance (DI). Si vous venez d'une langue côté serveur (de Java vers PHP ), vous êtes probablement familiarisé avec ce concept déjà, mais si vous êtes un client de jQuery, ce concept peut ressembler à tout, parfait à superflu à hipster . Mais ce n'est pas. 🙂

D'un point de vue large, DI signifie que vous pouvez déclarer des composants très librement, puis de n'importe quel autre composant, il suffit de demander une instance et il sera accordé. Vous ne devez pas savoir comment charger l'ordre, ni les emplacements des fichiers, ni quelque chose comme ça. L'alimentation peut ne pas être visible immédiatement, mais je ne fournira qu'un seul exemple (courant): le test.

Disons que dans notre application, nous avons besoin d'un service qui implémente le stockage côté serveur via une API REST et, selon l'état de l'application, le stockage local. Lors de l'exécution des tests sur nos contrôleurs, nous ne voulons pas devoir communiquer avec le serveur – nous testons le contrôleur , après tout. Nous pouvons simplement ajouter un service de simulation du même nom que notre composant d'origine, et l'injecteur veillera à ce que notre contrôleur obtienne le faux automatiquement – notre contrôleur n'a pas besoin de connaître la différence.

Parlant de tests …

4. Développement axé sur les tests – toujours

Cela fait vraiment partie de la section 3 sur l'architecture, mais il est si important que je le considère comme sa propre section de haut niveau.

Sur l'ensemble des nombreux plugins jQuery que vous avez vus, utilisés ou écrits, combien d'entre eux avaient une suite de test accompagnant? Pas très nombreux parce que jQuery n'est pas très propice à cela. Mais AngularJS est.

Dans jQuery, le seul moyen de tester consiste souvent à créer le composant indépendamment avec une page de démonstration / démonstration pour que nos tests puissent effectuer une manipulation DOM. Ensuite, nous devons développer un composant séparément, puis l' intégrer dans notre application. Quelle inconvénient! La plupart du temps, lorsque nous développons avec jQuery, nous optons pour un développement itératif plutôt que sur un test. Et qui pourrait nous reprocher?

Mais parce que nous avons une séparation des préoccupations, nous pouvons faire un développement axé sur les tests itérativement dans AngularJS! Par exemple, disons que nous voulons qu'une directive super-simple indique dans notre menu quelle est notre route actuelle. Nous pouvons déclarer ce que nous voulons dans l'optique de notre application:

 <a href="/hello" when-active>Hello</a> 

D'accord, nous pouvons maintenant écrire un test pour la directive inexistante when-active :

 it( 'should add "active" when the route changes', inject(function() { var elm = $compile( '<a href="/hello" when-active>Hello</a>' )( $scope ); $location.path('/not-matching'); expect( elm.hasClass('active') ).toBeFalsey(); $location.path( '/hello' ); expect( elm.hasClass('active') ).toBeTruthy(); })); 

Et lorsque nous effectuons notre test, nous pouvons confirmer qu'il échoue. Seulement maintenant, nous devrions créer notre directive:

 .directive( 'whenActive', function ( $location ) { return { scope: true, link: function ( scope, element, attrs ) { scope.$on( '$routeChangeSuccess', function () { if ( $location.path() == element.attr( 'href' ) ) { element.addClass( 'active' ); } else { element.removeClass( 'active' ); } }); } }; }); 

Notre test passe maintenant et notre menu fonctionne comme demandé. Notre développement est à la fois itératif et axé sur les tests. Mauvais-cool.

5. Conceptuellement, les directives ne sont pas regroupées jQuery

Vous entendrez souvent "uniquement la manipulation DOM dans une directive". C'est une nécessité. Traitez-le avec une déférence due!

Mais plongeons un peu plus profondément …

Certaines directives simplement décorent ce qui est déjà dans la vue (pense ngClass ) et donc parfois la manipulation DOM immédiatement et ensuite sont essentiellement faites. Mais si une directive est comme un «widget» et a un modèle, elle devrait également respecter la séparation des préoccupations. C'est-à-dire que le modèle devrait également rester largement indépendant de sa mise en œuvre dans les fonctions de liaison et de contrôleur.

AngularJS est livré avec un ensemble d'outils pour rendre cela très simple; Avec ngClass nous pouvons mettre à jour dynamiquement la classe; ngModel permet une liaison bidirectionnelle de données; ngShow et ngHide montrent ou masquent de ngHide programmée un élément; Et beaucoup plus – y compris ceux que nous écrivons nous-mêmes. En d'autres termes, nous pouvons faire toutes sortes d'émotions sans manipulation DOM. Plus les manipulations de DOM, les directives plus faciles sont à tester, plus elles sont faciles à styliser, plus elles sont faciles à changer dans le futur et plus elles sont réutilisables et distribuables.

Je vois beaucoup de développeurs nouveaux à AngularJS en utilisant les directives comme lieu de jeter un tas de jQuery. En d'autres termes, ils pensent "puisque je ne peux pas faire de manipulation DOM dans le contrôleur, je prendrai ce code pour le mettre dans une directive". Bien que cela soit beaucoup mieux, il est toujours toujours faux .

Pensez à l'enregistreur que nous avons programmé dans la section 3. Même si nous mettons cela dans une directive, nous voulons toujours le faire «Voie angulaire». Il ne prend toujours aucune manipulation DOM! Il y a beaucoup de fois où la manipulation DOM est nécessaire, mais c'est beaucoup plus rare que vous le pensez! Avant de manipuler DOM partout dans votre application, demandez-vous si vous avez vraiment besoin. Il pourrait y avoir une meilleure façon.

Voici un exemple rapide qui montre le modèle que je vois le plus souvent. Nous voulons un bouton à bascule. (Note: cet exemple est un peu conçu et un skosh détaillé pour représenter des cas plus compliqués qui sont résolus exactement de la même manière).

 .directive( 'myDirective', function () { return { template: '<a class="btn">Toggle me!</a>', link: function ( scope, element, attrs ) { var on = false; $(element).click( function () { on = !on; $(element).toggleClass('active', on); }); } }; }); 

Il y a quelques problèmes:

  1. Tout d'abord, jQuery n'a jamais été nécessaire. Il n'y a rien que nous avons fait ici qui nécessitait jQuery du tout!
  2. Deuxièmement, même si nous avons déjà jQuery sur notre page, il n'y a aucune raison de l'utiliser ici; Nous pouvons simplement utiliser angular.element et notre composant fonctionnera toujours lorsqu'il sera jeté dans un projet qui n'a pas jQuery.
  3. Troisièmement, même si jQuery était requis pour que cette directive fonctionne, jqLite ( angular.element ) utilisera toujours jQuery si elle a été chargée! Nous n'avons donc pas besoin d'utiliser le $ – nous pouvons simplement utiliser angular.element .
  4. Quatrièmement, étroitement lié à la troisième, est-ce que les éléments jqLite ne doivent pas être enveloppés en $ – l' element qui est transmis à la fonction de link serait déjà un élément jQuery!
  5. Et cinquième, que nous avons mentionné dans les sections précédentes, pourquoi mélangeons-nous des modèles dans notre logique?

Cette directive peut être réécrite (même pour des cas très compliqués!) Beaucoup plus simplement comme ceci:

 .directive( 'myDirective', function () { return { scope: true, template: '<a class="btn" ng-class="{active: on}" ng-click="toggle()">Toggle me!</a>', link: function ( scope, element, attrs ) { scope.on = false; scope.toggle = function () { scope.on = !scope.on; }; } }; }); 

Encore une fois, les éléments du modèle sont dans le modèle, de sorte que vous (ou vos utilisateurs) pouvez facilement l'échanger pour un qui répond à tout style nécessaire et la logique n'a jamais eu à être touchée. Reusabilité – boom!

Et il y a toujours tous ces autres avantages, comme les tests – c'est facile! Peu importe ce qu'il y a dans le modèle, l'API interne de la directive n'est jamais touchée, donc la refactorisation est facile. Vous pouvez modifier le modèle autant que vous le souhaitez sans toucher la directive. Et peu importe ce que vous changez, vos tests passent encore.

W00t!

Donc, si les directives ne sont pas seulement des collections de fonctions jQuery-like, qu'est-ce qu'elles sont? Les directives sont en fait des extensions de HTML . Si HTML ne fait pas quelque chose que vous en avez besoin, vous écrivez une directive pour le faire pour vous, puis utilisez-le comme si cela faisait partie du HTML.

Autrement dit, si AngularJS ne fait rien de rien, réfléchissez à la façon dont l'équipe l'accomplirait parfaitement avec ngClick , ngClass et al.

Résumé

N'utilisez même pas jQuery. Ne l'incluez même pas. Il vous retiendra. Et lorsque vous parvenez à un problème que vous pensez savoir déjà résoudre dans jQuery, avant d'atteindre le $ , essayez de réfléchir à la façon de le faire dans les limites de l'AngularJS. Si vous ne le savez pas, demandez! 19 fois sur 20, la meilleure façon de le faire n'a pas besoin de jQuery et essayer de le résoudre avec jQuery donne plus de travail pour vous.

Impératif → déclaratif

Dans jQuery, les sélecteurs sont utilisés pour trouver des éléments DOM , puis les lier / enregistrer les gestionnaires d'événements. Lorsqu'un événement déclenche, ce code (impératif) s'exécute pour mettre à jour / modifier le DOM.

Dans AngularJS, vous souhaitez réfléchir aux vues plutôt qu'aux éléments DOM. Les vues sont (déclaratives) HTML contenant des directives AngularJS. Les directives ont mis en place les gestionnaires d'événements derrière les scènes pour nous et nous apportent une liaison de données dynamique. Les sélecteurs sont rarement utilisés, de sorte que le besoin d'ID (et de certains types de classes) est fortement diminué. Les vues sont liées aux modèles (via les étendues). Les vues sont une projection du modèle. Les modèles de changement d'événements (c'est-à-dire les données, les propriétés de portée) et les vues qui projettent ces modèles se mettent à jour automatiquement.

Dans AngularJS, pensez à des modèles plutôt qu'à des éléments de DOM sélectionnés par jQuery qui contiennent vos données. Pensez aux vues en tant que projections de ces modèles, plutôt que d'enregistrer des rappels pour manipuler ce que l'utilisateur voit.

Séparation des préoccupations

JQuery emploie un comportement JavaScript discret (JavaScript) est séparé de la structure (HTML).

AngularJS utilise des contrôleurs et des directives (chacun pouvant avoir son propre contrôleur et / ou compilé et reliant des fonctions) pour supprimer le comportement de la vue / structure (HTML). Angular possède également des services et des filtres pour aider à séparer / organiser votre application.

Voir aussi https://stackoverflow.com/a/14346528/215945

Conception d'application

Une approche pour concevoir une application AngularJS:

  1. Pensez à vos modèles. Créez des services ou vos propres objets JavaScript pour ces modèles.
  2. Pensez à la façon dont vous souhaitez présenter vos modèles – vos points de vue. Créez des modèles HTML pour chaque vue, en utilisant les directives nécessaires pour obtenir une liaison de données dynamique.
  3. Attachez un contrôleur à chaque vue (en utilisant ng-view and routing, ou ng-controller). Demandez au contrôleur de trouver / obtenir uniquement les données de modèle que la vue doit faire pour son travail. Faites les contrôleurs aussi minces que possible.

Héritage prototypique

Vous pouvez faire beaucoup avec jQuery sans savoir comment fonctionne l'héritage prototypique JavaScript. Lors du développement d'applications AngularJS, vous éviterez certains pièges courants si vous avez une bonne compréhension de l'héritage JavaScript. Lecture recommandée: Quelles sont les nuances de portée de l'héritage prototypique / prototypique dans AngularJS?

AngularJS vs jQuery

AngularJS et jQuery adoptent des idéologies très différentes. Si vous venez de jQuery, vous pouvez trouver certaines des différences surprenantes. Angular peut vous mettre en colère.

C'est normal, vous devriez passer à travers. Angular en vaut la peine.

La grande différence (TLDR)

JQuery vous propose une boîte à outils pour sélectionner des bits arbitraires du DOM et vous apporter des modifications ad hoc. Vous pouvez faire tout ce que vous voulez, pièce par pièce.

AngularJS vous offre plutôt un compilateur .

Cela signifie que AngularJS lit votre DOM entier de haut en bas et le traite comme code, littéralement comme instructions pour le compilateur. En parcourant le DOM, il recherche des directives spécifiques ( directives du compilateur) qui indiquent au compilateur AngularJS comment se comporter et à faire. Les directives sont de petits objets plein de JavaScript qui peuvent correspondre à des attributs, des tags, des classes ou même des commentaires.

Lorsque le compilateur angulaire détermine qu'une partie du DOM correspond à une directive particulière, elle appelle la fonction directive, en la passant l'élément DOM, les attributs, la portée $ courante (qui est un magasin local) et d'autres bits utiles. Ces attributs peuvent contenir des expressions qui peuvent être interprétées par la directive, et qui lui indiquent comment rendre, et quand il doit se redessiner.

Les directives peuvent ensuite entraîner des composants angulaires supplémentaires tels que les contrôleurs, les services, etc. Ce qui sort du bas du compilateur est une application Web entièrement formée, câblée et prêt à fonctionner.

Cela signifie que Angular est piloté par un modèle . Votre modèle pilote le JavaScript, et non l'inverse. Il s'agit d'un renversement radical des rôles et de l'opposé total du JavaScript discrète que nous avons écrit depuis 10 ans environ. Cela peut prendre du temps à s'habituer.

Si cela semble être trop prescriptif et limitatif, rien ne peut être plus éloigné de la vérité. Parce que AngularJS traite votre code HTML comme code, vous obtenez une granularité de niveau HTML dans votre application Web . Tout est possible, et la plupart des choses sont étonnamment faciles une fois que vous faites quelques sauts conceptuels.

Passons au piège.

D'abord, Angular ne remplace pas jQuery

Angular et jQuery font différentes choses. AngularJS vous offre un ensemble d'outils pour produire des applications Web. JQuery vous fournit principalement des outils pour modifier le DOM. Si jQuery est présent sur votre page, AngularJS l'utilisera automatiquement. Si ce n'est pas le cas, AngularJS est livré avec jQuery Lite, qui est une version réduite mais encore parfaitement utilisable de jQuery.

Misko aime jQuery et ne s'oppose pas à ce que vous l'utilisiez. Cependant, vous constaterez que vous avancez tout au long de votre travail en utilisant une combinaison de portée, de modèles et de directives, et vous devriez préférer ce flux de travail dans la mesure du possible car votre code sera plus discret, plus configurable et plus Angulaire.

Si vous utilisez jQuery, vous ne devriez pas l'arroser partout. L'endroit correct pour la manipulation DOM dans AngularJS est dans une directive. Plus sur ces derniers.

JavaScript discret avec sélecteurs ou modèles déclaratifs

JQuery est généralement appliqué de manière discrète. Votre code JavaScript est lié dans l'en-tête (ou le pied de page), et c'est le seul endroit où il est mentionné. Nous utilisons des sélecteurs pour choisir les bits de la page et écrire des plugins pour modifier ces pièces.

Le JavaScript est en contrôle. Le HTML a une existence complètement indépendante. Votre HTML reste sémantique, même sans JavaScript. Les attributs OnClick sont très mauvais.

Une des premières choses que vous remarquerez à propos d'AngularJS est que les attributs personnalisés sont partout . Votre HTML sera jonché avec des attributs ng, qui sont essentiellement des atoutsClick sur les stéroïdes. Ce sont des directives (directives du compilateur) et sont l'une des principales façons dont le modèle est accroché au modèle.

Lorsque vous le voyez pour la première fois, vous pourriez être tenté d'écrire AngularJS en tant que vieille école intrusive JavaScript (comme je l'ai fait au début). En fait, AngularJS ne joue pas par ces règles. Dans AngularJS, votre HTML5 est un modèle. Il est compilé par AngularJS pour produire votre page Web.

C'est la première grande différence. Pour jQuery, votre page Web est un DOM à manipuler. Pour AngularJS, votre code HTML est un code à compiler. AngularJS lit dans votre page Web entière et le compile littéralement dans une nouvelle page Web en utilisant son compilateur intégré.

Votre modèle doit être déclaratif; Sa signification devrait être claire simplement en la lisant. Nous utilisons des attributs personnalisés avec des noms significatifs. Nous créons de nouveaux éléments HTML, encore une fois avec des noms significatifs. Un concepteur avec une connaissance HTML minimale et aucune compétence de codage peut lire votre modèle AngularJS et comprendre ce qu'il fait. Il ou elle peut apporter des modifications. C'est la voie angulaire.

Le modèle est dans le siège de conduite.

L'une des premières questions que j'ai posées lors du démarrage d'AngularJS et l'exécution des didacticiels est "Où est mon code?" . Je n'ai écrit aucun JavaScript, et pourtant j'ai tout ce comportement. La réponse est évidente. Parce que AngularJS compile le DOM, AngularJS traite votre code HTML comme code. Pour de nombreux cas simples, il suffit souvent d'écrire un modèle et de laisser Compilation d'AngularJS dans une application pour vous.

Votre modèle pilote votre application. Il est traité comme un DSL . Vous écrivez des composants AngularJS, et AngularJS prend soin de les intégrer et de les rendre disponibles au bon moment en fonction de la structure de votre modèle. Ceci est très différent d'un modèle MVC standard, où le modèle est juste pour la sortie.

C'est plus similaire à XSLT que Ruby on Rails, par exemple.

Il s'agit d'une inversion de contrôle radical qui s'habitue.

Arrêtez d'essayer de générer votre application à partir de votre JavaScript. Laissez le modèle conduire l'application, et laissez AngularJS prendre soin de câbler les composants ensemble. C'est aussi la voie angulaire.

HTML sémantique vs modèles sémantiques

Avec jQuery, votre page HTML devrait contenir un contenu sémantique significatif. Si le JavaScript est désactivé (par un utilisateur ou un moteur de recherche), votre contenu reste accessible.

Parce que AngularJS traite votre page HTML en tant que modèle. Le modèle n'est pas censé être sémantique car votre contenu est généralement stocké dans votre modèle qui vient en fin de compte de votre API. AngularJS compile votre DOM avec le modèle pour produire une page Web sémantique.

Votre source HTML n'est plus sémantique, votre API et les DOM compilés sont sémantiques.

Dans AngularJS, ce qui signifie vivre dans le modèle, le HTML n'est qu'un modèle, uniquement pour l'affichage.

À ce stade, vous avez probablement toutes sortes de questions concernant le référencement et l'accessibilité, et à juste titre. Il y a des problèmes ouverts ici. La plupart des lecteurs d'écran vont maintenant analyser JavaScript. Les moteurs de recherche peuvent également indexer le contenu AJAXed . Néanmoins, vous voudrez vous assurer que vous utilisez les URL pushstate et que vous disposez d'un sitemap correct. Consultez ici une discussion sur le problème: https://stackoverflow.com/a/23245379/687677

Séparation des préoccupations (SOC) vs MVC

La séparation des préoccupations (SOC) est un modèle qui a grandi pendant de nombreuses années de développement web pour diverses raisons, y compris le référencement, l'accessibilité et l'incompatibilité du navigateur. Cela ressemble à ceci:

  1. HTML – Signification sémantique. Le HTML devrait rester seul.
  2. CSS – Styling, sans le CSS, la page est encore lisible.
  3. JavaScript – Comportement, sans le script, le contenu reste.

Encore une fois, AngularJS ne joue pas selon ses règles. D'un coup, AngularJS élimine une décennie de sagesse reçue et met plutôt en œuvre un modèle MVC dans lequel le modèle n'est plus sémantique, même pas un peu.

Cela ressemble à ceci:

  1. Modèle – vos modèles contiennent vos données sémantiques. Les modèles sont généralement des objets JSON . Les modèles existent comme attributs d'un objet appelé $ scope. Vous pouvez également stocker des fonctions utilitaires pratiques sur $ dont vos modèles peuvent alors accéder.
  2. Vue – Vos vues sont écrites en HTML. La vue n'est généralement pas sémantique car vos données existent dans le modèle.
  3. Contrôleur – Votre contrôleur est une fonction JavaScript qui accroche la vue au modèle. Sa fonction est d'initialiser $ scope. Selon votre application, vous pouvez ou non avoir besoin de créer un contrôleur. Vous pouvez avoir plusieurs contrôleurs sur une page.

MVC et SOC ne sont pas sur les extrémités opposées de la même échelle, ils sont sur des axes complètement différents. SOC n'a aucun sens dans un contexte AngularJS. Vous devez l'oublier et continuer.

Si, comme moi, vous avez vécu les guerres des navigateurs, vous pourriez trouver cette idée très offensante. Survolez-le, cela en valait la peine, je le promets.

Plugins vs. directives

Les plugins étendent jQuery. Les directives AngularJS étendent les fonctionnalités de votre navigateur.

Dans jQuery, nous définissons des plugins en ajoutant des fonctions au jQuery.prototype. Nous les attachons ensuite au DOM en sélectionnant des éléments et en appelant le plugin sur le résultat. L'idée est d'étendre les capacités de jQuery.

Par exemple, si vous voulez un carrousel sur votre page, vous pouvez définir une liste désordonnée de figures, peut-être enveloppée dans un élément de navigation. Vous pouvez ensuite écrire quelques jQuery pour sélectionner la liste sur la page et la restructurer en tant que galerie avec timeouts pour faire l'animation coulissante.

Dans AngularJS, nous définissons des directives. Une directive est une fonction qui renvoie un objet JSON. Cet objet indique à AngularJS quels éléments DOM à rechercher, et ce qui les modifie. Directives are hooked in to the template using either attributes or elements, which you invent. The idea is to extend the capabilities of HTML with new attributes and elements.

The AngularJS way is to extend the capabilities of native looking HTML. You should write HTML that looks like HTML, extended with custom attributes and elements.

If you want a carousel, just use a <carousel /> element, then define a directive to pull in a template, and make that sucker work.

Lots of small directives vs. big plugins with configuration switches

The tendency with jQuery is to write great big plugins like lightbox which we then configure by passing in numerous values and options.

This is a mistake in AngularJS.

Take the example of a dropdown. When writing a dropdown plugin you might be tempted to code in click handlers, perhaps a function to add in a chevron which is either up or down, perhaps change the class of the unfolded element, show hide the menu, all helpful stuff.

Until you want to make a small change.

Say you have a menu that you want to unfold on hover. Well now we have a problem. Our plugin has wired in our click handler for us, we're going to need to add a configuration option to make it behave differently in this specific case.

In AngularJS we write smaller directives. Our dropdown directive would be ridiculously small. It might maintain the folded state, and provide methods to fold(), unfold() or toggle(). These methods would simply update $scope.menu.visible which is a boolean holding the state.

Now in our template we can wire this up:

 <a ng-click="toggle()">Menu</a> <ul ng-show="menu.visible"> ... </ul> 

Need to update on mouseover?

 <a ng-mouseenter="unfold()" ng-mouseleave="fold()">Menu</a> <ul ng-show="menu.visible"> ... </ul> 

The template drives the application so we get HTML level granularity. If we want to make case by case exceptions, the template makes this easy.

Closure vs. $scope

JQuery plugins are created in a closure. Privacy is maintained within that closure. It's up to you to maintain your scope chain within that closure. You only really have access to the set of DOM nodes passed in to the plugin by jQuery, plus any local variables defined in the closure and any globals you have defined. This means that plugins are quite self contained. This is a good thing, but can get restrictive when creating a whole application. Trying to pass data between sections of a dynamic page becomes a chore.

AngularJS has $scope objects. These are special objects created and maintained by AngularJS in which you store your model. Certain directives will spawn a new $scope, which by default inherits from its wrapping $scope using JavaScript prototypical inheritance. The $scope object is accessible in the controller and the view.

This is the clever part. Because the structure of $scope inheritance roughly follows the structure of the DOM, elements have access to their own scope, and any containing scopes seamlessly, all the way up to the global $scope (which is not the same as the global scope).

This makes it much easier to pass data around, and to store data at an appropriate level. If a dropdown is unfolded, only the dropdown $scope needs to know about it. If the user updates their preferences, you might want to update the global $scope, and any nested scopes listening to the user preferences would automatically be alerted.

This might sound complicated, in fact, once you relax into it, it's like flying. You don't need to create the $scope object, AngularJS instantiates and configures it for you, correctly and appropriately based on your template hierarchy. AngularJS then makes it available to your component using the magic of dependency injection (more on this later).

Manual DOM changes vs. Data Binding

In jQuery you make all your DOM changes by hand. You construct new DOM elements programatically. If you have a JSON array and you want to put it to the DOM, you must write a function to generate the HTML and insert it.

In AngularJS you can do this too, but you are encouraged to make use of data binding. Change your model, and because the DOM is bound to it via a template your DOM will automatically update, no intervention required.

Because data binding is done from the template, using either an attribute or the curly brace syntax, it's super easy to do. There's little cognitive overhead associated with it so you'll find yourself doing it all the time.

 <input ng-model="user.name" /> 

Binds the input element to $scope.user.name . Updating the input will update the value in your current scope, and vice-versa.

Likewise:

 <p> {{user.name}} </p> 

will output the user name in a paragraph. It's a live binding, so if the $scope.user.name value is updated, the template will update too.

Ajax all of the time

In jQuery making an Ajax call is fairly simple, but it's still something you might think twice about. There's the added complexity to think about, and a fair chunk of script to maintain.

In AngularJS, Ajax is your default go-to solution and it happens all the time, almost without you noticing. You can include templates with ng-include. You can apply a template with the simplest custom directive. You can wrap an Ajax call in a service and create yourself a GitHub service, or a Flickr service, which you can access with astonishing ease.

Service Objects vs Helper Functions

In jQuery, if we want to accomplish a small non-dom related task such as pulling a feed from an API, we might write a little function to do that in our closure. That's a valid solution, but what if we want to access that feed often? What if we want to reuse that code in another application?

AngularJS gives us service objects.

Services are simple objects that contain functions and data. They are always singletons, meaning there can never be more than one of them. Say we want to access the Stack Overflow API, we might write a StackOverflowService which defines methods for doing so.

Let's say we have a shopping cart. We might define a ShoppingCartService which maintains our cart and contains methods for adding and removing items. Because the service is a singleton, and is shared by all other components, any object that needs to can write to the shopping cart and pull data from it. It's always the same cart.

Service objects are self-contained AngularJS components which we can use and reuse as we see fit. They are simple JSON objects containing functions and Data. They are always singletons, so if you store data on a service in one place, you can get that data out somewhere else just by requesting the same service.

Dependency injection (DI) vs. Instatiation – aka de-spaghettification

AngularJS manages your dependencies for you. If you want an object, simply refer to it and AngularJS will get it for you.

Until you start to use this, it's hard to explain just what a massive time boon this is. Nothing like AngularJS DI exists inside jQuery.

DI means that instead of writing your application and wiring it together, you instead define a library of components, each identified by a string.

Say I have a component called 'FlickrService' which defines methods for pulling JSON feeds from Flickr. Now, if I want to write a controller that can access Flickr, I just need to refer to the 'FlickrService' by name when I declare the controller. AngularJS will take care of instantiating the component and making it available to my controller.

For example, here I define a service:

 myApp.service('FlickrService', function() { return { getFeed: function() { // do something here } } }); 

Now when I want to use that service I just refer to it by name like this:

 myApp.controller('myController', ['FlickrService', function(FlickrService) { FlickrService.getFeed() }]); 

AngularJS will recognise that a FlickrService object is needed to instantiate the controller, and will provide one for us.

This makes wiring things together very easy, and pretty much eliminates any tendency towards spagettification. We have a flat list of components, and AngularJS hands them to us one by one as and when we need them.

Modular service architecture

jQuery says very little about how you should organise your code. AngularJS has opinions.

AngularJS gives you modules into which you can place your code. If you're writing a script that talks to Flickr for example, you might want to create a Flickr module to wrap all your Flickr related functions in. Modules can include other modules (DI). Your main application is usually a module, and this should include all the other modules your application will depend on.

You get simple code reuse, if you want to write another application based on Flickr, you can just include the Flickr module and voila, you have access to all your Flickr related functions in your new application.

Modules contain AngularJS components. When we include a module, all the components in that module become available to us as a simple list identified by their unique strings . We can then inject those components into each other using AngularJS's dependency injection mechanism.

To sum up

AngularJS and jQuery are not enemies. It's possible to use jQuery within AngularJS very nicely. If you're using AngularJS well (templates, data-binding, $scope, directives, etc.) you will find you need a lot less jQuery than you might otherwise require.

The main thing to realise is that your template drives your application. Stop trying to write big plugins that do everything. Instead write little directives that do one thing, then write a simple template to wire them together.

Think less about unobtrusive JavaScript, and instead think in terms of HTML extensions.

My little book

I got so excited about AngularJS, I wrote a short book on it which you're very welcome to read online http://nicholasjohnson.com/angular-book/ . I hope it's helpful.

Pouvez-vous décrire le changement de paradigme nécessaire?

Imperative vs Declarative

With jQuery you tell the DOM what needs to happen, step by step. With AngularJS you describe what results you want but not how to do it. More on this here . Also, check out Mark Rajcok's answer.

How do I architect and design client-side web apps differently?

AngularJS is an entire client-side framework that uses the MVC pattern (check out their graphical representation ). It greatly focuses on separation of concerns.

Quelle est la plus grande différence? Que dois-je arrêter de faire / utiliser? what should I start doing/using instead?

jQuery is a library

AngularJS is a beautiful client-side framework, highly testable, that combines tons of cool stuff such as MVC, dependency injection , data binding and much more.

It focuses on separation of concerns and testing ( unit testing and end-to-end testing), which facilitates test-driven development.

The best way to start is going through their awesome tutorial . You can go through the steps in a couple of hours; however, in case you want to master the concepts behind the scenes, they include a myriad of reference for further reading.

Existe-t-il des considérations / restrictions côté serveur?

You may use it on existing applications where you are already using pure jQuery. However, if you want to fully take advantage of the AngularJS features you may consider coding the server side using a RESTful approach.

Doing so will allow you to leverage their resource factory , which creates an abstraction of your server side RESTful API and makes server-side calls (get, save, delete, etc.) incredibly easy.

To describe the "paradigm shift", I think a short answer can suffice.

AngularJS changes the way you find elements

In jQuery , you typically use selectors to find elements, and then wire them up:
$('#id .class').click(doStuff);

In AngularJS , you use directives to mark the elements directly, to wire them up:
<a ng-click="doStuff()">

AngularJS doesn't need (or want) you to find elements using selectors – the primary difference between AngularJS's jqLite versus full-blown jQuery is that jqLite does not support selectors .

So when people say "don't include jQuery at all", it's mainly because they don't want you to use selectors; they want you to learn to use directives instead. Direct, not select!

jQuery

jQuery makes ridiculously long JavaScript commands like getElementByHerpDerp shorter and cross-browser.

AngularJS

AngularJS allows you to make your own HTML tags/attributes that do things which work well with dynamic web applications (since HTML was designed for static pages).

Modifier:

Saying "I have a jQuery background how do I think in AngularJS?" is like saying "I have an HTML background how do I think in JavaScript?" The fact that you're asking the question shows you most likely don't understand the fundamental purposes of these two resources. This is why I chose to answer the question by simply pointing out the fundamental difference rather than going through the list saying "AngularJS makes use of directives whereas jQuery uses CSS selectors to make a jQuery object which does this and that etc….". This question does not require a lengthy answer.

jQuery is a way to make programming JavaScript in the browser easier. Shorter, cross-browser commands, etc.

AngularJS extends HTML, so you don't have to put <div> all over the place just to make an application. It makes HTML actually work for applications rather than what it was designed for, which is static, educational web pages. It accomplishes this in a roundabout way using JavaScript, but fundamentally it is an extension of HTML, not JavaScript.

jQuery: you think a lot about 'QUERYing the DOM ' for DOM elements and doing something.

AngularJS: THE model is the truth, and you always think from that ANGLE.

For example, when you get data from THE server which you intend to display in some format in the DOM, in jQuery, you need to '1. FIND' where in the DOM you want to place this data, the '2. UPDATE/APPEND' it there by creating a new node or just setting its innerHTML . Then when you want to update this view, you then '3. FIND' the location and '4. UPDATE'. This cycle of find and update all done within the same context of getting and formatting data from server is gone in AngularJS.

With AngularJS you have your model (JavaScript objects you are already used to) and the value of the model tells you about the model (obviously) and about the view, and an operation on the model automatically propagates to the view, so you don't have to think about it. You will find yourself in AngularJS no longer finding things in the DOM.

To put in another way, in jQuery, you need to think about CSS selectors, that is, where is the div or td that has a class or attribute, etc., so that I can get their HTML or color or value, but in AngularJS, you will find yourself thinking like this: what model am I dealing with, I will set the model's value to true. You are not bothering yourself of whether the view reflecting this value is a checked box or resides in a td element (details you would have often needed to think about in jQuery).

And with DOM manipulation in AngularJS, you find yourself adding directives and filters, which you can think of as valid HTML extensions.

One more thing you will experience in AngularJS: in jQuery you call the jQuery functions a lot, in AngularJS, AngularJS will call your functions, so AngularJS will 'tell you how to do things', but the benefits are worth it, so learning AngularJS usually means learning what AngularJS wants or the way AngularJS requires that you present your functions and it will call it accordingly. This is one of the things that makes AngularJS a framework rather than a library.

jQuery is a DOM manipulation library.

AngularJS is an MV* framework.

In fact, AngularJS is one of the few JavaScript MV* frameworks (many JavaScript MVC tools still fall under the category library).

Being a framework, it hosts your code and takes ownership of decisions about what to call and when!

AngularJS itself includes a jQuery-lite edition within it. So for some basic DOM selection/manipulation, you really don't have to include the jQuery library (it saves many bytes to run on the network.)

AngularJS has the concept of "Directives" for DOM manipulation and designing reusable UI components, so you should use it whenever you feel the need of doing DOM manipulation related stuff (directives are only place where you should write jQuery code while using AngularJS).

AngularJS involves some learning curve (more than jQuery :-).

–>For any developer coming from jQuery background, my first advice would be to "learn JavaScript as a first class language before jumping onto a rich framework like AngularJS!" I learned the above fact the hard way.

Bonne chance.

Those are some very nice, but lengthy answers.

To sum up my experiences:

  1. Controllers and providers (services, factories, etc.) are for modifying the data model, NOT HTML.
  2. HTML and directives define the layout and binding to the model.
  3. If you need to share data between controllers, create a service or factory – they are singletons that are shared across the application.
  4. If you need an HTML widget, create a directive.
  5. If you have some data and are now trying to update HTML… STOP! update the model, and make sure your HTML is bound to the model.

They're apples and oranges. You don't want to compare them. They're two different things. AngularJs has already jQuery lite built in which allows you to perform basic DOM manipulation without even including the full blown jQuery version.

jQuery is all about DOM manipulation. It solves all the cross browser pain otherwise you will have to deal with but it's not a framework that allows you to divide your app into components like AngularJS.

A nice thing about AngularJs is that it allows you to separate/isolate the DOM manipulation in the directives. There are built-in directives ready for you to use such as ng-click. You can create your own custom directives that will contain all your view logic or DOM manipulation so you don't end up mingle DOM manipulation code in the controllers or services that should take care of the business logic.

Angular breaks down your app into – Controllers – Services – Views – etc.

and there is one more thing, that's the directive. It's an attribute you can attach to any DOM element and you can go nuts with jQuery within it without worrying about your jQuery ever conflicts with AngularJs components or messes up with its architecture.

I heard from a meetup I attended, one of the founders of Angular said they worked really hard to separate out the DOM manipulation so do not try to include them back in.

Listen to the podcast JavaScript Jabber: Episode #32 that features the original creators of AngularJS: Misko Hevery & Igor Minar. They talk a lot about what it's like to come to AngularJS from other JavaScript backgrounds, especially jQuery.

One of the points made in the podcast made a lot of things click for me with respects to your question:

MISKO : […] one of the things we thought about very hardly in Angular is, how do we provide lots of escape hatches so that you can get out and basically figure out a way out of this. So to us, the answer is this thing called “Directives”. And with directives, you essentially become a regular little jQuery JavaScript, you can do whatever you want.

IGOR : So think of directive as the instruction to the compiler that tells it whenever you come across this certain element or this CSS in the template, and you keep this kind of code and that code is in charge of the element and everything below that element in the DOM tree.

A transcript of the entire episode is available at the link provided above.

So, to directly answer your question: AngularJS is -very- opinionated and is a true MV* framework. However, you can still do all of the really cool stuff you know and love with jQuery inside of directives. It's not a matter of "How do I do what I used to in jQuery?" as much as it's a matter of "How do I supplement AngularJS with all of the stuff I used to do in jQuery?"

It's really two very different states of mind.

I find this question interesting, because my first serious exposure to JavaScript programming was Node.js and AngularJS. I never learned jQuery, and I guess that's a good thing, because I don't have to unlearn anything. In fact, I actively avoid jQuery solutions to my problems, and instead, solely look for an "AngularJS way" to solve them. So, I guess my answer to this question would essentially boil down to, "think like someone who never learned jQuery" and avoid any temptation to incorporate jQuery directly (obviously AngularJS uses it to some extent behind the scenes).

AngularJS and jQuery:

AngularJs and JQuery are completely different at every level except the JQLite functionality and you will see it once you start learning the AngularJs core features (I explained it below).

AngularJs is a client side framework that offers to build the independent client side application. JQuery is a client side library that play around the DOM.

AngularJs Cool Principle – If you want some changes on your UI think from model data change perspective. Change your data and UI will re-render itself. You need not to play around DOM each time unless and until it is hardly required and that should also be handled through Angular Directives.

To answer this question, I want to share my experience on the first enterprise application with AngularJS. These are the most awesome features that Angular provide where we start changing our jQuery mindset and we get the Angular like a framework and not the library.

Two-way data binding is amazing: I had a grid with all functionality UPDATE, DELTE, INSERT. I have a data object that binds the grid's model using ng-repeat. You only need to write a single line of simple JavaScript code for delete and insert and that's it. grid automatically updates as the grid model changes instantly. Update functionality is real time, no code for it. You feel amazing!!!

Reusable directives are super: Write directives in one place and use it throughout the application. OMG!!! I used these directive for paging, regex, validations, etc. It is really cool!

Routing is strong: It's up to your implementation how you want to use it, but it requires very few lines of code to route the request to specify HTML and controller (JavaScript)

Controllers are great: Controllers take care of their own HTML, but this separation works well for common functionality well as. If you want to call the same function on the click of a button on master HTML, just write the same function name in each controller and write individual code.

Plugins: There are many other similar features like showing an overlay in your app. You don't need to write code for it, just use an overlay plugin available as wc-overlay, and this will automatically take care of all XMLHttpRequest (XHR) requests.

Ideal for RESTful architecture: Being a complete frameworks makes AngularJS great to work with a RESTful architecture. To call REST CRUD APIs is very easier and

Services : Write common codes using services and less code in controllers. Sevices can be used to share common functionalities among the controllers.

Extensibility : Angular has extended the HTML directives using angular directives. Write expressions inside html and evaluate them on runtime. Create your own directives and services and use them in another project without any extra effort.

As a JavaScript MV* beginner and purely focusing on the application architecture (not the server/client-side matters), I would certainly recommend the following resource (which I am surprised wasn't mentioned yet): JavaScript Design Patterns , by Addy Osmani, as an introduction to different JavaScript Design Patterns . The terms used in this answer are taken from the linked document above. I'm not going to repeat what was worded really well in the accepted answer. Instead, this answer links back to the theoretical backgrounds which power AngularJS (and other libraries).

Like me, you will quickly realize that AngularJS (or Ember.js , Durandal, & other MV* frameworks for that matter) is one complex framework assembling many of the different JavaScript design patterns.

I found it easier also, to test (1) native JavaScript code and (2) smaller libraries for each one of these patterns separately before diving into one global framework. This allowed me to better understand which crucial issues a framework adresses (because you are personally faced with the problem).

Par exemple:

  • JavaScript Object-oriented Programming (this is a Google search link). It is not a library, but certainly a prerequisite to any application programming. It taught me the native implementations of the prototype, constructor, singleton & decorator patterns
  • jQuery / Underscore for the facade pattern (like WYSIWYG's for manipulating the DOM)
  • Prototype.js for the prototype/ constructor/ mixin pattern
  • RequireJS / Curl.js for the module pattern/ AMD
  • KnockoutJS for the observable, publish/subscribe pattern

NB: This list is not complete, nor 'the best libraries'; they just happen to be the libraries I used. These libraries also include more patterns, the ones mentioned are just their main focuses or original intents. If you feel something is missing from this list, please do mention it in the comments, and I will be glad to add it.

Actually, if you're using AngularJS, you don't need jQuery anymore. AngularJS itself has the binding and directive, which is a very good "replacement" for most things you can do with jQuery.

I usually develop mobile applications using AngularJS and Cordova . The ONLY thing from jQuery I needed is the Selector.

By googling, I see that there is a standalone jQuery selector module out there. It's Sizzle.

And I decided to make a tiny code snippet that help me quickly start a website using AngularJS with the power of jQuery Selector (using Sizzle).

I shared my code here: https://github.com/huytd/Sizzular