From 6fc9761395297fcd7daab69307d64e1644ff3ef0 Mon Sep 17 00:00:00 2001 From: ericdouglas Date: Sun, 26 Oct 2014 14:15:02 -0200 Subject: [PATCH 001/567] translating intro updates --- i18n/PT-BR.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/i18n/PT-BR.md b/i18n/PT-BR.md index 7693b8c3..64fda36c 100644 --- a/i18n/PT-BR.md +++ b/i18n/PT-BR.md @@ -2,9 +2,9 @@ *Guia de Estilo Opinativo para times sobre AngularJS por [@john_papa](//twitter.com/john_papa)* -*Translation by [Eric Douglas](https://github.com/ericdouglas) and [Ciro Nunes](https://github.com/cironunes)* +*Traduzido por [Eric Douglas](https://github.com/ericdouglas) e [Ciro Nunes](https://github.com/cironunes)* ->The [original English version](http://jpapa.me/ngstyles) is the source of truth, as it is maintained and updated first. +>A [versão original em inglês](http://jpapa.me/ngstyles) é a *fonte da verdade*, por ser mantida e atualizada primeiro. Se você procura por um guia de estilo opinativo para sintaxe, convenções e estruturação de aplicações AngularJS, então siga em frente! Estes estilos são baseados em minha experiência com desenvolvimento [AngularJS](//angularjs.org), apresentações, [cursos de treinamento na Plurasight](http://pluralsight.com/training/Authors/Details/john-papa) e trabalho em times. From 862b4e7778182e73b8ce3f267b8cea2078495f09 Mon Sep 17 00:00:00 2001 From: natee Date: Thu, 30 Oct 2014 18:12:55 +0800 Subject: [PATCH 002/567] up to date --- i18n/zh-CN.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/i18n/zh-CN.md b/i18n/zh-CN.md index bf0020dc..4d876f99 100644 --- a/i18n/zh-CN.md +++ b/i18n/zh-CN.md @@ -2,9 +2,9 @@ *AngularJS风格指南[@john_papa](//twitter.com/john_papa)* -*Translation by [kerncink](https://github.com/natee)* +*翻译出自[kerncink](https://github.com/natee)* ->The [original English version](http://jpapa.me/ngstyles) is the source of truth, as it is maintained and updated first. +>[原始英文版本](http://jpapa.me/ngstyles)将会在第一时间维护和更新,翻译版本的更新将会在这之后。 如果你正在寻找一些关于语法、约定和结构化的AngularJS应用的一个有建设性的风格指南,这个正适合你。这里所包含的风格是基于我用[AngularJS](//angularjs.org)、演讲、[Pluralsight培训课程](http://pluralsight.com/training/Authors/Details/john-papa)并且在团队中运用的一些经验。 @@ -248,7 +248,7 @@ /* avoid */ angular .module('app') - .controller('Dashboard', function() { }); + .controller('Dashboard', function() { }) .factory('logger', function() { }); ``` From e58475284ed37530fb77b548ba7e22f499c78d47 Mon Sep 17 00:00:00 2001 From: natee Date: Mon, 3 Nov 2014 19:02:20 +0800 Subject: [PATCH 003/567] fix content and transitions --- i18n/zh-CN.md | 42 ++++++++++++++++++++++-------------------- 1 file changed, 22 insertions(+), 20 deletions(-) diff --git a/i18n/zh-CN.md b/i18n/zh-CN.md index 4d876f99..73188063 100644 --- a/i18n/zh-CN.md +++ b/i18n/zh-CN.md @@ -2,18 +2,18 @@ *AngularJS风格指南[@john_papa](//twitter.com/john_papa)* -*翻译出自[kerncink](https://github.com/natee)* +*由[kerncink](https://github.com/natee)翻译* >[原始英文版本](http://jpapa.me/ngstyles)将会在第一时间维护和更新,翻译版本的更新将会在这之后。 -如果你正在寻找一些关于语法、约定和结构化的AngularJS应用的一个有建设性的风格指南,这个正适合你。这里所包含的风格是基于我用[AngularJS](//angularjs.org)、演讲、[Pluralsight培训课程](http://pluralsight.com/training/Authors/Details/john-papa)并且在团队中运用的一些经验。 +如果你正在寻找一些关于语法、约定和结构化的AngularJS应用的一个有建设性的风格指南,这个repo正适合你。这里所包含的风格是基于我在团队中使用[AngularJS](//angularjs.org)的一些经验、一些演讲和[Pluralsight培训课程](http://pluralsight.com/training/Authors/Details/john-papa)。 ->如果你喜欢这个指南,在Pluralsight上check out我的[AngularJS Patterns: Clean Code](http://jpapa.me/ngclean)。 +>如果你喜欢这个指南,请在Pluralsight上检出我的[AngularJS Patterns: Clean Code](http://jpapa.me/ngclean)。 -这个风格指南的目的是通过展示我用到的约定给构建AngularJS应用提供指导,更加重要的是,我为什么要选择它们。 +这个风格指南的目的是为构建AngularJS应用提供指导,当然更加重要的是让大家知道我为什么要选择它们。 ## Community Awesomeness and Credit -我发现AngularJS社区是一个热衷于分享经验的令人难以置信的社区,因此,我的一个朋友、AngularJS专家Todd Motto和我合作了多种风格和惯例。我们同意其中的大多数,但是也有一些分歧。我鼓励你去看看[Todd的指引](https://github.com/toddmotto/angularjs-styleguide),从其中了解他的做法和它们是如何比较的。 +我发现AngularJS社区是一个热衷于分享经验的令人难以置信的社区,尽管Todd Motto(他是我的一个朋友,也是AngularJS专家)和我合作了多种风格和惯例,但是我们也存在着一些分歧。我鼓励你去看看[Todd的指南](https://github.com/toddmotto/angularjs-styleguide),从其中了解他的做法和它们是如何比较的。 我的许多风格都是从大量的程序会话[Ward Bell](http://twitter.com/wardbell)和我所拥有的而来的,虽然我们并不总是能达成一致,但是Ward确实影响了本指南的最终演变。 @@ -31,12 +31,12 @@ 1. [Factories](#factories) 1. [Data Services](#data-services) 1. [Directives](#directives) - 1. [解决Controller的Promises](#解决Controller的Promises) + 1. [解决Controller的Promises](#解决controller的promises) 1. [手动依赖注入](#手动依赖注入) 1. [压缩和注释](#压缩和注释) 1. [异常处理](#异常处理) 1. [命名](#命名) - 1. [应用程序结构LIFT原则](#应用程序结构LIFT原则) + 1. [应用程序结构LIFT原则](#应用程序结构lift原则) 1. [应用程序结构](#应用程序结构) 1. [模块化](#模块化) 1. [启动逻辑](#启动逻辑) @@ -47,7 +47,7 @@ 1. [JSHint](#js-hint) 1. [常量](#常量) 1. [文件模板和片段](#文件模板和片段) - 1. [AngularJS文档](#AngularJS文档) + 1. [AngularJS文档](#angularjs文档) 1. [贡献](#贡献) 1. [许可](#许可) @@ -57,7 +57,7 @@ - 一个文件只定义一个组件。 - 下面的一个例子在同一个文件中定义了一个`app`的module和它的一些依赖,定义了一个controller,一个factory。 + 下面的一个例子在同一个文件中定义了一个`app`的module和它的一些依赖、一个controller和一个factory。 ```javascript /* avoid */ @@ -71,7 +71,7 @@ function someFactory() { } ``` - 现在相同的组件被分割成单独的文件。 + 现在把相同的组件分割成单独的文件。 ```javascript /* recommended */ @@ -181,7 +181,7 @@ - 不使用任何一个使用了setter语法的变量来定义modules。 - *为什么?*: 在一个文件只有一个组件的条件下,很少有需要为一个模块引入一个变量。 + *为什么?*:在一个文件只有一个组件的条件下,很少有需要为一个模块引入一个变量。 ```javascript /* avoid */ @@ -497,7 +497,7 @@ ``` 注意这里重要的代码分散在前面的例子中。 - 下面的示例中,可以看到重要的代码都放到了顶部。实现的详细细节都在下方,这样的代码当然是更易读的。 + 下面的示例中,可以看到重要的代码都放到了顶部。实现的详细细节都在下方,显然这样的代码更易读。 ```javascript /* @@ -534,7 +534,7 @@ *为什么?*:把逻辑放到service中,并通过一个function暴露,就可以被多个controller重用。 - *为什么?*:把逻辑放到service中将会使单元测试的时候更加容易地把它们分离,相反,如果在controller中调用逻辑只会让这变得被别人嘲笑。 + *为什么?*:把逻辑放到service中将会使单元测试的时候更加容易地把它们分离,相反,如果在controller中调用逻辑就显得很二了。 *为什么?*:从controller中删除依赖关系并且隐藏实现细节。 @@ -679,7 +679,7 @@ - facotry是一个单例,它返回一个包含service成员的对象。 - 注意:[所有的AngularJS services都是单例](https://docs.angularjs.org/guide/services),这意味着每个injector都只有一个实例化的service。 + 注:[所有的AngularJS services都是单例](https://docs.angularjs.org/guide/services),这意味着每个injector都只有一个实例化的service。 ###可访问的成员放到顶部### @@ -962,7 +962,7 @@ ###一个文件限制一个 - - 在一个文件中只创建一个directive,并依照directive来命名文件。 + - 一个文件中只创建一个directive,并依照directive来命名文件。 *为什么?*:把所有directive放到一个文件中很容易,但是当一些directive是跨应用的,一些是跨模块的,一些仅仅在一个模块中使用时,想把它们独立出来是非常困难的。 @@ -1046,7 +1046,7 @@ } ``` - 注意:directive有很多命名选项,特别是从它们能够在一个狭隘的或者广泛的作用域中使用时,选择一个让directive和文件都清楚分明的名字。下面有一些例子,不过更多的建议去看命名章节。 + 注:directive有很多命名选项,特别是从它们能够在一个狭隘的或者广泛的作用域中使用时,选择一个让directive和文件都清楚分明的名字。下面有一些例子,不过更多的建议去看命名章节。 ###限制DOM操作 @@ -1131,6 +1131,8 @@ 注意:下面的directive演示了一些你可以在link和directivedirective控制器中使用scope的方法,用controllerAs。这里把template放在行内是为了在一个地方写出这些代码。 + 注意:关于依赖注入的内容,请看[手动依赖注入](#手动依赖注入)。 + ```html
``` @@ -1283,7 +1285,7 @@ } ``` - 注意:示例代码中的`movieService`不是安全压缩的做法,可以到[依赖注入](#依赖注入)和[压缩和注释](#压缩和注释)部分学习如何安全压缩。 + 注意:示例代码中的`movieService`不是安全压缩的做法,可以到[手动依赖注入](#手动依赖注入)和[压缩和注释](#压缩和注释)部分学习如何安全压缩。 **[返回顶部](#目录)** @@ -2079,11 +2081,11 @@ } ``` -### 运行块 +### 运行代码块 - - 任何在应用程序启动时需要运行的代码都应该在factory中声明,通过一个function暴露出来,然后注入到[运行块](https://docs.angularjs.org/guide/module#module-loading-dependencies)。 + - 任何在应用程序启动时需要运行的代码都应该在factory中声明,通过一个function暴露出来,然后注入到[运行代码块](https://docs.angularjs.org/guide/module#module-loading-dependencies)中。 - *为什么?*:直接在运行块处写代码将会使得测试变得很困难,相反,如果放到facotry则会使的抽象和模拟变得很简单。 + *为什么?*:直接在运行代码块处写代码将会使得测试变得很困难,相反,如果放到facotry则会使的抽象和模拟变得很简单。 ```javascript angular From 5b2c8ca1257cd9a697f515f0f3882c59543fc27a Mon Sep 17 00:00:00 2001 From: Aleksandar Bogatinov Date: Fri, 7 Nov 2014 21:07:05 +0100 Subject: [PATCH 004/567] Changed name to proper locale name --- i18n/{mk_MK.md => mk-MK.md} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename i18n/{mk_MK.md => mk-MK.md} (100%) diff --git a/i18n/mk_MK.md b/i18n/mk-MK.md similarity index 100% rename from i18n/mk_MK.md rename to i18n/mk-MK.md From ab8ffd9950d5d824d1e8f399c6be0be538c24734 Mon Sep 17 00:00:00 2001 From: Dan Mindru Date: Tue, 11 Nov 2014 22:48:53 +0100 Subject: [PATCH 005/567] Update README.md Made more sense to me like this! :) --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 4ba26e03..4f7ecf41 100644 --- a/README.md +++ b/README.md @@ -2460,8 +2460,8 @@ Open an issue first to discuss potential changes/additions. If you have question ### Process 1. Discuss the changes in an Issue. - 1. Open a Pull Request, reference the issue, and explain the change and why it adds value. - 1. The Pull Request will be evaluated and either merged or declined. + 2. Open a Pull Request, reference the issue, and explain the change and why it adds value. + 3. The Pull Request will be evaluated and either merged or declined. ## License From b3bdeb5b231ff1c7ca62e0bb469a195add9f888d Mon Sep 17 00:00:00 2001 From: jlcarvalho Date: Fri, 14 Nov 2014 19:40:17 -0200 Subject: [PATCH 006/567] Update PT-BR.md --- i18n/PT-BR.md | 87 ++++++++++++++++++++++++++------------------------- 1 file changed, 44 insertions(+), 43 deletions(-) diff --git a/i18n/PT-BR.md b/i18n/PT-BR.md index e843a4e5..4c2dfe5c 100644 --- a/i18n/PT-BR.md +++ b/i18n/PT-BR.md @@ -2,7 +2,7 @@ *Guia de Estilo opinativo de AngularJS para times. Por [@john_papa](//twitter.com/john_papa)* -*Traduzido por [Eric Douglas](https://github.com/ericdouglas) e [Ciro Nunes](https://github.com/cironunes)* +*Traduzido por [Eric Douglas](https://github.com/ericdouglas), [Ciro Nunes](https://github.com/cironunes) e [Jean Lucas de Carvalho](https://github.com/jlcarvalho)* >The [original English version](http://jpapa.me/ngstyles) is the source of truth, as it is maintained and updated first. @@ -292,9 +292,9 @@ ou *Definindo* vs *Obtendo* - Utilize a sintaxe [`controllerAs`](http://www.johnpapa.net/do-you-like-your-angular-controllers-with-or-without-sugar/) ao invés da sintaxe `clássica controller com $scope`. - *Why?*: Controllers are constructed, "newed" up, and provide a single new instance, and the `controllerAs` syntax is closer to that of a JavaScript constructor than the `classic $scope syntax`. + **Por que?**: Controllers são construídos, "iniciados", e fornecem um nova instância única, e a sintaxe `controlerAs` é mais próxima de um construtor JavaScriptar do que a `sintaxe clássica do $scope`. - *Why?*: It promotes the use of binding to a "dotted" object in the View (e.g. `customer.name` instead of `name`), which is more contextual, easier to read, and avoids any reference issues that may occur without "dotting". + **Por que?**: Isso promove o uso do binding de um objeto "pontuado", ou seja, com propriedades na View (ex. `customer.name` ao invés de `name`), que é mais contextual, legível, e evita qualquer problema com referências que podem ocorrer sem a "pontuação" **Por que?**: Ajuda a evitar o uso de chamadas ao `$parent` nas Views com controllers aninhados. @@ -368,7 +368,7 @@ ou *Definindo* vs *Obtendo* var vm = this; ``` - Note: When creating watches in a controller using `controller as`, you can watch the `vm.*` member using the following syntax. (Create watches with caution as they add more load to the digest cycle.) + Nota: Quando watches são criados no controller utilizando o `controller as`, você pode observar o objeto `vm.*` utilizando a seguinte sintaxe. (Crie watches com cuidado pois eles deixam o ciclo de digest mais "carregado".) ```javascript $scope.$watch('vm.title', function(current, original) { @@ -379,14 +379,14 @@ ou *Definindo* vs *Obtendo* ### Bindable Members Up Top - - Place bindable members at the top of the controller, alphabetized, and not spread through the controller code. + - Coloque os objetos que precisam de bind no início do controller, em ordem alfabética, e não espalhados através do código do controller. - *Why?*: Placing bindable members at the top makes it easy to read and helps you instantly identify which members of the controller can be bound and used in the View. + **Por que?**: Colocar os objetos que precisam de bind no início torna mais fácil de ler e te ajuda a instantaneamente identificar quais objetos do controller podem ser utilizados na View. - *Why?*: Setting anonymous functions in-line can be easy, but when those functions are more than 1 line of code they can reduce the readability. Defining the functions below the bindable members (the functions will be hoisted) moves the implementation details down, keeps the bindable members up top, and makes it easier to read. + **Por que?**: Setar funções anônimas pode ser fácil, mas quando essas funções possuem mais de 1 linha do código elas podem dificultar a legibilidade. Definindo as funções abaixo dos objetos que necessitam de bind as funções serão elevedas pelo JavaScript Hoisting move os detalhes de implementação para o final do controller, mantém os objetos que necessitam de bind no topo, e deixa o código mais fácil de se ler. ```javascript - /* avoid */ + /* evite */ function Sessions() { var vm = this; @@ -404,7 +404,7 @@ ou *Definindo* vs *Obtendo* ``` ```javascript - /* recommended */ + /* recomendado */ function Sessions() { var vm = this; @@ -431,21 +431,22 @@ ou *Definindo* vs *Obtendo* ![Controller Using "Above the Fold"](https://raw.githubusercontent.com/johnpapa/angularjs-styleguide/master/assets/above-the-fold-1.png) - Note: If the function is a 1 liner consider keeping it right up top, as long as readability is not affected. + Nota: Se a função possuir apenas 1 linha considere matê-la no topo, desde que a legibilidade não seja afetada. ```javascript - /* avoid */ + /* evite */ function Sessions(data) { var vm = this; vm.gotoSession = gotoSession; vm.refresh = function() { /** - * lines - * of - * code - * affects - * readability + * linhas + * de + * código + * afetam + * a + * legibilidade */ }; vm.search = search; @@ -454,12 +455,12 @@ ou *Definindo* vs *Obtendo* ``` ```javascript - /* recommended */ + /* recomendado */ function Sessions(dataservice) { var vm = this; vm.gotoSession = gotoSession; - vm.refresh = dataservice.refresh; // 1 liner is OK + vm.refresh = dataservice.refresh; // 1 linha está OK vm.search = search; vm.sessions = []; vm.title = 'Sessions'; @@ -467,22 +468,22 @@ ou *Definindo* vs *Obtendo* ### Function Declarations to Hide Implementation Details - - Use function declarations to hide implementation details. Keep your bindable members up top. When you need to bind a function in a controller, point it to a function declaration that appears later in the file. This is tied directly to the section Bindable Members Up Top. For more details see [this post](http://www.johnpapa.net/angular-function-declarations-function-expressions-and-readable-code). + - Utilize declarações de funções para esconder detalhes de implementação. Mantenha seus objetos que necessitam de bind no topo. Quando você precisar de fazer o bind de uma função no controller, aponte ela para a declaração de função que aparece no final do arquivo. Ela está ligada diretamente aos objetos que precisam de bind no início do arquivo. Para mais detalhes veja [este post](http://www.johnpapa.net/angular-function-declarations-function-expressions-and-readable-code). - *Why?*: Placing bindable members at the top makes it easy to read and helps you instantly identify which members of the controller can be bound and used in the View. (Same as above.) + **Por que?**: Colocar os objetos que precisam de bind no início torna mais fácil de ler e te ajuda a instantaneamente identificar quais objetos do controller podem ser utilizados na View. (Mesmo do item anterior.) - *Why?*: Placing the implementation details of a function later in the file moves that complexity out of view so you can see the important stuff up top. + **Por que?**: Colocar os detalhes de implementação de uma função no final do arquivo coloca a complexidade fora do foco, logo, você pode focar nas coisas importantes no topo. - *Why?*: Function declaration are hoisted so there are no concerns over using a function before it is defined (as there would be with function expressions). + **Por que?**: Declarações de funções são içadas, logo, não existe problema de se utilizar uma função antes dela ser definida (como haveria com expressões de função). - *Why?*: You never have to worry with function declarations that moving `var a` before `var b` will break your code because `a` depends on `b`. + **Por que?**: Você nunca precisará se preocupar com declarações de funções quebrarem seu código por colocar `var a` antes de `var b` por que `a` depende de `b`. - *Why?*: Order is critical with function expressions + **Por que?**: A ordenação é crítica em expressões de função. ```javascript /** - * avoid - * Using function expressions. + * evite + * Usar expressões de funções. */ function Avengers(dataservice, logger) { var vm = this; @@ -508,13 +509,13 @@ ou *Definindo* vs *Obtendo* } ``` - Notice that the important stuff is scattered in the preceding example. In the example below, notice that the important stuff is up top. For example, the members bound to the controller such as `vm.avengers` and `vm.title`. The implementation details are down below. This is just easier to read. + Note-se que as coisas importantes estão espalhadas no exemplo anterior. No exemplo abaixo, nota-se que as coisas importantes do javascript estão logo no topo. Por exemplo, os objetos que precisam de bind no controller como `vm.avengers` e `vm.title`. Os detalhes de implementação estão abaixo. Isto é mais fácil de ler. ```javascript /* - * recommend - * Using function declarations - * and bindable members up top. + * recomendado + * Usar declarações de funções + * e objetos que precisam de bind no topo. */ function Avengers(dataservice, logger) { var vm = this; @@ -541,16 +542,16 @@ ou *Definindo* vs *Obtendo* ### Defer Controller Logic - - Defer logic in a controller by delegating to services and factories. + - Remova a lógica do controller delegando ela a services e factories. - *Why?*: Logic may be reused by multiple controllers when placed within a service and exposed via a function. + **Por que?**: A lógica pode ser reutilizada em múltiplos controllers quando colocada em um service e exposta através de uma função. - *Why?*: Logic in a service can more easily be isolated in a unit test, while the calling logic in the controller can be easily mocked. + **Por que?**: A lógica em um serviço pode ser mais facilmente isolada em um teste unitário, enquanto in a service can more easily be isolated in a unit test, enquanto a lógica feita no controlador pode ser facilmente [mockada](http://www.thoughtworks.com/pt/insights/blog/mockists-are-dead-long-live-classicists). - *Why?*: Removes dependencies and hides implementation details from the controller. + **Por que?**: Remove as dependências e esconde os detalhes de implementação do controlador. ```javascript - /* avoid */ + /* evite */ function Order($http, $q) { var vm = this; vm.checkCredit = checkCredit; @@ -567,7 +568,7 @@ ou *Definindo* vs *Obtendo* ``` ```javascript - /* recommended */ + /* recomendado */ function Order(creditService) { var vm = this; vm.checkCredit = checkCredit; @@ -581,20 +582,20 @@ ou *Definindo* vs *Obtendo* ### Keep Controllers Focused - - Define a controller for a view, and try not to reuse the controller for other views. Instead, move reusable logic to factories and keep the controller simple and focused on its view. + - Defina um controller para a view, e tente não reutilizar o controller para outras views. Ao invés disso, coloque as lógicas reaproveitáveis em factories e mantenha o controller simples e focado em sua view. - *Why?*: Reusing controllers with several views is brittle and good end to end (e2e) test coverage is required to ensure stability across large applications. + **Por que?**: Reutilizar controllers em várias views é arriscado e um boa cobertura de testes end to end (e2e) é obrigatório para se garantir estabilidade em grandes aplicações. ### Assigning Controllers - - When a controller must be paired with a view and either component may be re-used by other controllers or views, define controllers along with their routes. + - Quando um controller deve ser pareado com sua view e algum componente pode ser reutilizado por outros controllers ou views, defina controladores juntamente de suas rotas. - Note: If a View is loaded via another means besides a route, then use the `ng-controller="Avengers as vm"` syntax. + Nota: Se uma View é carregada de outra forma que não seja através de uma rota, então utilize a sintaxe `ng-controller="Avengers as vm"`. - *Why?*: Pairing the controller in the route allows different routes to invoke different pairs of controllers and views. When controllers are assigned in the view using [`ng-controller`](https://docs.angularjs.org/api/ng/directive/ngController), that view is always associated with the same controller. + **Por que?**: Parear os controllers nas rotas permite diferentes rotas invocarem diferentes pares de controllers e views. Quando um controller é utilizado na view usando a sintaxe [`ng-controller`](https://docs.angularjs.org/api/ng/directive/ngController), esta view sempre será associada ao mesmo controller. ```javascript - /* avoid - when using with a route and dynamic pairing is desired */ + /* evite - quando utilizar com uma rota e emparelhamento dinâmico é desejado */ // route-config.js angular @@ -616,7 +617,7 @@ ou *Definindo* vs *Obtendo* ``` ```javascript - /* recommended */ + /* recomendado */ // route-config.js angular From 94a4b88379243c7eeecd9bfc9db8221de8a66e66 Mon Sep 17 00:00:00 2001 From: Spencer Handley Date: Sat, 15 Nov 2014 12:52:39 -0800 Subject: [PATCH 007/567] README - Fixed Typo I noticed a typo in the 'Function Declarations to Hide Implementation Details' Portion. I changed acessible to accessible. Nothing else was altered. Thanks so much for this amazing guide! --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 4ba26e03..d2b38734 100644 --- a/README.md +++ b/README.md @@ -736,7 +736,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see ### Function Declarations to Hide Implementation Details - - Use function declarations to hide implementation details. Keep your acessible members of the factory up top. Point those to function declarations that appears later in the file. For more details see [this post](http://www.johnpapa.net/angular-function-declarations-function-expressions-and-readable-code). + - Use function declarations to hide implementation details. Keep your accessible members of the factory up top. Point those to function declarations that appears later in the file. For more details see [this post](http://www.johnpapa.net/angular-function-declarations-function-expressions-and-readable-code). *Why?*: Placing accessible members at the top makes it easy to read and helps you instantly identify which functions of the factory you can access externally. From 79f22b7eca278c94f28928b5c500aaf59708bb41 Mon Sep 17 00:00:00 2001 From: John Papa Date: Sun, 16 Nov 2014 16:17:43 -0500 Subject: [PATCH 008/567] closes #121 . directive injection was unreachable. must be before the return --- README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 4ba26e03..3d206f53 100644 --- a/README.md +++ b/README.md @@ -1153,9 +1153,11 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see controller : ExampleController, controllerAs: 'vm' }; + + ExampleController.$inject = ['$scope']; + return directive; - ExampleController.$inject = ['$scope']; function ExampleController($scope) { // Injecting $scope just for comparison /* jshint validthis:true */ From 2427cc503463e0d73e6236147be078fc3b6e076d Mon Sep 17 00:00:00 2001 From: angelochiello Date: Mon, 17 Nov 2014 08:46:46 +0100 Subject: [PATCH 009/567] Update it-IT.md PR #116 --- i18n/it-IT.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/i18n/it-IT.md b/i18n/it-IT.md index 7b0128af..7e0f36fd 100644 --- a/i18n/it-IT.md +++ b/i18n/it-IT.md @@ -2473,8 +2473,8 @@ Apri prima una "issue" per discutere potenziali cambiamenti/aggiunte. Se hai del ### Processo 1. Discuti i cambiamenti in un Issue. - 1. Apri una Pull Request, fai riferimento all issue e spiega i cambiamenti e perché questi aggiungono valore. - 1. La Pull Request sarà vagliata e quindi fatto un merge o declinata. + 2. Apri una Pull Request, fai riferimento all issue e spiega i cambiamenti e perché questi aggiungono valore. + 3. La Pull Request sarà vagliata e quindi fatto un merge o declinata. ## Licenza From dded16a929680c25c99874edc410e7053c7fe30e Mon Sep 17 00:00:00 2001 From: Vinicius Sabadim Fernandes Date: Mon, 17 Nov 2014 14:13:37 -0200 Subject: [PATCH 010/567] Fix on topic 'Bindable Members Up Top' --- i18n/PT-BR.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/i18n/PT-BR.md b/i18n/PT-BR.md index 4c2dfe5c..7c96cb4f 100644 --- a/i18n/PT-BR.md +++ b/i18n/PT-BR.md @@ -383,7 +383,7 @@ ou *Definindo* vs *Obtendo* **Por que?**: Colocar os objetos que precisam de bind no início torna mais fácil de ler e te ajuda a instantaneamente identificar quais objetos do controller podem ser utilizados na View. - **Por que?**: Setar funções anônimas pode ser fácil, mas quando essas funções possuem mais de 1 linha do código elas podem dificultar a legibilidade. Definindo as funções abaixo dos objetos que necessitam de bind as funções serão elevedas pelo JavaScript Hoisting move os detalhes de implementação para o final do controller, mantém os objetos que necessitam de bind no topo, e deixa o código mais fácil de se ler. + **Por que?**: Setar funções anônimas pode ser fácil, mas quando essas funções possuem mais de 1 linha do código elas podem dificultar a legibilidade. Definindo as funções abaixo dos objetos que necessitam de bind (as funções serão elevadas pelo JavaScript Hoisting) move os detalhes de implementação para o final do controller, mantém os objetos que necessitam de bind no topo, e deixa o código mais fácil de se ler. ```javascript /* evite */ From 83c2a5beff4c13c786f65b3435941ab8081df15a Mon Sep 17 00:00:00 2001 From: Vinicius Sabadim Fernandes Date: Mon, 17 Nov 2014 14:20:03 -0200 Subject: [PATCH 011/567] Fix on topic 'Function Declarations to Hide Implementation Details' --- i18n/PT-BR.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/i18n/PT-BR.md b/i18n/PT-BR.md index 4c2dfe5c..a1881889 100644 --- a/i18n/PT-BR.md +++ b/i18n/PT-BR.md @@ -468,7 +468,7 @@ ou *Definindo* vs *Obtendo* ### Function Declarations to Hide Implementation Details - - Utilize declarações de funções para esconder detalhes de implementação. Mantenha seus objetos que necessitam de bind no topo. Quando você precisar de fazer o bind de uma função no controller, aponte ela para a declaração de função que aparece no final do arquivo. Ela está ligada diretamente aos objetos que precisam de bind no início do arquivo. Para mais detalhes veja [este post](http://www.johnpapa.net/angular-function-declarations-function-expressions-and-readable-code). + - Utilize declarações de funções para esconder detalhes de implementação. Mantenha seus objetos que necessitam de bind no topo. Quando você precisar fazer o bind de uma função no controller, aponte ela para a declaração de função que aparece no final do arquivo. Ela está ligada diretamente aos objetos que precisam de bind no início do arquivo. Para mais detalhes veja [este post](http://www.johnpapa.net/angular-function-declarations-function-expressions-and-readable-code). **Por que?**: Colocar os objetos que precisam de bind no início torna mais fácil de ler e te ajuda a instantaneamente identificar quais objetos do controller podem ser utilizados na View. (Mesmo do item anterior.) From d482bd47a1679f9074af566ce51ec7ffcc661094 Mon Sep 17 00:00:00 2001 From: Vinicius Sabadim Fernandes Date: Mon, 17 Nov 2014 14:23:07 -0200 Subject: [PATCH 012/567] Fix on topic 'Defer Controller Logic' --- i18n/PT-BR.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/i18n/PT-BR.md b/i18n/PT-BR.md index 4c2dfe5c..5e5e85de 100644 --- a/i18n/PT-BR.md +++ b/i18n/PT-BR.md @@ -546,7 +546,7 @@ ou *Definindo* vs *Obtendo* **Por que?**: A lógica pode ser reutilizada em múltiplos controllers quando colocada em um service e exposta através de uma função. - **Por que?**: A lógica em um serviço pode ser mais facilmente isolada em um teste unitário, enquanto in a service can more easily be isolated in a unit test, enquanto a lógica feita no controlador pode ser facilmente [mockada](http://www.thoughtworks.com/pt/insights/blog/mockists-are-dead-long-live-classicists). + **Por que?**: A lógica em um serviço pode ser mais facilmente isolada em um teste unitário, enquanto a lógica feita no controlador pode ser facilmente [mockada](http://www.thoughtworks.com/pt/insights/blog/mockists-are-dead-long-live-classicists). **Por que?**: Remove as dependências e esconde os detalhes de implementação do controlador. From a7840e531e04a3cfa20157b389e656d60030c588 Mon Sep 17 00:00:00 2001 From: Vinicius Sabadim Fernandes Date: Mon, 17 Nov 2014 14:40:09 -0200 Subject: [PATCH 013/567] Translate for the topic 'Services' --- i18n/PT-BR.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/i18n/PT-BR.md b/i18n/PT-BR.md index 4c2dfe5c..a5fd8da3 100644 --- a/i18n/PT-BR.md +++ b/i18n/PT-BR.md @@ -646,9 +646,9 @@ ou *Definindo* vs *Obtendo* ### Singletons - - Services are instantiated with the `new` keyword, use `this` for public methods and variables. Since these are so similar to factories, use a factory instead for consistency. + - Services são instanciados com a palavra-chave `new`, use `this` para métodos públicos e variáveis. Services são bastante similares a factories, use um factory para consistência. - Note: [All AngularJS services are singletons](https://docs.angularjs.org/guide/services). This means that there is only one instance of a given service per injector. + Nota: [Todos services em AngularJS são singletons](https://docs.angularjs.org/guide/services). Isso significa que há apenas uma instância do serviço para cada injetor. ```javascript // service From 28e0fd788665a7375c1a53851e36461b87ce2a7a Mon Sep 17 00:00:00 2001 From: natee Date: Tue, 18 Nov 2014 17:25:45 +0800 Subject: [PATCH 014/567] sync change --- i18n/zh-CN.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/i18n/zh-CN.md b/i18n/zh-CN.md index 73188063..51896247 100644 --- a/i18n/zh-CN.md +++ b/i18n/zh-CN.md @@ -1153,9 +1153,10 @@ controller : ExampleController, controllerAs: 'vm' }; + + ExampleController.$inject = ['$scope']; return directive; - ExampleController.$inject = ['$scope']; function ExampleController($scope) { // Injecting $scope just for comparison /* jshint validthis:true */ @@ -2442,8 +2443,8 @@ ###过程 1. 在一个Issue中讨论这个问题。 - 1. 打开一个pull request,引用这个问题,解释你做的修改和为什么要这样做。 - 1. pull request将会被进行评估,结果就是合并或是拒绝。 + 2. 打开一个pull request,引用这个问题,解释你做的修改和为什么要这样做。 + 3. pull request将会被进行评估,结果就是合并或是拒绝。 ## 许可证 From 845df83c1779e496e06941daafc1af1ca8c7a9e0 Mon Sep 17 00:00:00 2001 From: Vinicius Sabadim Fernandes Date: Tue, 18 Nov 2014 15:23:40 -0200 Subject: [PATCH 015/567] Translate for the topic 'Factories' (PT-BR) --- i18n/PT-BR.md | 66 +++++++++++++++++++++++++++------------------------ 1 file changed, 35 insertions(+), 31 deletions(-) diff --git a/i18n/PT-BR.md b/i18n/PT-BR.md index 3a300757..ce106234 100644 --- a/i18n/PT-BR.md +++ b/i18n/PT-BR.md @@ -681,29 +681,32 @@ ou *Definindo* vs *Obtendo* **[⬆ De volta ao topo ⬆](#tabela-de-conte%C3%BAdo)** ## Factories +ou *Fábricas* ### Single Responsibility +ou *Responsabilidade Única* - - Factories should have a [single responsibility](http://en.wikipedia.org/wiki/Single_responsibility_principle), that is encapsulated by its context. Once a factory begins to exceed that singular purpose, a new factory should be created. + - Factories devem ter [responsabilidade única](http://en.wikipedia.org/wiki/Single_responsibility_principle), que é encapsulado pelo seu contexto. Assim que uma factory começa a exceder a proposta de singularidade, uma nova factory deve ser criada. ### Singletons - - Factories are singletons and return an object that contains the members of the service. + - Factories são singletons e retornam um objeto que contém os membros do serviço. - Note: [All AngularJS services are singletons](https://docs.angularjs.org/guide/services). + Nota: [Todos services em AngularJS são singletons](https://docs.angularjs.org/guide/services). ### Accessible Members Up Top +ou *Membros acessíveis no topo* - - Expose the callable members of the service (it's interface) at the top, using a technique derived from the [Revealing Module Pattern](http://addyosmani.com/resources/essentialjsdesignpatterns/book/#revealingmodulepatternjavascript). + - Exponha os membros que podem ser invocados no serviço (a interface) no topo, utilizando uma técnica derivada do [Revealing Module Pattern](http://addyosmani.com/resources/essentialjsdesignpatterns/book/#revealingmodulepatternjavascript). - *Why?*: Placing the callable members at the top makes it easy to read and helps you instantly identify which members of the service can be called and must be unit tested (and/or mocked). + **Por que?**: Colocando no topo os membros que podem ser invocados da factory, a leitura torna-se mais fácil e ajuda a identificar imediatamente quais membros da factory podem ser invocados e testados através de teste unitário (e/ou mock). - *Why?*: This is especially helpful when the file gets longer as it helps avoid the need to scroll to see what is exposed. + **Por que?**: É especialmente útil quando o arquivo torna-se muito longo e ajuda a evitar a necessidade de rolagem para ver o que é exposto. - *Why?*: Setting functions as you go can be easy, but when those functions are more than 1 line of code they can reduce the readability and cause more scrolling. Defining the callable interface via the returned service moves the implementation details down, keeps the callable interface up top, and makes it easier to read. + **Por que?**: Definir as funções conforme você escreve o código pode ser fácil, mas quando essas funções tem mais que 1 linha de código, elas podem reduzir a leitura e causar rolagem. Definir a interface no topo do que pode ser invocado da factory, torna a leitura mais fácil e mantém os detalhes de implementação mais abaixo. ```javascript - /* avoid */ + /* evite */ function dataService() { var someValue = ''; function save() { @@ -722,7 +725,7 @@ ou *Definindo* vs *Obtendo* ``` ```javascript - /* recommended */ + /* recomendado */ function dataService() { var someValue = ''; var service = { @@ -744,51 +747,52 @@ ou *Definindo* vs *Obtendo* } ``` - This way bindings are mirrored across the host object, primitive values cannot update alone using the revealing module pattern + Dessa forma, os bindings são espelhados através do objeto da interface da factory e os valores primitivos não podem ser atualizados sozinhos utilizando o revealing module pattern ![Factories Using "Above the Fold"](https://raw.githubusercontent.com/johnpapa/angularjs-styleguide/master/assets/above-the-fold-2.png) ### Function Declarations to Hide Implementation Details +ou *Declarações de função para esconder detalhes de implementação* - - Use function declarations to hide implementation details. Keep your acessible members of the factory up top. Point those to function declarations that appears later in the file. For more details see [this post](http://www.johnpapa.net/angular-function-declarations-function-expressions-and-readable-code). + - Use function declarations (declarações de função) para esconder detalhes de implementação. Mantenha os membros acessíveis da factory no topo. Aponte as function declarations que aparecem posteriormente no arquivo. Para mais detalhes leia [esse post](http://www.johnpapa.net/angular-function-declarations-function-expressions-and-readable-code). - *Why?*: Placing accessible members at the top makes it easy to read and helps you instantly identify which functions of the factory you can access externally. + **Por que?**: Colocando os membros acessíveis no topo, a leitura torna-se mais fácil e ajuda a identificar imediatamente quais membros da factory podem ser acessados externamente. - *Why?*: Placing the implementation details of a function later in the file moves that complexity out of view so you can see the important stuff up top. + **Por que?**: Colocando os detalhes de implementação da função posteriormente no arquivo move a complexidade para fora da visão, permitindo que você veja as coisas mais importantes no topo. - *Why?*: Function declaration are hoisted so there are no concerns over using a function before it is defined (as there would be with function expressions). + **Por que?**: Function declarations (declarações de função) são içadas (hoisted) para que não hajam preocupações em utilizar uma função antes que ela seja definida (como haveria com function expressions (expressões de função)). - *Why?*: You never have to worry with function declarations that moving `var a` before `var b` will break your code because `a` depends on `b`. + **Por que?**: Você nunca deve se preocupar com function declaration (declarações de função) onde `var a` está antes de `var b` vai ou não quebrar o seu código porque `a` depende de `b`. - *Why?*: Order is critical with function expressions + **Por que?**: A ordem é crítica com function expressions (expressões de função) ```javascript /** - * avoid - * Using function expressions + * evite + * Utilizando function expressions (expressões de função) */ function dataservice($http, $location, $q, exception, logger) { var isPrimed = false; var primePromise; var getAvengers = function() { - // implementation details go here + // detalhes de implementação }; var getAvengerCount = function() { - // implementation details go here + // detalhes de implementação }; var getAvengersCast = function() { - // implementation details go here + // detalhes de implementação }; var prime = function() { - // implementation details go here + // detalhes de implementação }; var ready = function(nextPromises) { - // implementation details go here + // detalhes de implementação }; var service = { @@ -804,9 +808,9 @@ ou *Definindo* vs *Obtendo* ```javascript /** - * recommended - * Using function declarations - * and accessible members up top. + * recomendado + * Utilizando function declarations (declarações de função) + * e membros acessíveis no topo. */ function dataservice($http, $location, $q, exception, logger) { var isPrimed = false; @@ -824,23 +828,23 @@ ou *Definindo* vs *Obtendo* //////////// function getAvengers() { - // implementation details go here + // detalhes de implementação } function getAvengerCount() { - // implementation details go here + // detalhes de implementação } function getAvengersCast() { - // implementation details go here + // detalhes de implementação } function prime() { - // implementation details go here + // detalhes de implementação } function ready(nextPromises) { - // implementation details go here + // detalhes de implementação } } ``` From 00d6332de789a9da4463dfba7dd18f3b3622df1c Mon Sep 17 00:00:00 2001 From: Vinicius Sabadim Fernandes Date: Wed, 19 Nov 2014 10:40:19 -0200 Subject: [PATCH 016/567] Translate for the topic 'Data services' (PT-BR) --- i18n/PT-BR.md | 47 +++++++++++++++++++++++++---------------------- 1 file changed, 25 insertions(+), 22 deletions(-) diff --git a/i18n/PT-BR.md b/i18n/PT-BR.md index ce106234..c13185eb 100644 --- a/i18n/PT-BR.md +++ b/i18n/PT-BR.md @@ -852,21 +852,23 @@ ou *Declarações de função para esconder detalhes de implementação* **[⬆ De volta ao topo ⬆](#tabela-de-conte%C3%BAdo)** ## Data Services +ou *Serviços de dados* ### Separate Data Calls +ou *Chamadas de dados separadas* - - Refactor logic for making data operations and interacting with data to a factory. Make data services responsible for XHR calls, local storage, stashing in memory, or any other data operations. + - A lógica de refatoração (refactor) para operações com dados e interação com dados na factory. Faça serviços de dados responsáveis por chamadas XHR, armazenamento local (local storage), armazenamento em memória (stashing) ou outras operações com dados. - *Why?*: The controller's responsibility is for the presentation and gathering of information for the view. It should not care how it gets the data, just that it knows who to ask for it. Separating the data services moves the logic on how to get it to the data service, and lets the controller be simpler and more focused on the view. + **Por que?**: A responsabilidade dos controladores (controllers) é para a apresentação e coleta de informações da view. Eles não devem se importar como os dados são adquiridos, somente como "perguntar" por eles. Separar os serviços de dados (data services), move a lógica de como adquiri-los para o serviço e deixa o controlador (controller) mais simples e focado na view. - *Why?*: This makes it easier to test (mock or real) the data calls when testing a controller that uses a data service. + **Por que?**: Isso torna mais fácil testar (mock ou real) as chamadas de dados quando estiver testando um controlador (controller) que utiliza um serviço de dados (data service). - *Why?*: Data service implementation may have very specific code to handle the data repository. This may include headers, how to talk to the data, or other services such as $http. Separating the logic into a data service encapsulates this logic in a single place hiding the implementation from the outside consumers (perhaps a controller), also making it easier to change the implementation. + **Por que?**: A implementação de um serviço de dados (data service) pode ter um código bem específico para lidar com o repositório de dados. Isso pode incluir cabeçalhos (headers), como comunicar com os dados ou outros serviços, como $http. Separando a lógica de dados em um serviço, coloca toda a lógica somente em um local e esconde a implementação de consumidores de fora (talvez um controlador (controller)), tornado mais fácil mudar a implementação. ```javascript - /* recommended */ + /* recomendado */ - // dataservice factory + // factory de serviço de dados (data service factory) angular .module('app.core') .factory('dataservice', dataservice); @@ -894,12 +896,12 @@ ou *Declarações de função para esconder detalhes de implementação* } ``` - Note: The data service is called from consumers, such as a controller, hiding the implementation from the consumers, as shown below. + Nota: O serviço de dados (data service) é chamado pelos consumidores, como um controlador (controller), escondendo a implementação dos consumidores, como mostrado abaixo. ```javascript - /* recommended */ + /* recomendado */ - // controller calling the dataservice factory + // controlador chamando uma factory de serviço de dados angular .module('app.avengers') .controller('Avengers', Avengers); @@ -929,26 +931,27 @@ ou *Declarações de função para esconder detalhes de implementação* ``` ### Return a Promise from Data Calls +ou *Retorne uma promessa de chamadas de dados* - - When calling a data service that returns a promise such as $http, return a promise in your calling function too. + - Quando chamar um serviço de dados (data service) que retorna uma promessa (promise), como o $http, retorne uma promessa (promise) na função que está chamando também. - *Why?*: You can chain the promises together and take further action after the data call completes and resolves or rejects the promise. + **Por que?**: Você pode encandear as promessas (promises) juntas e definir ações após a promessa (promise) da chamada do dado ser completada, resolvendo ou rejeitando a promessa (promise). ```javascript - /* recommended */ + /* recomendado */ activate(); function activate() { /** - * Step 1 - * Ask the getAvengers function for the - * avenger data and wait for the promise + * Passo 1 + * Chame a função getAvengers para os dados + * dos vingadores (avengers) e espere pela promessa (promise) */ return getAvengers().then(function() { /** - * Step 4 - * Perform an action on resolve of final promise + * Passo 4 + * Faça uma ação resolvendo a promessa (promise) finalizada */ logger.info('Activated Avengers View'); }); @@ -956,15 +959,15 @@ ou *Declarações de função para esconder detalhes de implementação* function getAvengers() { /** - * Step 2 - * Ask the data service for the data and wait - * for the promise + * Passo 2 + * Chame o serviço de dados (data service) e espere + * pela promessa (promise) */ return dataservice.getAvengers() .then(function(data) { /** - * Step 3 - * set the data and resolve the promise + * Passo 3 + * Atribua os dados e resolva a promessa (promise) */ vm.avengers = data; return vm.avengers; From 4b231d35e4cf6df3446a0d07a3c6aa2625ed22cd Mon Sep 17 00:00:00 2001 From: Lucivaldo Costa Date: Fri, 21 Nov 2014 00:11:52 -0200 Subject: [PATCH 017/567] Update PT-BR.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Correção de acentuação e outros detalhes. --- i18n/PT-BR.md | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/i18n/PT-BR.md b/i18n/PT-BR.md index c13185eb..5a029998 100644 --- a/i18n/PT-BR.md +++ b/i18n/PT-BR.md @@ -5,8 +5,9 @@ *Traduzido por [Eric Douglas](https://github.com/ericdouglas), [Ciro Nunes](https://github.com/cironunes) e [Jean Lucas de Carvalho](https://github.com/jlcarvalho)* >The [original English version](http://jpapa.me/ngstyles) is the source of truth, as it is maintained and updated first. +>A [versão original em inglês](http://jpapa.me/ngstyles) é a fonte da verdade, já que é corrigida e atualizada primeiro. -Se você procura por um guia de estilo opinativo para sintaxe, convenções e estruturação de aplicações AngularJS, então siga em frente! Estes estilos são baseados em minha experiência com desenvolvimento com [AngularJS](//angularjs.org), apresentações, [cursos de treinamento na Plurasight](http://pluralsight.com/training/Authors/Details/john-papa) e trabalhando em equipes. +Se você procura por um guia de estilo opinativo para sintaxe, convenções e estruturação de aplicações AngularJS, então siga em frente! Estes estilos são baseados em minha experiência com desenvolvimento com [AngularJS](//angularjs.org), apresentações, [cursos de treinamento na Pluralsight](http://pluralsight.com/training/Authors/Details/john-papa) e trabalhando em equipes. > Se você gostar deste estilo, confira meu curso [AngularJS Patterns: Clean Code](http://jpapa.me/ngclean) na Plurasight. @@ -24,7 +25,7 @@ Embora este guia explique o **o quê**, **porque** e **como**, acho útil ver tu > **Nota de tradução**: Os títulos originais de cada seção será mantido, pois caso você queira buscar mais sobre estes assuntos futuramente, fazendo tal busca em inglês será obtido um resultado **imensamente** melhor. > -> Após o titúlo, estará a tradução auxiliar, quando necessária, visto que alguns termos são mais facilmente entendidos quando não traduzidos, por fazerem parte do núcleo do estudo em questão. +> Após o título, estará a tradução auxiliar, quando necessária, visto que alguns termos são mais facilmente entendidos quando não traduzidos, por fazerem parte do núcleo do estudo em questão. > > Para eventuais erros de digitação e/ou tradução, favor enviar um pull-request! @@ -173,7 +174,7 @@ ou *Responsabilidade Única* - **Nota**: Apenas para agilizar, o resto dos exemplos neste guia omitirão a sintaxe IIFE. - - **Nota**: IIFE impede que códigos de teste alcancem membros privados como expressões regulares ou funções auxiliares que são frequentemente boas para testes unitários. Entretanto você pode testá-las através de membros acessíveis ou expondo-os pelo próprio componente. Por exemplo, colocando funções auxiliares, expressões regulares ou constantes em sua própria *factory* ou constante. + - **Nota**: IIFE impede que códigos de teste alcancem membros privados como expressões regulares ou funções auxiliares que são frequentemente boas para testes unitários. Entretanto, você pode testá-las através de membros acessíveis ou expondo-os pelo próprio componente. Por exemplo, colocando funções auxiliares, expressões regulares ou constantes em sua própria *factory* ou constante. **[⬆ De volta ao topo ⬆](#tabela-de-conte%C3%BAdo)** @@ -188,7 +189,7 @@ ou Módulos ### Definições (*aka Setters*) -> ps: **aka** é o acrônimo de **A**lso **Know** **A**s, de forma traduzida, **também conhecido como**. +> ps: **aka** é o acrônimo de **A**lso **K**nown** **A**s, de forma traduzida, **também conhecido como**. - Declare os módulos sem uma variável usando a sintaxe *setter*. @@ -383,7 +384,7 @@ ou *Definindo* vs *Obtendo* **Por que?**: Colocar os objetos que precisam de bind no início torna mais fácil de ler e te ajuda a instantaneamente identificar quais objetos do controller podem ser utilizados na View. - **Por que?**: Setar funções anônimas pode ser fácil, mas quando essas funções possuem mais de 1 linha do código elas podem dificultar a legibilidade. Definindo as funções abaixo dos objetos que necessitam de bind (as funções serão elevadas pelo JavaScript Hoisting) move os detalhes de implementação para o final do controller, mantém os objetos que necessitam de bind no topo, e deixa o código mais fácil de se ler. + **Por que?**: Setar funções anônimas pode ser fácil, mas quando essas funções possuem mais de 1 linha do código elas podem dificultar a legibilidade. Definir as funções abaixo dos objetos que necessitam de bind (as funções serão elevadas pelo JavaScript Hoisting) move os detalhes de implementação para o final do controller, mantém os objetos que necessitam de bind no topo, e deixa o código mais fácil de se ler. ```javascript /* evite */ @@ -588,7 +589,7 @@ ou *Definindo* vs *Obtendo* ### Assigning Controllers - - Quando um controller deve ser pareado com sua view e algum componente pode ser reutilizado por outros controllers ou views, defina controladores juntamente de suas rotas. + - Quando um controller deve ser pareado com sua view e algum componente pode ser reutilizado por outros controllers ou views, defina controllers juntamente de suas rotas. Nota: Se uma View é carregada de outra forma que não seja através de uma rota, então utilize a sintaxe `ng-controller="Avengers as vm"`. From 95ecf08b9b72ebe3cfbb2c5a22ec8a783b084714 Mon Sep 17 00:00:00 2001 From: John Papa Date: Thu, 20 Nov 2014 22:01:17 -0500 Subject: [PATCH 018/567] removed validthis as controllers do not need it if they are uppercased --- README.md | 9 --------- 1 file changed, 9 deletions(-) diff --git a/README.md b/README.md index 78bf3b92..009f8b66 100644 --- a/README.md +++ b/README.md @@ -348,13 +348,6 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see } ``` - Note: You can avoid any [jshint](http://www.jshint.com/) warnings by placing the comment below above the line of code. - - ```javascript - /* jshint validthis: true */ - var vm = this; - ``` - Note: When creating watches in a controller using `controller as`, you can watch the `vm.*` member using the following syntax. (Create watches with caution as they add more load to the digest cycle.) ```javascript @@ -1160,7 +1153,6 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see function ExampleController($scope) { // Injecting $scope just for comparison - /* jshint validthis:true */ var vm = this; vm.min = 3; @@ -1283,7 +1275,6 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see Avengers.$inject = ['moviesPrepService']; function Avengers(moviesPrepService) { - /* jshint validthis:true */ var vm = this; vm.movies = moviesPrepService.movies; } From 3919bc29d9ddaff70fb40c57c863f140a4db9ff2 Mon Sep 17 00:00:00 2001 From: John Papa Date: Thu, 20 Nov 2014 22:03:04 -0500 Subject: [PATCH 019/567] removed validthis as controllers do not need it if they are uppercased --- README.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/README.md b/README.md index 009f8b66..50592931 100644 --- a/README.md +++ b/README.md @@ -348,6 +348,13 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see } ``` + Note: You can avoid any [jshint](http://www.jshint.com/) warnings by placing the comment below above the line of code. However it is not needed when the function is named using UpperCasing, as this convention means it is a constructor function, which is what a controller is in Angular. + + ```javascript + /* jshint validthis: true */ + var vm = this; + ``` + Note: When creating watches in a controller using `controller as`, you can watch the `vm.*` member using the following syntax. (Create watches with caution as they add more load to the digest cycle.) ```javascript From 449fdb3187f067fcc6d8e2cf85a949dc90cb05d5 Mon Sep 17 00:00:00 2001 From: John Papa Date: Thu, 20 Nov 2014 23:52:10 -0500 Subject: [PATCH 020/567] whitespace --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 50592931..c77eb509 100644 --- a/README.md +++ b/README.md @@ -51,7 +51,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see ## Single Responsibility -### Rule of 1 +### Rule of 1 - Define 1 component per file. From 0418f4b7000f06df651eb7e0cb2f9685c0b1f3d8 Mon Sep 17 00:00:00 2001 From: John Papa Date: Thu, 20 Nov 2014 23:52:41 -0500 Subject: [PATCH 021/567] first code --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index c77eb509..1fa3a1ba 100644 --- a/README.md +++ b/README.md @@ -52,6 +52,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see ## Single Responsibility ### Rule of 1 +Style [#Y001](#Y001) - Define 1 component per file. From aaaf008c5e513ba87936e8a1e9b0086d18d761ef Mon Sep 17 00:00:00 2001 From: John Papa Date: Thu, 20 Nov 2014 23:54:00 -0500 Subject: [PATCH 022/567] first code --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 1fa3a1ba..12445b2f 100644 --- a/README.md +++ b/README.md @@ -52,7 +52,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see ## Single Responsibility ### Rule of 1 -Style [#Y001](#Y001) +###### Style [Y001](#Y001) - Define 1 component per file. From 857788794161ce0a17dbe08729d0994393aee41f Mon Sep 17 00:00:00 2001 From: John Papa Date: Fri, 21 Nov 2014 00:10:17 -0500 Subject: [PATCH 023/567] added Style codes --- README.md | 83 ++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 82 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 12445b2f..d86512ac 100644 --- a/README.md +++ b/README.md @@ -52,7 +52,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see ## Single Responsibility ### Rule of 1 -###### Style [Y001](#Y001) +###### [Style [Y001](#Y001)] - Define 1 component per file. @@ -106,6 +106,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see ## IIFE ### JavaScript Closures +###### [Style [Y010](#Y010)] - Wrap AngularJS components in an Immediately Invoked Function Expression (IIFE). @@ -172,12 +173,14 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see ## Modules ### Avoid Naming Collisions +###### [Style [Y020](#Y020)] - Use unique naming conventions with separators for sub-modules. *Why?*: Unique names help avoid module name collisions. Separators help define modules and their submodule hierarchy. For example `app` may be your root module while `app.dashboard` and `app.users` may be modules that are used as dependencies of `app`. ### Definitions (aka Setters) +###### [Style [Y021](#Y021)] - Declare modules without a variable using the setter syntax. @@ -207,6 +210,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see ``` ### Getters +###### [Style [Y022](#Y022)] - When using a module, avoid using a variable and instead use chaining with the getter syntax. @@ -230,6 +234,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see ``` ### Setting vs Getting +###### [Style [Y023](#Y023)] - Only set once and get for all other instances. @@ -239,6 +244,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see - Use `angular.module('app');` to get a module. ### Named vs Anonymous Functions +###### [Style [Y024](#Y024)] - Use named functions instead of passing an anonymous function in as a callback. @@ -277,6 +283,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see ## Controllers ### controllerAs View Syntax +###### [Style [Y030](#Y030)] - Use the [`controllerAs`](http://www.johnpapa.net/do-you-like-your-angular-controllers-with-or-without-sugar/) syntax over the `classic controller with $scope` syntax. @@ -301,6 +308,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see ``` ### controllerAs Controller Syntax +###### [Style [Y031](#Y031)] - Use the `controllerAs` syntax over the `classic controller with $scope` syntax. @@ -327,6 +335,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see ``` ### controllerAs with vm +###### [Style [Y032](#Y032)] - Use a capture variable for `this` when using the `controllerAs` syntax. Choose a consistent variable name such as `vm`, which stands for ViewModel. @@ -366,6 +375,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see ``` ### Bindable Members Up Top +###### [Style [Y033](#Y033)] - Place bindable members at the top of the controller, alphabetized, and not spread through the controller code. @@ -454,6 +464,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see ``` ### Function Declarations to Hide Implementation Details +###### [Style [Y034](#Y034)] - Use function declarations to hide implementation details. Keep your bindable members up top. When you need to bind a function in a controller, point it to a function declaration that appears later in the file. This is tied directly to the section Bindable Members Up Top. For more details see [this post](http://www.johnpapa.net/angular-function-declarations-function-expressions-and-readable-code). @@ -528,6 +539,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see ``` ### Defer Controller Logic +###### [Style [Y035](#Y036)] - Defer logic in a controller by delegating to services and factories. @@ -568,12 +580,14 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see ``` ### Keep Controllers Focused +###### [Style [Y037](#Y037)] - Define a controller for a view, and try not to reuse the controller for other views. Instead, move reusable logic to factories and keep the controller simple and focused on its view. *Why?*: Reusing controllers with several views is brittle and good end to end (e2e) test coverage is required to ensure stability across large applications. ### Assigning Controllers +###### [Style [Y038](#Y038)] - When a controller must be paired with a view and either component may be re-used by other controllers or views, define controllers along with their routes. @@ -632,6 +646,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see ## Services ### Singletons +###### [Style [Y040](#Y040)] - Services are instantiated with the `new` keyword, use `this` for public methods and variables. Since these are so similar to factories, use a factory instead for consistency. @@ -670,16 +685,19 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see ## Factories ### Single Responsibility +###### [Style [Y050](#Y050)] - Factories should have a [single responsibility](http://en.wikipedia.org/wiki/Single_responsibility_principle), that is encapsulated by its context. Once a factory begins to exceed that singular purpose, a new factory should be created. ### Singletons +###### [Style [Y051](#Y051)] - Factories are singletons and return an object that contains the members of the service. Note: [All AngularJS services are singletons](https://docs.angularjs.org/guide/services). ### Accessible Members Up Top +###### [Style [Y052](#Y052)] - Expose the callable members of the service (it's interface) at the top, using a technique derived from the [Revealing Module Pattern](http://addyosmani.com/resources/essentialjsdesignpatterns/book/#revealingmodulepatternjavascript). @@ -736,6 +754,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see ![Factories Using "Above the Fold"](https://raw.githubusercontent.com/johnpapa/angularjs-styleguide/master/assets/above-the-fold-2.png) ### Function Declarations to Hide Implementation Details +###### [Style [Y053](#Y053)] - Use function declarations to hide implementation details. Keep your accessible members of the factory up top. Point those to function declarations that appears later in the file. For more details see [this post](http://www.johnpapa.net/angular-function-declarations-function-expressions-and-readable-code). @@ -837,6 +856,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see ## Data Services ### Separate Data Calls +###### [Style [Y060](#Y060)] - Refactor logic for making data operations and interacting with data to a factory. Make data services responsible for XHR calls, local storage, stashing in memory, or any other data operations. @@ -912,6 +932,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see ``` ### Return a Promise from Data Calls +###### [Style [Y061](#Y061)] - When calling a data service that returns a promise such as $http, return a promise in your calling function too. @@ -959,6 +980,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see ## Directives ### Limit 1 Per File +###### [Style [Y070](#Y070)] - Create one directive per file. Name the file for the directive. @@ -1050,12 +1072,14 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see Note: There are many naming options for directives, especially since they can be used in narrow or wide scopes. Choose one that makes the directive and it's file name distinct and clear. Some examples are below, but see the naming section for more recommendations. ### Limit DOM Manipulation +###### [Style [Y072](#Y072)] - When manipulating the DOM directly, use a directive. If alternative ways can be used such as using CSS to set styles or the [animation services](https://docs.angularjs.org/api/ngAnimate), Angular templating, [`ngShow`](https://docs.angularjs.org/api/ng/directive/ngShow) or [`ngHide`](https://docs.angularjs.org/api/ng/directive/ngHide), then use those instead. For example, if the directive simply hides and shows, use ngHide/ngShow. *Why?*: DOM manipulation can be difficult to test, debug, and there are often better ways (e.g. CSS, animations, templates) ### Provide a Unique Directive Prefix +###### [Style [Y073](#Y073)] - Provide a short, unique and descriptive directive prefix such as `acmeSalesCustomerInfo` which is declared in HTML as `acme-sales-customer-info`. @@ -1064,6 +1088,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see Note: Avoid `ng-` as these are reserved for AngularJS directives.Research widely used directives to avoid naming conflicts, such as `ion-` for the [Ionic Framework](http://ionicframework.com/). ### Restrict to Elements and Attributes +###### [Style [Y074](#Y074)] - When creating a directive that makes sense as a standalone element, allow restrict `E` (custom element) and optionally restrict `A` (custom attribute). Generally, if it could be its own control, `E` is appropriate. General guideline is allow `EA` but lean towards implementing as an element when its standalone and as an attribute when it enhances its existing DOM element. @@ -1125,6 +1150,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see ``` ### Directives and ControllerAs +###### [Style [Y075](#Y075)] - Use `controller as` syntax with a directive to be consistent with using `controller as` with view and controller pairings. @@ -1190,6 +1216,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see ## Resolving Promises for a Controller ### Controller Activation Promises +###### [Style [Y080](#Y080)] - Resolve start-up logic for a controller in an `activate` function. @@ -1232,6 +1259,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see ``` ### Route Resolve Promises +###### [Style [Y081](#Y081)] - When a controller depends on a promise to be resolved, resolve those dependencies in the `$routeProvider` before the controller logic is executed. If you need to conditionally cancel a route before the controller is activated, use a route resolver. @@ -1295,6 +1323,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see ## Manual Annotating for Dependency Injection ### UnSafe from Minification +###### [Style [Y090](#Y090)] - Avoid using the shortcut syntax of declaring dependencies without using a minification-safe approach. @@ -1318,6 +1347,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see ``` ### Manually Identify Dependencies +###### [Style [Y091](#Y091)] - Use `$inject` to manually identify your dependencies for AngularJS components. @@ -1391,6 +1421,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see ``` ### Manually Identify Route Resolver Dependencies +###### [Style [Y092](#Y092)] - Use $inject to manually identify your route resolver dependencies for AngularJS components. @@ -1423,6 +1454,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see ## Minification and Annotation ### ng-annotate +###### [Style [Y100](#Y100)] - Use [ng-annotate](//github.com/olov/ng-annotate) for [Gulp](http://gulpjs.com) or [Grunt](http://gruntjs.com) and comment functions that need automated dependency injection using `/** @ngInject */` @@ -1499,6 +1531,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see `` ### Use Gulp or Grunt for ng-annotate +###### [Style [Y101](#Y101)] - Use [gulp-ng-annotate](https://www.npmjs.org/package/gulp-ng-annotate) or [grunt-ng-annotate](https://www.npmjs.org/package/grunt-ng-annotate) in an automated build task. Inject `/* @ngInject */` prior to any function that has dependencies. @@ -1532,6 +1565,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see ## Exception Handling ### decorators +###### [Style [Y110](#Y110)] - Use a [decorator](https://docs.angularjs.org/api/auto/service/$provide#decorator), at config time using the [`$provide`](https://docs.angularjs.org/api/auto/service/$provide) service, on the [`$exceptionHandler`](https://docs.angularjs.org/api/ng/service/$exceptionHandler) service to perform custom actions when exceptions occur. @@ -1572,6 +1606,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see ``` ### Exception Catchers +###### [Style [Y111](#Y111)] - Create a factory that exposes an interface to catch and gracefully handle exceptions. @@ -1602,6 +1637,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see ``` ### Route Errors +###### [Style [Y112](#Y112)] - Handle and log all routing errors using [`$routeChangeError`](https://docs.angularjs.org/api/ngRoute/service/$route#$routeChangeError). @@ -1637,6 +1673,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see ## Naming ### Naming Guidelines +###### [Style [Y120](#Y120)] - Use consistent names for all components following a pattern that describes the component's feature then (optionally) its type. My recommended pattern is `feature.type.js`. There are 2 names for most assets: * the file name (`avengers.controller.js`) @@ -1647,6 +1684,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see *Why?*: The naming conventions should simply help you find your code faster and make it easier to understand. ### Feature File Names +###### [Style [Y121](#Y121)] - Use consistent names for all components following a pattern that describes the component's feature then (optionally) its type. My recommended pattern is `feature.type.js`. @@ -1713,6 +1751,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see ``` ### Test File Names +###### [Style [Y122](#Y122)] - Name test specifications similar to the component they test with a suffix of `spec`. @@ -1731,6 +1770,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see ``` ### Controller Names +###### [Style [Y123](#Y123)] - Use consistent names for all controllers named after their feature. Use UpperCamelCase for controllers, as they are constructors. @@ -1752,6 +1792,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see ``` ### Controller Name Suffix +###### [Style [Y124](#Y124)] - Append the controller name with the suffix `Controller` or with no suffix. Choose 1, not both. @@ -1786,6 +1827,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see ``` ### Factory Names +###### [Style [Y125](#Y125)] - Use consistent names for all factories named after their feature. Use camel-casing for services and factories. @@ -1805,6 +1847,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see ``` ### Directive Component Names +###### [Style [Y126](#Y126)] - Use consistent names for all directives using camel-case. Use a short prefix to describe the area that the directives belong (some example are company prefix or project prefix). @@ -1826,6 +1869,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see ``` ### Modules +###### [Style [Y127](#Y127)] - When there are multiple modules, the main module file is named `app.module.js` while other dependent modules are named after what they represent. For example, an admin module is named `admin.module.js`. The respective registered module names would be `app` and `admin`. A single module app might be named `app.js`, omitting the module moniker. @@ -1836,6 +1880,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see *Why?*: Provides easy way to use task automation to load all module definitions first, then all other angular files (for bundling). ### Configuration +###### [Style [Y128](#Y128)] - Separate configuration for a module into its own file named after the module. A configuration file for the main `app` module is named `app.config.js` (or simply `config.js`). A configuration for a module named `admin.module.js` is named `admin.config.js`. @@ -1844,6 +1889,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see *Why?*: Provides a identifiable place to set configuration for a module. ### Routes +###### [Style [Y129](#Y129)] - Separate route configuration into its own file. Examples might be `app.route.js` for the main module and `admin.route.js` for the `admin` module. Even in smaller apps I prefer this separation from the rest of the configuration. An alternative is a longer name such as `admin.config.route.js`. @@ -1851,6 +1897,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see ## Application Structure LIFT Principle ### LIFT +###### [Style [Y140](#Y140)] - Structure your app such that you can `L`ocate your code quickly, `I`dentify the code at a glance, keep the `F`lattest structure you can, and `T`ry to stay DRY. The structure should follow these 4 basic guidelines. @@ -1864,6 +1911,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see 4. `T`ry to stay DRY (Don’t Repeat Yourself) or T-DRY ### Locate +###### [Style [Y141](#Y141)] - Make locating your code intuitive, simple and fast. @@ -1888,18 +1936,21 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see ``` ### Identify +###### [Style [Y142](#Y142)] - When you look at a file you should instantly know what it contains and represents. *Why?*: You spend less time hunting and pecking for code, and become more efficient. If this means you want longer file names, then so be it. Be descriptive with file names and keeping the contents of the file to exactly 1 component. Avoid files with multiple controllers, multiple services, or a mixture. There are deviations of the 1 per file rule when I have a set of very small features that are all related to each other, they are still easily identifiable. ### Flat +###### [Style [Y143](#Y143)] - Keep a flat folder structure as long as possible. When you get to 7+ files, begin considering separation. *Why?*: Nobody wants to search 7 levels of folders to find a file. Think about menus on web sites … anything deeper than 2 should take serious consideration. In a folder structure there is no hard and fast number rule, but when a folder has 7-10 files, that may be time to create subfolders. Base it on your comfort level. Use a flatter structure until there is an obvious value (to help the rest of LIFT) in creating a new folder. ### T-DRY (Try to Stick to DRY) +###### [Style [Y144](#Y144)] - Be DRY, but don't go nuts and sacrifice readability. @@ -1910,18 +1961,21 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see ## Application Structure ### Overall Guidelines +###### [Style [Y150](#Y150)] - Have a near term view of implementation and a long term vision. In other words, start small and but keep in mind on where the app is heading down the road. All of the app's code goes in a root folder named `app`. All content is 1 feature per file. Each controller, service, module, view is in its own file. All 3rd party vendor scripts are stored in another root folder and not in the `app` folder. I didn't write them and I don't want them cluttering my app (`bower_components`, `scripts`, `lib`). Note: Find more details and reasoning behind the structure at [this original post on application structure](http://www.johnpapa.net/angular-app-structuring-guidelines/). ### Layout +###### [Style [Y151](#Y151)] - Place components that define the overall layout of the application in a folder named `layout`. These may include a shell view and controller may act as the container for the app, navigation, menus, content areas, and other regions. *Why?*: Organizes all layout in a single place re-used throughout the application. ### Folders-by-Feature Structure +###### [Style [Y152](#Y152)] - Create folders named for the feature they represent. When a folder grows to contain more than 7 files, start to consider creating a folder for them. Your threshold may be different, so adjust as needed. @@ -2019,24 +2073,28 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see ## Modularity ### Many Small, Self Contained Modules +###### [Style [Y160](#Y160)] - Create small modules that encapsulate one responsibility. *Why?*: Modular applications make it easy to plug and go as they allow the development teams to build vertical slices of the applications and roll out incrementally. This means we can plug in new features as we develop them. ### Create an App Module +###### [Style [Y161](#Y161)] - Create an application root module whose role is pull together all of the modules and features of your application. Name this for your application. *Why?*: AngularJS encourages modularity and separation patterns. Creating an application root module whose role is to tie your other modules together provides a very straightforward way to add or remove modules from your application. ### Keep the App Module Thin +###### [Style [Y162](#Y162)] - Only put logic for pulling together the app in the application module. Leave features in their own modules. *Why?*: Adding additional roles to the application root to get remote data, display views, or other logic not related to pulling the app together muddies the app module and make both sets of features harder to reuse or turn off. ### Feature Areas are Modules +###### [Style [Y163](#Y163)] - Create modules that represent feature areas, such as layout, reusable and shared services, dashboards, and app specific features (e.g. customers, admin, sales). @@ -2047,12 +2105,14 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see *Why?*: Separating feature areas into modules makes it easier to test the modules in isolation and reuse code. ### Reusable Blocks are Modules +###### [Style [Y164](#Y164)] - Create modules that represent reusable application blocks for common services such as exception handling, logging, diagnostics, security, and local data stashing. *Why?*: These types of features are needed in many applications, so by keeping them separated in their own modules they can be application generic and be reused across applications. ### Module Dependencies +###### [Style [Y165](#Y165)] - The application root module depends on the app specific feature modules, the feature modules have no direct dependencies, the cross-application modules depend on all generic modules. @@ -2073,6 +2133,8 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see ## Startup Logic ### Configuration +###### [Style [Y170](#Y170)] + - Inject code into [module configuration](https://docs.angularjs.org/guide/module#module-loading-dependencies) that must be configured before running the angular app. Ideal candidaes include providers and constants. *Why?*: This makes it easier to have a less places for configuration. @@ -2103,6 +2165,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see ``` ### Run Blocks +###### [Style [Y171](#Y171)] - Any code that needs to run when an application starts should be declared in a factory, exposed via a function, and injected into the [run block](https://docs.angularjs.org/guide/module#module-loading-dependencies). @@ -2126,12 +2189,14 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see ## Angular $ Wrapper Services ### $document and $window +###### [Style [Y180](#Y180)] - Use [`$document`](https://docs.angularjs.org/api/ng/service/$document) and [`$window`](https://docs.angularjs.org/api/ng/service/$window) instead of `document` and `window`. *Why?*: These services are wrapped by Angular and more easily testable than using document and window in tests. This helps you avoid having to mock document and window yourself. ### $timeout and $interval +###### [Style [Y181](#Y181)] - Use [`$timeout`](https://docs.angularjs.org/api/ng/service/$timeout) and [`$interval`](https://docs.angularjs.org/api/ng/service/$interval) instead of `setTimeout` and `setInterval` . @@ -2143,6 +2208,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see Unit testing helps maintain clean code, as such I included some of my recommendations for unit testing foundations with links for more information. ### Write Tests with Stories +###### [Style [Y190](#Y190)] - Write a set of tests for every story. Start with an empty test and fill them in as you write the code for the story. @@ -2169,6 +2235,7 @@ Unit testing helps maintain clean code, as such I included some of my recommenda ``` ### Testing Library +###### [Style [Y191](#Y191)] - Use [Jasmine](http://jasmine.github.io/) or [Mocha](http://visionmedia.github.io/mocha/) for unit testing. @@ -2177,6 +2244,7 @@ Unit testing helps maintain clean code, as such I included some of my recommenda Note: When using Mocha, also consider choosing an assert library such as [Chai](http://chaijs.com). ### Test Runner +###### [Style [Y192](#Y192)] - Use [Karma](http://karma-runner.github.io) as a test runner. @@ -2189,6 +2257,7 @@ Unit testing helps maintain clean code, as such I included some of my recommenda *Why?*: Karma works well with task automation leaders such as [Grunt](http://www.gruntjs.com) (with [grunt-karma](https://github.com/karma-runner/grunt-karma)) and [Gulp](http://www.gulpjs.com) (with [gulp-karma](https://github.com/lazd/gulp-karma)). ### Stubbing and Spying +###### [Style [Y193](#Y193)] - Use Sinon for stubbing and spying. @@ -2197,6 +2266,7 @@ Unit testing helps maintain clean code, as such I included some of my recommenda *Why?*: Sinon makes it easier to toggle between Jasmine and Mocha, if you want to try both. ### Headless Browser +###### [Style [Y194](#Y194)] - Use [PhantomJS](http://phantomjs.org/) to run your tests on a server. @@ -2205,12 +2275,14 @@ Unit testing helps maintain clean code, as such I included some of my recommenda Note: You should still test on all browsers in your environment, as appropriate for your target audience. ### Code Analysis +###### [Style [Y195](#Y195)] - Run JSHint on your tests. *Why?*: Tests are code. JSHint can help identify code quality issues that may cause the test to work improperly. ### Alleviate Globals for JSHint Rules on Tests +###### [Style [Y196](#Y196)] - Relax the rules on your test code to allow for common globals such as `describe` and `expect`. @@ -2227,6 +2299,7 @@ Unit testing helps maintain clean code, as such I included some of my recommenda ## Animations ### Usage +###### [Style [Y210](#Y210)] - Use subtle [animations with AngularJS](https://docs.angularjs.org/guide/animations) to transition between states for views and primary visual elements. Include the [ngAnimate module](https://docs.angularjs.org/api/ngAnimate). The 3 keys are subtle, smooth, seamless. @@ -2235,12 +2308,14 @@ Unit testing helps maintain clean code, as such I included some of my recommenda *Why?*: Subtle animations can improve perceived performance as views transition. ### Sub Second +###### [Style [Y211](#Y211)] - Use short durations for animations. I generally start with 300ms and adjust until appropriate. *Why?*: Long animations can have the reverse affect on User Experience and perceived performance by giving the appearance of a slow application. ### animate.css +###### [Style [Y212](#Y212)] - Use [animate.css](http://daneden.github.io/animate.css/) for conventional animations. @@ -2257,6 +2332,7 @@ Unit testing helps maintain clean code, as such I included some of my recommenda ## Comments ### jsDoc +###### [Style [Y220](#Y220)] - If planning to produce documentation, use [`jsDoc`](http://usejsdoc.org/) syntax to document function names, description, params and returns. Use `@namespace` and `@memberOf` to match your app structure. @@ -2308,6 +2384,7 @@ Unit testing helps maintain clean code, as such I included some of my recommenda ## JS Hint ### Use an Options File +###### [Style [Y230](#Y230)] - Use JS Hint for linting your JavaScript and be sure to customize the JS Hint options file and include in source control. See the [JS Hint docs](http://www.jshint.com/docs/) for details on the options. @@ -2384,6 +2461,7 @@ Unit testing helps maintain clean code, as such I included some of my recommenda ## Constants ### Vendor Globals +###### [Style [Y240](#Y240)] - Create an AngularJS Constant for vendor libraries' global variables. @@ -2409,6 +2487,7 @@ Unit testing helps maintain clean code, as such I included some of my recommenda Use file templates or snippets to help follow consistent styles and patterns. Here are templates and/or snippets for some of the web development editors and IDEs. ### Sublime Text +###### [Style [Y250](#Y250)] - AngularJS snippets that follow these styles and guidelines. @@ -2425,6 +2504,7 @@ Use file templates or snippets to help follow consistent styles and patterns. He ``` ### Visual Studio +###### [Style [Y251](#Y251)] - AngularJS file templates that follow these styles and guidelines can be found at [SideWaffle](http://www.sidewaffle.com) @@ -2433,6 +2513,7 @@ Use file templates or snippets to help follow consistent styles and patterns. He - Restart Visual Studio ### WebStorm +###### [Style [Y252](#Y252)] - AngularJS snippets and file templates that follow these styles and guidelines. You can import them into your WebStorm settings: From f7130cec535bf358987669b0578af6ba2497cc56 Mon Sep 17 00:00:00 2001 From: John Papa Date: Fri, 21 Nov 2014 00:12:01 -0500 Subject: [PATCH 024/567] added Style codes with links --- README.md | 162 +++++++++++++++++++++++++++--------------------------- 1 file changed, 81 insertions(+), 81 deletions(-) diff --git a/README.md b/README.md index d86512ac..d298abe6 100644 --- a/README.md +++ b/README.md @@ -52,7 +52,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see ## Single Responsibility ### Rule of 1 -###### [Style [Y001](#Y001)] +###### [Style [Y001](#Style-Y001)] - Define 1 component per file. @@ -106,7 +106,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see ## IIFE ### JavaScript Closures -###### [Style [Y010](#Y010)] +###### [Style [Y010](#Style-Y010)] - Wrap AngularJS components in an Immediately Invoked Function Expression (IIFE). @@ -173,14 +173,14 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see ## Modules ### Avoid Naming Collisions -###### [Style [Y020](#Y020)] +###### [Style [Y020](#Style-Y020)] - Use unique naming conventions with separators for sub-modules. *Why?*: Unique names help avoid module name collisions. Separators help define modules and their submodule hierarchy. For example `app` may be your root module while `app.dashboard` and `app.users` may be modules that are used as dependencies of `app`. ### Definitions (aka Setters) -###### [Style [Y021](#Y021)] +###### [Style [Y021](#Style-Y021)] - Declare modules without a variable using the setter syntax. @@ -210,7 +210,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see ``` ### Getters -###### [Style [Y022](#Y022)] +###### [Style [Y022](#Style-Y022)] - When using a module, avoid using a variable and instead use chaining with the getter syntax. @@ -234,7 +234,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see ``` ### Setting vs Getting -###### [Style [Y023](#Y023)] +###### [Style [Y023](#Style-Y023)] - Only set once and get for all other instances. @@ -244,7 +244,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see - Use `angular.module('app');` to get a module. ### Named vs Anonymous Functions -###### [Style [Y024](#Y024)] +###### [Style [Y024](#Style-Y024)] - Use named functions instead of passing an anonymous function in as a callback. @@ -283,7 +283,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see ## Controllers ### controllerAs View Syntax -###### [Style [Y030](#Y030)] +###### [Style [Y030](#Style-Y030)] - Use the [`controllerAs`](http://www.johnpapa.net/do-you-like-your-angular-controllers-with-or-without-sugar/) syntax over the `classic controller with $scope` syntax. @@ -308,7 +308,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see ``` ### controllerAs Controller Syntax -###### [Style [Y031](#Y031)] +###### [Style [Y031](#Style-Y031)] - Use the `controllerAs` syntax over the `classic controller with $scope` syntax. @@ -335,7 +335,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see ``` ### controllerAs with vm -###### [Style [Y032](#Y032)] +###### [Style [Y032](#Style-Y032)] - Use a capture variable for `this` when using the `controllerAs` syntax. Choose a consistent variable name such as `vm`, which stands for ViewModel. @@ -375,7 +375,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see ``` ### Bindable Members Up Top -###### [Style [Y033](#Y033)] +###### [Style [Y033](#Style-Y033)] - Place bindable members at the top of the controller, alphabetized, and not spread through the controller code. @@ -464,7 +464,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see ``` ### Function Declarations to Hide Implementation Details -###### [Style [Y034](#Y034)] +###### [Style [Y034](#Style-Y034)] - Use function declarations to hide implementation details. Keep your bindable members up top. When you need to bind a function in a controller, point it to a function declaration that appears later in the file. This is tied directly to the section Bindable Members Up Top. For more details see [this post](http://www.johnpapa.net/angular-function-declarations-function-expressions-and-readable-code). @@ -539,7 +539,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see ``` ### Defer Controller Logic -###### [Style [Y035](#Y036)] +###### [Style [Y035](#Style-Y036)] - Defer logic in a controller by delegating to services and factories. @@ -580,14 +580,14 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see ``` ### Keep Controllers Focused -###### [Style [Y037](#Y037)] +###### [Style [Y037](#Style-Y037)] - Define a controller for a view, and try not to reuse the controller for other views. Instead, move reusable logic to factories and keep the controller simple and focused on its view. *Why?*: Reusing controllers with several views is brittle and good end to end (e2e) test coverage is required to ensure stability across large applications. ### Assigning Controllers -###### [Style [Y038](#Y038)] +###### [Style [Y038](#Style-Y038)] - When a controller must be paired with a view and either component may be re-used by other controllers or views, define controllers along with their routes. @@ -646,7 +646,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see ## Services ### Singletons -###### [Style [Y040](#Y040)] +###### [Style [Y040](#Style-Y040)] - Services are instantiated with the `new` keyword, use `this` for public methods and variables. Since these are so similar to factories, use a factory instead for consistency. @@ -685,19 +685,19 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see ## Factories ### Single Responsibility -###### [Style [Y050](#Y050)] +###### [Style [Y050](#Style-Y050)] - Factories should have a [single responsibility](http://en.wikipedia.org/wiki/Single_responsibility_principle), that is encapsulated by its context. Once a factory begins to exceed that singular purpose, a new factory should be created. ### Singletons -###### [Style [Y051](#Y051)] +###### [Style [Y051](#Style-Y051)] - Factories are singletons and return an object that contains the members of the service. Note: [All AngularJS services are singletons](https://docs.angularjs.org/guide/services). ### Accessible Members Up Top -###### [Style [Y052](#Y052)] +###### [Style [Y052](#Style-Y052)] - Expose the callable members of the service (it's interface) at the top, using a technique derived from the [Revealing Module Pattern](http://addyosmani.com/resources/essentialjsdesignpatterns/book/#revealingmodulepatternjavascript). @@ -754,7 +754,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see ![Factories Using "Above the Fold"](https://raw.githubusercontent.com/johnpapa/angularjs-styleguide/master/assets/above-the-fold-2.png) ### Function Declarations to Hide Implementation Details -###### [Style [Y053](#Y053)] +###### [Style [Y053](#Style-Y053)] - Use function declarations to hide implementation details. Keep your accessible members of the factory up top. Point those to function declarations that appears later in the file. For more details see [this post](http://www.johnpapa.net/angular-function-declarations-function-expressions-and-readable-code). @@ -856,7 +856,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see ## Data Services ### Separate Data Calls -###### [Style [Y060](#Y060)] +###### [Style [Y060](#Style-Y060)] - Refactor logic for making data operations and interacting with data to a factory. Make data services responsible for XHR calls, local storage, stashing in memory, or any other data operations. @@ -932,7 +932,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see ``` ### Return a Promise from Data Calls -###### [Style [Y061](#Y061)] +###### [Style [Y061](#Style-Y061)] - When calling a data service that returns a promise such as $http, return a promise in your calling function too. @@ -980,7 +980,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see ## Directives ### Limit 1 Per File -###### [Style [Y070](#Y070)] +###### [Style [Y070](#Style-Y070)] - Create one directive per file. Name the file for the directive. @@ -1072,14 +1072,14 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see Note: There are many naming options for directives, especially since they can be used in narrow or wide scopes. Choose one that makes the directive and it's file name distinct and clear. Some examples are below, but see the naming section for more recommendations. ### Limit DOM Manipulation -###### [Style [Y072](#Y072)] +###### [Style [Y072](#Style-Y072)] - When manipulating the DOM directly, use a directive. If alternative ways can be used such as using CSS to set styles or the [animation services](https://docs.angularjs.org/api/ngAnimate), Angular templating, [`ngShow`](https://docs.angularjs.org/api/ng/directive/ngShow) or [`ngHide`](https://docs.angularjs.org/api/ng/directive/ngHide), then use those instead. For example, if the directive simply hides and shows, use ngHide/ngShow. *Why?*: DOM manipulation can be difficult to test, debug, and there are often better ways (e.g. CSS, animations, templates) ### Provide a Unique Directive Prefix -###### [Style [Y073](#Y073)] +###### [Style [Y073](#Style-Y073)] - Provide a short, unique and descriptive directive prefix such as `acmeSalesCustomerInfo` which is declared in HTML as `acme-sales-customer-info`. @@ -1088,7 +1088,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see Note: Avoid `ng-` as these are reserved for AngularJS directives.Research widely used directives to avoid naming conflicts, such as `ion-` for the [Ionic Framework](http://ionicframework.com/). ### Restrict to Elements and Attributes -###### [Style [Y074](#Y074)] +###### [Style [Y074](#Style-Y074)] - When creating a directive that makes sense as a standalone element, allow restrict `E` (custom element) and optionally restrict `A` (custom attribute). Generally, if it could be its own control, `E` is appropriate. General guideline is allow `EA` but lean towards implementing as an element when its standalone and as an attribute when it enhances its existing DOM element. @@ -1150,7 +1150,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see ``` ### Directives and ControllerAs -###### [Style [Y075](#Y075)] +###### [Style [Y075](#Style-Y075)] - Use `controller as` syntax with a directive to be consistent with using `controller as` with view and controller pairings. @@ -1216,7 +1216,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see ## Resolving Promises for a Controller ### Controller Activation Promises -###### [Style [Y080](#Y080)] +###### [Style [Y080](#Style-Y080)] - Resolve start-up logic for a controller in an `activate` function. @@ -1259,7 +1259,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see ``` ### Route Resolve Promises -###### [Style [Y081](#Y081)] +###### [Style [Y081](#Style-Y081)] - When a controller depends on a promise to be resolved, resolve those dependencies in the `$routeProvider` before the controller logic is executed. If you need to conditionally cancel a route before the controller is activated, use a route resolver. @@ -1323,7 +1323,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see ## Manual Annotating for Dependency Injection ### UnSafe from Minification -###### [Style [Y090](#Y090)] +###### [Style [Y090](#Style-Y090)] - Avoid using the shortcut syntax of declaring dependencies without using a minification-safe approach. @@ -1347,7 +1347,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see ``` ### Manually Identify Dependencies -###### [Style [Y091](#Y091)] +###### [Style [Y091](#Style-Y091)] - Use `$inject` to manually identify your dependencies for AngularJS components. @@ -1421,7 +1421,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see ``` ### Manually Identify Route Resolver Dependencies -###### [Style [Y092](#Y092)] +###### [Style [Y092](#Style-Y092)] - Use $inject to manually identify your route resolver dependencies for AngularJS components. @@ -1454,7 +1454,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see ## Minification and Annotation ### ng-annotate -###### [Style [Y100](#Y100)] +###### [Style [Y100](#Style-Y100)] - Use [ng-annotate](//github.com/olov/ng-annotate) for [Gulp](http://gulpjs.com) or [Grunt](http://gruntjs.com) and comment functions that need automated dependency injection using `/** @ngInject */` @@ -1531,7 +1531,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see `` ### Use Gulp or Grunt for ng-annotate -###### [Style [Y101](#Y101)] +###### [Style [Y101](#Style-Y101)] - Use [gulp-ng-annotate](https://www.npmjs.org/package/gulp-ng-annotate) or [grunt-ng-annotate](https://www.npmjs.org/package/grunt-ng-annotate) in an automated build task. Inject `/* @ngInject */` prior to any function that has dependencies. @@ -1565,7 +1565,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see ## Exception Handling ### decorators -###### [Style [Y110](#Y110)] +###### [Style [Y110](#Style-Y110)] - Use a [decorator](https://docs.angularjs.org/api/auto/service/$provide#decorator), at config time using the [`$provide`](https://docs.angularjs.org/api/auto/service/$provide) service, on the [`$exceptionHandler`](https://docs.angularjs.org/api/ng/service/$exceptionHandler) service to perform custom actions when exceptions occur. @@ -1606,7 +1606,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see ``` ### Exception Catchers -###### [Style [Y111](#Y111)] +###### [Style [Y111](#Style-Y111)] - Create a factory that exposes an interface to catch and gracefully handle exceptions. @@ -1637,7 +1637,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see ``` ### Route Errors -###### [Style [Y112](#Y112)] +###### [Style [Y112](#Style-Y112)] - Handle and log all routing errors using [`$routeChangeError`](https://docs.angularjs.org/api/ngRoute/service/$route#$routeChangeError). @@ -1673,7 +1673,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see ## Naming ### Naming Guidelines -###### [Style [Y120](#Y120)] +###### [Style [Y120](#Style-Y120)] - Use consistent names for all components following a pattern that describes the component's feature then (optionally) its type. My recommended pattern is `feature.type.js`. There are 2 names for most assets: * the file name (`avengers.controller.js`) @@ -1684,7 +1684,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see *Why?*: The naming conventions should simply help you find your code faster and make it easier to understand. ### Feature File Names -###### [Style [Y121](#Y121)] +###### [Style [Y121](#Style-Y121)] - Use consistent names for all components following a pattern that describes the component's feature then (optionally) its type. My recommended pattern is `feature.type.js`. @@ -1751,7 +1751,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see ``` ### Test File Names -###### [Style [Y122](#Y122)] +###### [Style [Y122](#Style-Y122)] - Name test specifications similar to the component they test with a suffix of `spec`. @@ -1770,7 +1770,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see ``` ### Controller Names -###### [Style [Y123](#Y123)] +###### [Style [Y123](#Style-Y123)] - Use consistent names for all controllers named after their feature. Use UpperCamelCase for controllers, as they are constructors. @@ -1792,7 +1792,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see ``` ### Controller Name Suffix -###### [Style [Y124](#Y124)] +###### [Style [Y124](#Style-Y124)] - Append the controller name with the suffix `Controller` or with no suffix. Choose 1, not both. @@ -1827,7 +1827,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see ``` ### Factory Names -###### [Style [Y125](#Y125)] +###### [Style [Y125](#Style-Y125)] - Use consistent names for all factories named after their feature. Use camel-casing for services and factories. @@ -1847,7 +1847,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see ``` ### Directive Component Names -###### [Style [Y126](#Y126)] +###### [Style [Y126](#Style-Y126)] - Use consistent names for all directives using camel-case. Use a short prefix to describe the area that the directives belong (some example are company prefix or project prefix). @@ -1869,7 +1869,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see ``` ### Modules -###### [Style [Y127](#Y127)] +###### [Style [Y127](#Style-Y127)] - When there are multiple modules, the main module file is named `app.module.js` while other dependent modules are named after what they represent. For example, an admin module is named `admin.module.js`. The respective registered module names would be `app` and `admin`. A single module app might be named `app.js`, omitting the module moniker. @@ -1880,7 +1880,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see *Why?*: Provides easy way to use task automation to load all module definitions first, then all other angular files (for bundling). ### Configuration -###### [Style [Y128](#Y128)] +###### [Style [Y128](#Style-Y128)] - Separate configuration for a module into its own file named after the module. A configuration file for the main `app` module is named `app.config.js` (or simply `config.js`). A configuration for a module named `admin.module.js` is named `admin.config.js`. @@ -1889,7 +1889,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see *Why?*: Provides a identifiable place to set configuration for a module. ### Routes -###### [Style [Y129](#Y129)] +###### [Style [Y129](#Style-Y129)] - Separate route configuration into its own file. Examples might be `app.route.js` for the main module and `admin.route.js` for the `admin` module. Even in smaller apps I prefer this separation from the rest of the configuration. An alternative is a longer name such as `admin.config.route.js`. @@ -1897,7 +1897,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see ## Application Structure LIFT Principle ### LIFT -###### [Style [Y140](#Y140)] +###### [Style [Y140](#Style-Y140)] - Structure your app such that you can `L`ocate your code quickly, `I`dentify the code at a glance, keep the `F`lattest structure you can, and `T`ry to stay DRY. The structure should follow these 4 basic guidelines. @@ -1911,7 +1911,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see 4. `T`ry to stay DRY (Don’t Repeat Yourself) or T-DRY ### Locate -###### [Style [Y141](#Y141)] +###### [Style [Y141](#Style-Y141)] - Make locating your code intuitive, simple and fast. @@ -1936,21 +1936,21 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see ``` ### Identify -###### [Style [Y142](#Y142)] +###### [Style [Y142](#Style-Y142)] - When you look at a file you should instantly know what it contains and represents. *Why?*: You spend less time hunting and pecking for code, and become more efficient. If this means you want longer file names, then so be it. Be descriptive with file names and keeping the contents of the file to exactly 1 component. Avoid files with multiple controllers, multiple services, or a mixture. There are deviations of the 1 per file rule when I have a set of very small features that are all related to each other, they are still easily identifiable. ### Flat -###### [Style [Y143](#Y143)] +###### [Style [Y143](#Style-Y143)] - Keep a flat folder structure as long as possible. When you get to 7+ files, begin considering separation. *Why?*: Nobody wants to search 7 levels of folders to find a file. Think about menus on web sites … anything deeper than 2 should take serious consideration. In a folder structure there is no hard and fast number rule, but when a folder has 7-10 files, that may be time to create subfolders. Base it on your comfort level. Use a flatter structure until there is an obvious value (to help the rest of LIFT) in creating a new folder. ### T-DRY (Try to Stick to DRY) -###### [Style [Y144](#Y144)] +###### [Style [Y144](#Style-Y144)] - Be DRY, but don't go nuts and sacrifice readability. @@ -1961,21 +1961,21 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see ## Application Structure ### Overall Guidelines -###### [Style [Y150](#Y150)] +###### [Style [Y150](#Style-Y150)] - Have a near term view of implementation and a long term vision. In other words, start small and but keep in mind on where the app is heading down the road. All of the app's code goes in a root folder named `app`. All content is 1 feature per file. Each controller, service, module, view is in its own file. All 3rd party vendor scripts are stored in another root folder and not in the `app` folder. I didn't write them and I don't want them cluttering my app (`bower_components`, `scripts`, `lib`). Note: Find more details and reasoning behind the structure at [this original post on application structure](http://www.johnpapa.net/angular-app-structuring-guidelines/). ### Layout -###### [Style [Y151](#Y151)] +###### [Style [Y151](#Style-Y151)] - Place components that define the overall layout of the application in a folder named `layout`. These may include a shell view and controller may act as the container for the app, navigation, menus, content areas, and other regions. *Why?*: Organizes all layout in a single place re-used throughout the application. ### Folders-by-Feature Structure -###### [Style [Y152](#Y152)] +###### [Style [Y152](#Style-Y152)] - Create folders named for the feature they represent. When a folder grows to contain more than 7 files, start to consider creating a folder for them. Your threshold may be different, so adjust as needed. @@ -2073,28 +2073,28 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see ## Modularity ### Many Small, Self Contained Modules -###### [Style [Y160](#Y160)] +###### [Style [Y160](#Style-Y160)] - Create small modules that encapsulate one responsibility. *Why?*: Modular applications make it easy to plug and go as they allow the development teams to build vertical slices of the applications and roll out incrementally. This means we can plug in new features as we develop them. ### Create an App Module -###### [Style [Y161](#Y161)] +###### [Style [Y161](#Style-Y161)] - Create an application root module whose role is pull together all of the modules and features of your application. Name this for your application. *Why?*: AngularJS encourages modularity and separation patterns. Creating an application root module whose role is to tie your other modules together provides a very straightforward way to add or remove modules from your application. ### Keep the App Module Thin -###### [Style [Y162](#Y162)] +###### [Style [Y162](#Style-Y162)] - Only put logic for pulling together the app in the application module. Leave features in their own modules. *Why?*: Adding additional roles to the application root to get remote data, display views, or other logic not related to pulling the app together muddies the app module and make both sets of features harder to reuse or turn off. ### Feature Areas are Modules -###### [Style [Y163](#Y163)] +###### [Style [Y163](#Style-Y163)] - Create modules that represent feature areas, such as layout, reusable and shared services, dashboards, and app specific features (e.g. customers, admin, sales). @@ -2105,14 +2105,14 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see *Why?*: Separating feature areas into modules makes it easier to test the modules in isolation and reuse code. ### Reusable Blocks are Modules -###### [Style [Y164](#Y164)] +###### [Style [Y164](#Style-Y164)] - Create modules that represent reusable application blocks for common services such as exception handling, logging, diagnostics, security, and local data stashing. *Why?*: These types of features are needed in many applications, so by keeping them separated in their own modules they can be application generic and be reused across applications. ### Module Dependencies -###### [Style [Y165](#Y165)] +###### [Style [Y165](#Style-Y165)] - The application root module depends on the app specific feature modules, the feature modules have no direct dependencies, the cross-application modules depend on all generic modules. @@ -2133,7 +2133,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see ## Startup Logic ### Configuration -###### [Style [Y170](#Y170)] +###### [Style [Y170](#Style-Y170)] - Inject code into [module configuration](https://docs.angularjs.org/guide/module#module-loading-dependencies) that must be configured before running the angular app. Ideal candidaes include providers and constants. @@ -2165,7 +2165,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see ``` ### Run Blocks -###### [Style [Y171](#Y171)] +###### [Style [Y171](#Style-Y171)] - Any code that needs to run when an application starts should be declared in a factory, exposed via a function, and injected into the [run block](https://docs.angularjs.org/guide/module#module-loading-dependencies). @@ -2189,14 +2189,14 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see ## Angular $ Wrapper Services ### $document and $window -###### [Style [Y180](#Y180)] +###### [Style [Y180](#Style-Y180)] - Use [`$document`](https://docs.angularjs.org/api/ng/service/$document) and [`$window`](https://docs.angularjs.org/api/ng/service/$window) instead of `document` and `window`. *Why?*: These services are wrapped by Angular and more easily testable than using document and window in tests. This helps you avoid having to mock document and window yourself. ### $timeout and $interval -###### [Style [Y181](#Y181)] +###### [Style [Y181](#Style-Y181)] - Use [`$timeout`](https://docs.angularjs.org/api/ng/service/$timeout) and [`$interval`](https://docs.angularjs.org/api/ng/service/$interval) instead of `setTimeout` and `setInterval` . @@ -2208,7 +2208,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see Unit testing helps maintain clean code, as such I included some of my recommendations for unit testing foundations with links for more information. ### Write Tests with Stories -###### [Style [Y190](#Y190)] +###### [Style [Y190](#Style-Y190)] - Write a set of tests for every story. Start with an empty test and fill them in as you write the code for the story. @@ -2235,7 +2235,7 @@ Unit testing helps maintain clean code, as such I included some of my recommenda ``` ### Testing Library -###### [Style [Y191](#Y191)] +###### [Style [Y191](#Style-Y191)] - Use [Jasmine](http://jasmine.github.io/) or [Mocha](http://visionmedia.github.io/mocha/) for unit testing. @@ -2244,7 +2244,7 @@ Unit testing helps maintain clean code, as such I included some of my recommenda Note: When using Mocha, also consider choosing an assert library such as [Chai](http://chaijs.com). ### Test Runner -###### [Style [Y192](#Y192)] +###### [Style [Y192](#Style-Y192)] - Use [Karma](http://karma-runner.github.io) as a test runner. @@ -2257,7 +2257,7 @@ Unit testing helps maintain clean code, as such I included some of my recommenda *Why?*: Karma works well with task automation leaders such as [Grunt](http://www.gruntjs.com) (with [grunt-karma](https://github.com/karma-runner/grunt-karma)) and [Gulp](http://www.gulpjs.com) (with [gulp-karma](https://github.com/lazd/gulp-karma)). ### Stubbing and Spying -###### [Style [Y193](#Y193)] +###### [Style [Y193](#Style-Y193)] - Use Sinon for stubbing and spying. @@ -2266,7 +2266,7 @@ Unit testing helps maintain clean code, as such I included some of my recommenda *Why?*: Sinon makes it easier to toggle between Jasmine and Mocha, if you want to try both. ### Headless Browser -###### [Style [Y194](#Y194)] +###### [Style [Y194](#Style-Y194)] - Use [PhantomJS](http://phantomjs.org/) to run your tests on a server. @@ -2275,14 +2275,14 @@ Unit testing helps maintain clean code, as such I included some of my recommenda Note: You should still test on all browsers in your environment, as appropriate for your target audience. ### Code Analysis -###### [Style [Y195](#Y195)] +###### [Style [Y195](#Style-Y195)] - Run JSHint on your tests. *Why?*: Tests are code. JSHint can help identify code quality issues that may cause the test to work improperly. ### Alleviate Globals for JSHint Rules on Tests -###### [Style [Y196](#Y196)] +###### [Style [Y196](#Style-Y196)] - Relax the rules on your test code to allow for common globals such as `describe` and `expect`. @@ -2299,7 +2299,7 @@ Unit testing helps maintain clean code, as such I included some of my recommenda ## Animations ### Usage -###### [Style [Y210](#Y210)] +###### [Style [Y210](#Style-Y210)] - Use subtle [animations with AngularJS](https://docs.angularjs.org/guide/animations) to transition between states for views and primary visual elements. Include the [ngAnimate module](https://docs.angularjs.org/api/ngAnimate). The 3 keys are subtle, smooth, seamless. @@ -2308,14 +2308,14 @@ Unit testing helps maintain clean code, as such I included some of my recommenda *Why?*: Subtle animations can improve perceived performance as views transition. ### Sub Second -###### [Style [Y211](#Y211)] +###### [Style [Y211](#Style-Y211)] - Use short durations for animations. I generally start with 300ms and adjust until appropriate. *Why?*: Long animations can have the reverse affect on User Experience and perceived performance by giving the appearance of a slow application. ### animate.css -###### [Style [Y212](#Y212)] +###### [Style [Y212](#Style-Y212)] - Use [animate.css](http://daneden.github.io/animate.css/) for conventional animations. @@ -2332,7 +2332,7 @@ Unit testing helps maintain clean code, as such I included some of my recommenda ## Comments ### jsDoc -###### [Style [Y220](#Y220)] +###### [Style [Y220](#Style-Y220)] - If planning to produce documentation, use [`jsDoc`](http://usejsdoc.org/) syntax to document function names, description, params and returns. Use `@namespace` and `@memberOf` to match your app structure. @@ -2384,7 +2384,7 @@ Unit testing helps maintain clean code, as such I included some of my recommenda ## JS Hint ### Use an Options File -###### [Style [Y230](#Y230)] +###### [Style [Y230](#Style-Y230)] - Use JS Hint for linting your JavaScript and be sure to customize the JS Hint options file and include in source control. See the [JS Hint docs](http://www.jshint.com/docs/) for details on the options. @@ -2461,7 +2461,7 @@ Unit testing helps maintain clean code, as such I included some of my recommenda ## Constants ### Vendor Globals -###### [Style [Y240](#Y240)] +###### [Style [Y240](#Style-Y240)] - Create an AngularJS Constant for vendor libraries' global variables. @@ -2487,7 +2487,7 @@ Unit testing helps maintain clean code, as such I included some of my recommenda Use file templates or snippets to help follow consistent styles and patterns. Here are templates and/or snippets for some of the web development editors and IDEs. ### Sublime Text -###### [Style [Y250](#Y250)] +###### [Style [Y250](#Style-Y250)] - AngularJS snippets that follow these styles and guidelines. @@ -2504,7 +2504,7 @@ Use file templates or snippets to help follow consistent styles and patterns. He ``` ### Visual Studio -###### [Style [Y251](#Y251)] +###### [Style [Y251](#Style-Y251)] - AngularJS file templates that follow these styles and guidelines can be found at [SideWaffle](http://www.sidewaffle.com) @@ -2513,7 +2513,7 @@ Use file templates or snippets to help follow consistent styles and patterns. He - Restart Visual Studio ### WebStorm -###### [Style [Y252](#Y252)] +###### [Style [Y252](#Style-Y252)] - AngularJS snippets and file templates that follow these styles and guidelines. You can import them into your WebStorm settings: From 43a52df4e38b36b97bd802c9ebd9f823ce1b796b Mon Sep 17 00:00:00 2001 From: John Papa Date: Fri, 21 Nov 2014 00:12:54 -0500 Subject: [PATCH 025/567] proper casing for links --- README.md | 162 +++++++++++++++++++++++++++--------------------------- 1 file changed, 81 insertions(+), 81 deletions(-) diff --git a/README.md b/README.md index d298abe6..0a2372ad 100644 --- a/README.md +++ b/README.md @@ -52,7 +52,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see ## Single Responsibility ### Rule of 1 -###### [Style [Y001](#Style-Y001)] +###### [Style [Y001](#style-y001)] - Define 1 component per file. @@ -106,7 +106,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see ## IIFE ### JavaScript Closures -###### [Style [Y010](#Style-Y010)] +###### [Style [Y010](#style-y010)] - Wrap AngularJS components in an Immediately Invoked Function Expression (IIFE). @@ -173,14 +173,14 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see ## Modules ### Avoid Naming Collisions -###### [Style [Y020](#Style-Y020)] +###### [Style [Y020](#style-y020)] - Use unique naming conventions with separators for sub-modules. *Why?*: Unique names help avoid module name collisions. Separators help define modules and their submodule hierarchy. For example `app` may be your root module while `app.dashboard` and `app.users` may be modules that are used as dependencies of `app`. ### Definitions (aka Setters) -###### [Style [Y021](#Style-Y021)] +###### [Style [Y021](#style-y021)] - Declare modules without a variable using the setter syntax. @@ -210,7 +210,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see ``` ### Getters -###### [Style [Y022](#Style-Y022)] +###### [Style [Y022](#style-y022)] - When using a module, avoid using a variable and instead use chaining with the getter syntax. @@ -234,7 +234,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see ``` ### Setting vs Getting -###### [Style [Y023](#Style-Y023)] +###### [Style [Y023](#style-y023)] - Only set once and get for all other instances. @@ -244,7 +244,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see - Use `angular.module('app');` to get a module. ### Named vs Anonymous Functions -###### [Style [Y024](#Style-Y024)] +###### [Style [Y024](#style-y024)] - Use named functions instead of passing an anonymous function in as a callback. @@ -283,7 +283,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see ## Controllers ### controllerAs View Syntax -###### [Style [Y030](#Style-Y030)] +###### [Style [Y030](#style-y030)] - Use the [`controllerAs`](http://www.johnpapa.net/do-you-like-your-angular-controllers-with-or-without-sugar/) syntax over the `classic controller with $scope` syntax. @@ -308,7 +308,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see ``` ### controllerAs Controller Syntax -###### [Style [Y031](#Style-Y031)] +###### [Style [Y031](#style-y031)] - Use the `controllerAs` syntax over the `classic controller with $scope` syntax. @@ -335,7 +335,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see ``` ### controllerAs with vm -###### [Style [Y032](#Style-Y032)] +###### [Style [Y032](#style-y032)] - Use a capture variable for `this` when using the `controllerAs` syntax. Choose a consistent variable name such as `vm`, which stands for ViewModel. @@ -375,7 +375,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see ``` ### Bindable Members Up Top -###### [Style [Y033](#Style-Y033)] +###### [Style [Y033](#style-y033)] - Place bindable members at the top of the controller, alphabetized, and not spread through the controller code. @@ -464,7 +464,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see ``` ### Function Declarations to Hide Implementation Details -###### [Style [Y034](#Style-Y034)] +###### [Style [Y034](#style-y034)] - Use function declarations to hide implementation details. Keep your bindable members up top. When you need to bind a function in a controller, point it to a function declaration that appears later in the file. This is tied directly to the section Bindable Members Up Top. For more details see [this post](http://www.johnpapa.net/angular-function-declarations-function-expressions-and-readable-code). @@ -539,7 +539,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see ``` ### Defer Controller Logic -###### [Style [Y035](#Style-Y036)] +###### [Style [Y035](#style-y036)] - Defer logic in a controller by delegating to services and factories. @@ -580,14 +580,14 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see ``` ### Keep Controllers Focused -###### [Style [Y037](#Style-Y037)] +###### [Style [Y037](#style-y037)] - Define a controller for a view, and try not to reuse the controller for other views. Instead, move reusable logic to factories and keep the controller simple and focused on its view. *Why?*: Reusing controllers with several views is brittle and good end to end (e2e) test coverage is required to ensure stability across large applications. ### Assigning Controllers -###### [Style [Y038](#Style-Y038)] +###### [Style [Y038](#style-y038)] - When a controller must be paired with a view and either component may be re-used by other controllers or views, define controllers along with their routes. @@ -646,7 +646,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see ## Services ### Singletons -###### [Style [Y040](#Style-Y040)] +###### [Style [Y040](#style-y040)] - Services are instantiated with the `new` keyword, use `this` for public methods and variables. Since these are so similar to factories, use a factory instead for consistency. @@ -685,19 +685,19 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see ## Factories ### Single Responsibility -###### [Style [Y050](#Style-Y050)] +###### [Style [Y050](#style-y050)] - Factories should have a [single responsibility](http://en.wikipedia.org/wiki/Single_responsibility_principle), that is encapsulated by its context. Once a factory begins to exceed that singular purpose, a new factory should be created. ### Singletons -###### [Style [Y051](#Style-Y051)] +###### [Style [Y051](#style-y051)] - Factories are singletons and return an object that contains the members of the service. Note: [All AngularJS services are singletons](https://docs.angularjs.org/guide/services). ### Accessible Members Up Top -###### [Style [Y052](#Style-Y052)] +###### [Style [Y052](#style-y052)] - Expose the callable members of the service (it's interface) at the top, using a technique derived from the [Revealing Module Pattern](http://addyosmani.com/resources/essentialjsdesignpatterns/book/#revealingmodulepatternjavascript). @@ -754,7 +754,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see ![Factories Using "Above the Fold"](https://raw.githubusercontent.com/johnpapa/angularjs-styleguide/master/assets/above-the-fold-2.png) ### Function Declarations to Hide Implementation Details -###### [Style [Y053](#Style-Y053)] +###### [Style [Y053](#style-y053)] - Use function declarations to hide implementation details. Keep your accessible members of the factory up top. Point those to function declarations that appears later in the file. For more details see [this post](http://www.johnpapa.net/angular-function-declarations-function-expressions-and-readable-code). @@ -856,7 +856,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see ## Data Services ### Separate Data Calls -###### [Style [Y060](#Style-Y060)] +###### [Style [Y060](#style-y060)] - Refactor logic for making data operations and interacting with data to a factory. Make data services responsible for XHR calls, local storage, stashing in memory, or any other data operations. @@ -932,7 +932,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see ``` ### Return a Promise from Data Calls -###### [Style [Y061](#Style-Y061)] +###### [Style [Y061](#style-y061)] - When calling a data service that returns a promise such as $http, return a promise in your calling function too. @@ -980,7 +980,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see ## Directives ### Limit 1 Per File -###### [Style [Y070](#Style-Y070)] +###### [Style [Y070](#style-y070)] - Create one directive per file. Name the file for the directive. @@ -1072,14 +1072,14 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see Note: There are many naming options for directives, especially since they can be used in narrow or wide scopes. Choose one that makes the directive and it's file name distinct and clear. Some examples are below, but see the naming section for more recommendations. ### Limit DOM Manipulation -###### [Style [Y072](#Style-Y072)] +###### [Style [Y072](#style-y072)] - When manipulating the DOM directly, use a directive. If alternative ways can be used such as using CSS to set styles or the [animation services](https://docs.angularjs.org/api/ngAnimate), Angular templating, [`ngShow`](https://docs.angularjs.org/api/ng/directive/ngShow) or [`ngHide`](https://docs.angularjs.org/api/ng/directive/ngHide), then use those instead. For example, if the directive simply hides and shows, use ngHide/ngShow. *Why?*: DOM manipulation can be difficult to test, debug, and there are often better ways (e.g. CSS, animations, templates) ### Provide a Unique Directive Prefix -###### [Style [Y073](#Style-Y073)] +###### [Style [Y073](#style-y073)] - Provide a short, unique and descriptive directive prefix such as `acmeSalesCustomerInfo` which is declared in HTML as `acme-sales-customer-info`. @@ -1088,7 +1088,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see Note: Avoid `ng-` as these are reserved for AngularJS directives.Research widely used directives to avoid naming conflicts, such as `ion-` for the [Ionic Framework](http://ionicframework.com/). ### Restrict to Elements and Attributes -###### [Style [Y074](#Style-Y074)] +###### [Style [Y074](#style-y074)] - When creating a directive that makes sense as a standalone element, allow restrict `E` (custom element) and optionally restrict `A` (custom attribute). Generally, if it could be its own control, `E` is appropriate. General guideline is allow `EA` but lean towards implementing as an element when its standalone and as an attribute when it enhances its existing DOM element. @@ -1150,7 +1150,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see ``` ### Directives and ControllerAs -###### [Style [Y075](#Style-Y075)] +###### [Style [Y075](#style-y075)] - Use `controller as` syntax with a directive to be consistent with using `controller as` with view and controller pairings. @@ -1216,7 +1216,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see ## Resolving Promises for a Controller ### Controller Activation Promises -###### [Style [Y080](#Style-Y080)] +###### [Style [Y080](#style-y080)] - Resolve start-up logic for a controller in an `activate` function. @@ -1259,7 +1259,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see ``` ### Route Resolve Promises -###### [Style [Y081](#Style-Y081)] +###### [Style [Y081](#style-y081)] - When a controller depends on a promise to be resolved, resolve those dependencies in the `$routeProvider` before the controller logic is executed. If you need to conditionally cancel a route before the controller is activated, use a route resolver. @@ -1323,7 +1323,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see ## Manual Annotating for Dependency Injection ### UnSafe from Minification -###### [Style [Y090](#Style-Y090)] +###### [Style [Y090](#style-y090)] - Avoid using the shortcut syntax of declaring dependencies without using a minification-safe approach. @@ -1347,7 +1347,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see ``` ### Manually Identify Dependencies -###### [Style [Y091](#Style-Y091)] +###### [Style [Y091](#style-y091)] - Use `$inject` to manually identify your dependencies for AngularJS components. @@ -1421,7 +1421,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see ``` ### Manually Identify Route Resolver Dependencies -###### [Style [Y092](#Style-Y092)] +###### [Style [Y092](#style-y092)] - Use $inject to manually identify your route resolver dependencies for AngularJS components. @@ -1454,7 +1454,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see ## Minification and Annotation ### ng-annotate -###### [Style [Y100](#Style-Y100)] +###### [Style [Y100](#style-y100)] - Use [ng-annotate](//github.com/olov/ng-annotate) for [Gulp](http://gulpjs.com) or [Grunt](http://gruntjs.com) and comment functions that need automated dependency injection using `/** @ngInject */` @@ -1531,7 +1531,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see `` ### Use Gulp or Grunt for ng-annotate -###### [Style [Y101](#Style-Y101)] +###### [Style [Y101](#style-y101)] - Use [gulp-ng-annotate](https://www.npmjs.org/package/gulp-ng-annotate) or [grunt-ng-annotate](https://www.npmjs.org/package/grunt-ng-annotate) in an automated build task. Inject `/* @ngInject */` prior to any function that has dependencies. @@ -1565,7 +1565,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see ## Exception Handling ### decorators -###### [Style [Y110](#Style-Y110)] +###### [Style [Y110](#style-y110)] - Use a [decorator](https://docs.angularjs.org/api/auto/service/$provide#decorator), at config time using the [`$provide`](https://docs.angularjs.org/api/auto/service/$provide) service, on the [`$exceptionHandler`](https://docs.angularjs.org/api/ng/service/$exceptionHandler) service to perform custom actions when exceptions occur. @@ -1606,7 +1606,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see ``` ### Exception Catchers -###### [Style [Y111](#Style-Y111)] +###### [Style [Y111](#style-y111)] - Create a factory that exposes an interface to catch and gracefully handle exceptions. @@ -1637,7 +1637,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see ``` ### Route Errors -###### [Style [Y112](#Style-Y112)] +###### [Style [Y112](#style-y112)] - Handle and log all routing errors using [`$routeChangeError`](https://docs.angularjs.org/api/ngRoute/service/$route#$routeChangeError). @@ -1673,7 +1673,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see ## Naming ### Naming Guidelines -###### [Style [Y120](#Style-Y120)] +###### [Style [Y120](#style-y120)] - Use consistent names for all components following a pattern that describes the component's feature then (optionally) its type. My recommended pattern is `feature.type.js`. There are 2 names for most assets: * the file name (`avengers.controller.js`) @@ -1684,7 +1684,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see *Why?*: The naming conventions should simply help you find your code faster and make it easier to understand. ### Feature File Names -###### [Style [Y121](#Style-Y121)] +###### [Style [Y121](#style-y121)] - Use consistent names for all components following a pattern that describes the component's feature then (optionally) its type. My recommended pattern is `feature.type.js`. @@ -1751,7 +1751,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see ``` ### Test File Names -###### [Style [Y122](#Style-Y122)] +###### [Style [Y122](#style-y122)] - Name test specifications similar to the component they test with a suffix of `spec`. @@ -1770,7 +1770,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see ``` ### Controller Names -###### [Style [Y123](#Style-Y123)] +###### [Style [Y123](#style-y123)] - Use consistent names for all controllers named after their feature. Use UpperCamelCase for controllers, as they are constructors. @@ -1792,7 +1792,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see ``` ### Controller Name Suffix -###### [Style [Y124](#Style-Y124)] +###### [Style [Y124](#style-y124)] - Append the controller name with the suffix `Controller` or with no suffix. Choose 1, not both. @@ -1827,7 +1827,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see ``` ### Factory Names -###### [Style [Y125](#Style-Y125)] +###### [Style [Y125](#style-y125)] - Use consistent names for all factories named after their feature. Use camel-casing for services and factories. @@ -1847,7 +1847,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see ``` ### Directive Component Names -###### [Style [Y126](#Style-Y126)] +###### [Style [Y126](#style-y126)] - Use consistent names for all directives using camel-case. Use a short prefix to describe the area that the directives belong (some example are company prefix or project prefix). @@ -1869,7 +1869,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see ``` ### Modules -###### [Style [Y127](#Style-Y127)] +###### [Style [Y127](#style-y127)] - When there are multiple modules, the main module file is named `app.module.js` while other dependent modules are named after what they represent. For example, an admin module is named `admin.module.js`. The respective registered module names would be `app` and `admin`. A single module app might be named `app.js`, omitting the module moniker. @@ -1880,7 +1880,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see *Why?*: Provides easy way to use task automation to load all module definitions first, then all other angular files (for bundling). ### Configuration -###### [Style [Y128](#Style-Y128)] +###### [Style [Y128](#style-y128)] - Separate configuration for a module into its own file named after the module. A configuration file for the main `app` module is named `app.config.js` (or simply `config.js`). A configuration for a module named `admin.module.js` is named `admin.config.js`. @@ -1889,7 +1889,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see *Why?*: Provides a identifiable place to set configuration for a module. ### Routes -###### [Style [Y129](#Style-Y129)] +###### [Style [Y129](#style-y129)] - Separate route configuration into its own file. Examples might be `app.route.js` for the main module and `admin.route.js` for the `admin` module. Even in smaller apps I prefer this separation from the rest of the configuration. An alternative is a longer name such as `admin.config.route.js`. @@ -1897,7 +1897,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see ## Application Structure LIFT Principle ### LIFT -###### [Style [Y140](#Style-Y140)] +###### [Style [Y140](#style-y140)] - Structure your app such that you can `L`ocate your code quickly, `I`dentify the code at a glance, keep the `F`lattest structure you can, and `T`ry to stay DRY. The structure should follow these 4 basic guidelines. @@ -1911,7 +1911,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see 4. `T`ry to stay DRY (Don’t Repeat Yourself) or T-DRY ### Locate -###### [Style [Y141](#Style-Y141)] +###### [Style [Y141](#style-y141)] - Make locating your code intuitive, simple and fast. @@ -1936,21 +1936,21 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see ``` ### Identify -###### [Style [Y142](#Style-Y142)] +###### [Style [Y142](#style-y142)] - When you look at a file you should instantly know what it contains and represents. *Why?*: You spend less time hunting and pecking for code, and become more efficient. If this means you want longer file names, then so be it. Be descriptive with file names and keeping the contents of the file to exactly 1 component. Avoid files with multiple controllers, multiple services, or a mixture. There are deviations of the 1 per file rule when I have a set of very small features that are all related to each other, they are still easily identifiable. ### Flat -###### [Style [Y143](#Style-Y143)] +###### [Style [Y143](#style-y143)] - Keep a flat folder structure as long as possible. When you get to 7+ files, begin considering separation. *Why?*: Nobody wants to search 7 levels of folders to find a file. Think about menus on web sites … anything deeper than 2 should take serious consideration. In a folder structure there is no hard and fast number rule, but when a folder has 7-10 files, that may be time to create subfolders. Base it on your comfort level. Use a flatter structure until there is an obvious value (to help the rest of LIFT) in creating a new folder. ### T-DRY (Try to Stick to DRY) -###### [Style [Y144](#Style-Y144)] +###### [Style [Y144](#style-y144)] - Be DRY, but don't go nuts and sacrifice readability. @@ -1961,21 +1961,21 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see ## Application Structure ### Overall Guidelines -###### [Style [Y150](#Style-Y150)] +###### [Style [Y150](#style-y150)] - Have a near term view of implementation and a long term vision. In other words, start small and but keep in mind on where the app is heading down the road. All of the app's code goes in a root folder named `app`. All content is 1 feature per file. Each controller, service, module, view is in its own file. All 3rd party vendor scripts are stored in another root folder and not in the `app` folder. I didn't write them and I don't want them cluttering my app (`bower_components`, `scripts`, `lib`). Note: Find more details and reasoning behind the structure at [this original post on application structure](http://www.johnpapa.net/angular-app-structuring-guidelines/). ### Layout -###### [Style [Y151](#Style-Y151)] +###### [Style [Y151](#style-y151)] - Place components that define the overall layout of the application in a folder named `layout`. These may include a shell view and controller may act as the container for the app, navigation, menus, content areas, and other regions. *Why?*: Organizes all layout in a single place re-used throughout the application. ### Folders-by-Feature Structure -###### [Style [Y152](#Style-Y152)] +###### [Style [Y152](#style-y152)] - Create folders named for the feature they represent. When a folder grows to contain more than 7 files, start to consider creating a folder for them. Your threshold may be different, so adjust as needed. @@ -2073,28 +2073,28 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see ## Modularity ### Many Small, Self Contained Modules -###### [Style [Y160](#Style-Y160)] +###### [Style [Y160](#style-y160)] - Create small modules that encapsulate one responsibility. *Why?*: Modular applications make it easy to plug and go as they allow the development teams to build vertical slices of the applications and roll out incrementally. This means we can plug in new features as we develop them. ### Create an App Module -###### [Style [Y161](#Style-Y161)] +###### [Style [Y161](#style-y161)] - Create an application root module whose role is pull together all of the modules and features of your application. Name this for your application. *Why?*: AngularJS encourages modularity and separation patterns. Creating an application root module whose role is to tie your other modules together provides a very straightforward way to add or remove modules from your application. ### Keep the App Module Thin -###### [Style [Y162](#Style-Y162)] +###### [Style [Y162](#style-y162)] - Only put logic for pulling together the app in the application module. Leave features in their own modules. *Why?*: Adding additional roles to the application root to get remote data, display views, or other logic not related to pulling the app together muddies the app module and make both sets of features harder to reuse or turn off. ### Feature Areas are Modules -###### [Style [Y163](#Style-Y163)] +###### [Style [Y163](#style-y163)] - Create modules that represent feature areas, such as layout, reusable and shared services, dashboards, and app specific features (e.g. customers, admin, sales). @@ -2105,14 +2105,14 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see *Why?*: Separating feature areas into modules makes it easier to test the modules in isolation and reuse code. ### Reusable Blocks are Modules -###### [Style [Y164](#Style-Y164)] +###### [Style [Y164](#style-y164)] - Create modules that represent reusable application blocks for common services such as exception handling, logging, diagnostics, security, and local data stashing. *Why?*: These types of features are needed in many applications, so by keeping them separated in their own modules they can be application generic and be reused across applications. ### Module Dependencies -###### [Style [Y165](#Style-Y165)] +###### [Style [Y165](#style-y165)] - The application root module depends on the app specific feature modules, the feature modules have no direct dependencies, the cross-application modules depend on all generic modules. @@ -2133,7 +2133,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see ## Startup Logic ### Configuration -###### [Style [Y170](#Style-Y170)] +###### [Style [Y170](#style-y170)] - Inject code into [module configuration](https://docs.angularjs.org/guide/module#module-loading-dependencies) that must be configured before running the angular app. Ideal candidaes include providers and constants. @@ -2165,7 +2165,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see ``` ### Run Blocks -###### [Style [Y171](#Style-Y171)] +###### [Style [Y171](#style-y171)] - Any code that needs to run when an application starts should be declared in a factory, exposed via a function, and injected into the [run block](https://docs.angularjs.org/guide/module#module-loading-dependencies). @@ -2189,14 +2189,14 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see ## Angular $ Wrapper Services ### $document and $window -###### [Style [Y180](#Style-Y180)] +###### [Style [Y180](#style-y180)] - Use [`$document`](https://docs.angularjs.org/api/ng/service/$document) and [`$window`](https://docs.angularjs.org/api/ng/service/$window) instead of `document` and `window`. *Why?*: These services are wrapped by Angular and more easily testable than using document and window in tests. This helps you avoid having to mock document and window yourself. ### $timeout and $interval -###### [Style [Y181](#Style-Y181)] +###### [Style [Y181](#style-y181)] - Use [`$timeout`](https://docs.angularjs.org/api/ng/service/$timeout) and [`$interval`](https://docs.angularjs.org/api/ng/service/$interval) instead of `setTimeout` and `setInterval` . @@ -2208,7 +2208,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see Unit testing helps maintain clean code, as such I included some of my recommendations for unit testing foundations with links for more information. ### Write Tests with Stories -###### [Style [Y190](#Style-Y190)] +###### [Style [Y190](#style-y190)] - Write a set of tests for every story. Start with an empty test and fill them in as you write the code for the story. @@ -2235,7 +2235,7 @@ Unit testing helps maintain clean code, as such I included some of my recommenda ``` ### Testing Library -###### [Style [Y191](#Style-Y191)] +###### [Style [Y191](#style-y191)] - Use [Jasmine](http://jasmine.github.io/) or [Mocha](http://visionmedia.github.io/mocha/) for unit testing. @@ -2244,7 +2244,7 @@ Unit testing helps maintain clean code, as such I included some of my recommenda Note: When using Mocha, also consider choosing an assert library such as [Chai](http://chaijs.com). ### Test Runner -###### [Style [Y192](#Style-Y192)] +###### [Style [Y192](#style-y192)] - Use [Karma](http://karma-runner.github.io) as a test runner. @@ -2257,7 +2257,7 @@ Unit testing helps maintain clean code, as such I included some of my recommenda *Why?*: Karma works well with task automation leaders such as [Grunt](http://www.gruntjs.com) (with [grunt-karma](https://github.com/karma-runner/grunt-karma)) and [Gulp](http://www.gulpjs.com) (with [gulp-karma](https://github.com/lazd/gulp-karma)). ### Stubbing and Spying -###### [Style [Y193](#Style-Y193)] +###### [Style [Y193](#style-y193)] - Use Sinon for stubbing and spying. @@ -2266,7 +2266,7 @@ Unit testing helps maintain clean code, as such I included some of my recommenda *Why?*: Sinon makes it easier to toggle between Jasmine and Mocha, if you want to try both. ### Headless Browser -###### [Style [Y194](#Style-Y194)] +###### [Style [Y194](#style-y194)] - Use [PhantomJS](http://phantomjs.org/) to run your tests on a server. @@ -2275,14 +2275,14 @@ Unit testing helps maintain clean code, as such I included some of my recommenda Note: You should still test on all browsers in your environment, as appropriate for your target audience. ### Code Analysis -###### [Style [Y195](#Style-Y195)] +###### [Style [Y195](#style-y195)] - Run JSHint on your tests. *Why?*: Tests are code. JSHint can help identify code quality issues that may cause the test to work improperly. ### Alleviate Globals for JSHint Rules on Tests -###### [Style [Y196](#Style-Y196)] +###### [Style [Y196](#style-y196)] - Relax the rules on your test code to allow for common globals such as `describe` and `expect`. @@ -2299,7 +2299,7 @@ Unit testing helps maintain clean code, as such I included some of my recommenda ## Animations ### Usage -###### [Style [Y210](#Style-Y210)] +###### [Style [Y210](#style-y210)] - Use subtle [animations with AngularJS](https://docs.angularjs.org/guide/animations) to transition between states for views and primary visual elements. Include the [ngAnimate module](https://docs.angularjs.org/api/ngAnimate). The 3 keys are subtle, smooth, seamless. @@ -2308,14 +2308,14 @@ Unit testing helps maintain clean code, as such I included some of my recommenda *Why?*: Subtle animations can improve perceived performance as views transition. ### Sub Second -###### [Style [Y211](#Style-Y211)] +###### [Style [Y211](#style-y211)] - Use short durations for animations. I generally start with 300ms and adjust until appropriate. *Why?*: Long animations can have the reverse affect on User Experience and perceived performance by giving the appearance of a slow application. ### animate.css -###### [Style [Y212](#Style-Y212)] +###### [Style [Y212](#style-y212)] - Use [animate.css](http://daneden.github.io/animate.css/) for conventional animations. @@ -2332,7 +2332,7 @@ Unit testing helps maintain clean code, as such I included some of my recommenda ## Comments ### jsDoc -###### [Style [Y220](#Style-Y220)] +###### [Style [Y220](#style-y220)] - If planning to produce documentation, use [`jsDoc`](http://usejsdoc.org/) syntax to document function names, description, params and returns. Use `@namespace` and `@memberOf` to match your app structure. @@ -2384,7 +2384,7 @@ Unit testing helps maintain clean code, as such I included some of my recommenda ## JS Hint ### Use an Options File -###### [Style [Y230](#Style-Y230)] +###### [Style [Y230](#style-y230)] - Use JS Hint for linting your JavaScript and be sure to customize the JS Hint options file and include in source control. See the [JS Hint docs](http://www.jshint.com/docs/) for details on the options. @@ -2461,7 +2461,7 @@ Unit testing helps maintain clean code, as such I included some of my recommenda ## Constants ### Vendor Globals -###### [Style [Y240](#Style-Y240)] +###### [Style [Y240](#style-y240)] - Create an AngularJS Constant for vendor libraries' global variables. @@ -2487,7 +2487,7 @@ Unit testing helps maintain clean code, as such I included some of my recommenda Use file templates or snippets to help follow consistent styles and patterns. Here are templates and/or snippets for some of the web development editors and IDEs. ### Sublime Text -###### [Style [Y250](#Style-Y250)] +###### [Style [Y250](#style-y250)] - AngularJS snippets that follow these styles and guidelines. @@ -2504,7 +2504,7 @@ Use file templates or snippets to help follow consistent styles and patterns. He ``` ### Visual Studio -###### [Style [Y251](#Style-Y251)] +###### [Style [Y251](#style-y251)] - AngularJS file templates that follow these styles and guidelines can be found at [SideWaffle](http://www.sidewaffle.com) @@ -2513,7 +2513,7 @@ Use file templates or snippets to help follow consistent styles and patterns. He - Restart Visual Studio ### WebStorm -###### [Style [Y252](#Style-Y252)] +###### [Style [Y252](#style-y252)] - AngularJS snippets and file templates that follow these styles and guidelines. You can import them into your WebStorm settings: From 89b50887262c96d385dbe4b97aed83cd3e90d73c Mon Sep 17 00:00:00 2001 From: angelochiello Date: Fri, 21 Nov 2014 09:32:14 +0100 Subject: [PATCH 026/567] Pull Request #136 changes Edited to match PR #136 and minor translation changes. --- i18n/it-IT.md | 83 ++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 82 insertions(+), 1 deletion(-) diff --git a/i18n/it-IT.md b/i18n/it-IT.md index 7e0f36fd..50ecc376 100644 --- a/i18n/it-IT.md +++ b/i18n/it-IT.md @@ -56,6 +56,7 @@ Nonostante questa guida spieghi i *cosa*, *come* e *perché*, trovo che sia di a ## Responsabilità singola ### Regola dell'1 +###### [Stile [Y001](#stile-y001)] - Definire 1 componente per file. @@ -109,6 +110,7 @@ Nonostante questa guida spieghi i *cosa*, *come* e *perché*, trovo che sia di a ## IIFE ### JavaScript Closures +###### [Stile [Y010](#stile-y010)] - Racchiudi i componenti di AngularJS in una Immediately Invoked Function Expression (IIFE) (Espressione di funzione immediatamente chiamata). @@ -174,12 +176,14 @@ Nonostante questa guida spieghi i *cosa*, *come* e *perché*, trovo che sia di a ## Moduli ### Evitare la collisione di nomi +###### [Stile [Y020](#stile-y020)] - Usa una convenzione unica per i nomi con separatori per sotto moduli. *Perché?*: Nomi unici aiutano ad evitare la collisione di nomi dei moduli. I separatori aiutano a definire gerarchie di moduli e dei propri sotto moduli. Per esempio `app` potrebbe essere il modulo principale mentre `app.dashboard` e `app.users` potrebbero essere moduli che sono usati come dipendenze di `app`. ### Definizioni (altrimenti noti come Setter) +###### [Stile [Y021](#stile-y021)] - Dichiara moduli senza una variabile usando la sintassi setter. @@ -209,6 +213,7 @@ Nonostante questa guida spieghi i *cosa*, *come* e *perché*, trovo che sia di a ``` ### Getter +###### [Stile [Y022](#stile-y022)] - Usando un modulo, evita l'uso di una variabile e piuttosto usa la concatenazione con la sintassi getter. @@ -232,6 +237,7 @@ Nonostante questa guida spieghi i *cosa*, *come* e *perché*, trovo che sia di a ``` ### Setting vs Getting +###### [Stile [Y023](#stile-y023)] - Setta solo una volta e prendi (get) per tutte le altre istanze. @@ -241,6 +247,7 @@ Nonostante questa guida spieghi i *cosa*, *come* e *perché*, trovo che sia di a - Usa `angular.module('app');` per prendere (get) un modulo. ### Funzioni con un nome vs funzioni anonime +###### [Stile [Y024](#stile-y024)] - Usa funzioni che hanno un nome piuttosto che passare una funzione anonima come in una callback. @@ -279,6 +286,7 @@ Nonostante questa guida spieghi i *cosa*, *come* e *perché*, trovo che sia di a ## Controller ### Sintassi controllerAs nella View +###### [Stile [Y030](#stile-y030)] - Usa la sintassi [`controllerAs`](http://www.johnpapa.net/do-you-like-your-angular-controllers-with-or-without-sugar/) al posto della sintassi `classico controller con $scope`. @@ -303,6 +311,7 @@ Nonostante questa guida spieghi i *cosa*, *come* e *perché*, trovo che sia di a ``` ### Sintassi controllerAs nel Controller +###### [Stile [Y031](#stile-y031)] - Usa la sintassi `controllerAs` al posto della sintassi `classico controller con $scope`. @@ -329,6 +338,7 @@ Nonostante questa guida spieghi i *cosa*, *come* e *perché*, trovo che sia di a ``` ### controllerAs con vm +###### [Stile [Y032](#stile-y032)] - Usa una variabile che "catturi" `this` quando si utilizza la sintassi `controllerAs`. Scegli un nome della variabile consistente come `vm`, che sta per ViewModel. @@ -368,6 +378,7 @@ Nonostante questa guida spieghi i *cosa*, *come* e *perché*, trovo che sia di a ``` ### Membri che possono fare il bind in cima +###### [Stile [Y033](#stile-y033)] - Poni i membri che possono fare il bind in cima al controller, in ordine alfabetico, piuttosto che dispersi in tutto il codice del controller. @@ -456,6 +467,7 @@ Nonostante questa guida spieghi i *cosa*, *come* e *perché*, trovo che sia di a ``` ### Dichiarazioni di funzione per nascondere i dettagli di implementazione +###### [Stile [Y034](#stile-y034)] - Usa le dichiarazioni di funzione per nascondere i dettagli di implementazione. Tieni i membri che possono fare il binding in cima. Quando necessiti di fare binding a una funzione nel controller, puntalo ad una dichiarazione di funzione che compaia dopo nel file. Questo è direttamente collegabile con la sezione Membri che possono fare il binding in cima. Per ulteriori dettagli guarda [questo post](http://www.johnpapa.net/angular-function-declarations-function-expressions-and-readable-code) (in inglese). @@ -530,6 +542,7 @@ Nonostante questa guida spieghi i *cosa*, *come* e *perché*, trovo che sia di a ``` ### Rimandare la logica del Controller +###### [Stile [Y035](#stile-y035)] - Rimandare la logica in un controller delegandola ai service e factory. @@ -570,12 +583,14 @@ Nonostante questa guida spieghi i *cosa*, *come* e *perché*, trovo che sia di a ``` ### Tenere i controller "a fuoco" +###### [Stile [Y037](#stile-y037)] - Definisci un controller per vista e prova a non utilizzare il controller per altre view. Piuttosto, sposta la logica riutilizzabile alle factory e mantieni il controller semplice ed a fuoco sulla propria view. *Perché?*: Riutilizzare i controller con diverse view è precario e sono necessari dei buoni test end to end (e2e) per assicurarne la stabilità in applicazioni su larga scala. ### Assegnazione dei Controller +###### [Stile [Y038](#stile-y038)] - Quando un controller deve essere accoppiato ad una view ed un componente può essere riutilizzato da altri controller o view, definisci i controller insieme alle loro route. @@ -634,6 +649,7 @@ Nonostante questa guida spieghi i *cosa*, *come* e *perché*, trovo che sia di a ## Service ### Singleton +###### [Stile [Y040](#stile-y040)] - I Service sono istanziati con la keyword `new`, usa `this` per metodi e variabili pubbliche. Dal momento che sono molto simili alle factory, usa queste ultime per consistenza. @@ -672,16 +688,19 @@ Nonostante questa guida spieghi i *cosa*, *come* e *perché*, trovo che sia di a ## Factory ### Singola responsabilità +###### [Stile [Y050](#stile-y050)] - Le factory dovrebbero avere la [singola responsabilità](http://en.wikipedia.org/wiki/Single_responsibility_principle) che è incapsulata nel proprio contesto. Una volta che una factory eccede quello che è un singolo scopo, una nuova factory dovrebbe essere creata. ### Singleton +###### [Stile [Y051](#stile-y051)] - Le factory sono singleton e ritornano un oggetto che contiene i membri del servizio. Nota: [Tutti i servizi di AngularJS sono singleton](https://docs.angularjs.org/guide/services). ### Membri accessibili in cima +###### [Stile [Y052](#stile-y052)] - Esponi tutti i membri richiamabili del servizio (l'interfaccia) in cima, usando una tecnica derivata dal [Revealing Module Pattern](http://addyosmani.com/resources/essentialjsdesignpatterns/book/#revealingmodulepatternjavascript). @@ -739,6 +758,7 @@ Nonostante questa guida spieghi i *cosa*, *come* e *perché*, trovo che sia di a ![Factory che usano "Above the Fold"](https://raw.githubusercontent.com/johnpapa/angularjs-styleguide/master/assets/above-the-fold-2.png) ### Dichiarazioni di funzione per nascondere i dettagli di implementazione +###### [Stile [Y053](#stile-y053)] - Usa le dichiarazioni di funzioni per nascondere i dettagli di implementazione. Tieni i membri accessibili della factory in cima. Puntali alle dichiarazioni di funzioni che compaiono dopo nel file. Per ulteriori dettagli guarda [questo post](http://www.johnpapa.net/angular-function-declarations-function-expressions-and-readable-code) (in inglese). @@ -840,6 +860,7 @@ Nonostante questa guida spieghi i *cosa*, *come* e *perché*, trovo che sia di a ## Data Service ### Separare le chiamate ai dati +###### [Stile [Y060](#stile-y060)] - Rivedi la logica per gestire le operazioni con i dati e con la loro interazione delegandola ad una factory. @@ -916,6 +937,7 @@ Nonostante questa guida spieghi i *cosa*, *come* e *perché*, trovo che sia di a ``` ### Ritornare una promessa dalle chiamate ai dati +###### [Stile [Y061](#stile-y061)] - Quando si chiama un servizio ai dati che ritorna una promessa come $http, ritorna a tua volta una promessa nella tua funzione di chiamata. @@ -963,6 +985,7 @@ Nonostante questa guida spieghi i *cosa*, *come* e *perché*, trovo che sia di a ## Directive ### Limite di 1 per file +###### [Stile [Y070](#stile-y070)] - Crea una directive per file. Nomina il file per la directive. @@ -1054,12 +1077,14 @@ Nonostante questa guida spieghi i *cosa*, *come* e *perché*, trovo che sia di a Nota: Ci sono molte opzioni per i nomi delle directive, in particolare dal momento che possono essere usate in ambiti stretti o larghi. Scegline uno che sia chiaro e distino che dia senso alla directive e il suo nome del file. Alcuni esempi sono sotto ma vedi la sezione sulla nomenclatura per maggiori raccomandazioni. ### Limiti alla manipolazione del DOM +###### [Stile [Y072](#stile-y072)] - Quando devi manipolare direttamente il DOM, usa una directive. Se possono essere usate delle alternative come settare stili CSS o i [servizi di animazione](https://docs.angularjs.org/api/ngAnimate), templating di Angular, [`ngShow`](https://docs.angularjs.org/api/ng/directive/ngShow) oppure [`ngHide`](https://docs.angularjs.org/api/ng/directive/ngHide), piuttosto usa questi. Per esempio, se la directive semplicemente nasconde e mostra, usa ngHide/ngShow. *Perché?*: Manipolare il DOM può essere difficoltoso da testare, debuggare e spesso ci sono modi migliori (p.e. CSS, animazioni, template) ### Utilizza un prefisso unico per la Directive +###### [Stile [Y073](#stile-y073)] - Utilizza un corto, unico e descrittivo prefisso alla directive come `acmeSalesCustomerInfo` che è dichiarato in HTML come `acme-sales-customer-info`. @@ -1068,6 +1093,7 @@ Nonostante questa guida spieghi i *cosa*, *come* e *perché*, trovo che sia di a Nota: Evita `ng-` poiché queste sono riservate per le directive di AngularJS. Cerca directive che sono largamente utilizzate per evitare il conflitto di nomi, come `ion-` per il [Framework Ionic ](http://ionicframework.com/). ### Restringi a Elementi and Attributi +###### [Stile [Y074](#stile-y074)] - Quando crei una directive che abbia senso come elemento a se stante, considera la restrizione a `E` (elemento custom) e facoltativamente restringere a `A` (attributo custom). In generale, se può essere il suo stesso controllo, `E` è appropriato. Le linee guida generali sono di permettere `EA` ma tendono verso l'implementazione come un elemento quando è a se stante e come attributo quando accresce il proprio elemento DOM esistente. @@ -1129,6 +1155,7 @@ Nonostante questa guida spieghi i *cosa*, *come* e *perché*, trovo che sia di a ``` ### Directive e ControllerAs +###### [Stile [Y075](#stile-y075)] - Usa la sintassi `controller as` con una directive per essere consistente con l'utilizzo di `controller as` con una coppia di view e controller. @@ -1193,6 +1220,7 @@ Nonostante questa guida spieghi i *cosa*, *come* e *perché*, trovo che sia di a ## Risoluzioni di promesse per un controller ### Promesse di attivazione di un Controller +###### [Stile [Y080](#stile-y080)] - Risolvi la logica di start-up per un controller in una funzione `activate`. @@ -1235,6 +1263,7 @@ Nonostante questa guida spieghi i *cosa*, *come* e *perché*, trovo che sia di a ``` ### Promesse risolte nel route +###### [Stile [Y081](#stile-y081)] - Quando un controller dipende dalla dal fatto che una promessa sia risolta risolvi queste dipendenze nel `$routeProvider` prima che la logica del controller sia eseguita. Se hai bisogno di annullare condizionalmente una route prima che il controller sia attivato, usa un resolver della route. @@ -1299,6 +1328,7 @@ Nonostante questa guida spieghi i *cosa*, *come* e *perché*, trovo che sia di a ## Annotazioni manuali per la Dependency Injection ### Non sicuro per la minificazione +###### [Stile [Y090](#stile-y090)] - Evita di usare abbreviazioni sintattiche per la dichiarazione di dipendenze senza usare un approccio a prova di minificazione. @@ -1322,6 +1352,7 @@ Nonostante questa guida spieghi i *cosa*, *come* e *perché*, trovo che sia di a ``` ### Indentificazione manuale delle dipendenze +###### [Stile [Y091](#stile-y091)] - Usa `$inject` per identificare manualmente le tue dipendenze per i componenti di AngularJS. @@ -1395,6 +1426,7 @@ Nonostante questa guida spieghi i *cosa*, *come* e *perché*, trovo che sia di a ``` ### Idetificazione manuale delle dipendenze di resolver della route +###### [Stile [Y092](#stile-y092)] - Usa $inject per identificare manualmente le tue dipendenze di resolver della route per i componenti di AngularJS. @@ -1427,6 +1459,7 @@ Nonostante questa guida spieghi i *cosa*, *come* e *perché*, trovo che sia di a ## Minificazione e Annotazioni ### ng-annotate +###### [Stile [Y100](#stile-y100)] - Usa [ng-annotate](//github.com/olov/ng-annotate) per [Gulp](http://gulpjs.com) o [Grunt](http://gruntjs.com) e commenta le funzioni che necessitano di automatizzare il dependency injection usando `/** @ngInject */` @@ -1504,6 +1537,7 @@ Nonostante questa guida spieghi i *cosa*, *come* e *perché*, trovo che sia di a `` ### Usa Gulp o Grunt per ng-annotate +###### [Stile [Y101](#stile-y101)] - Usa [gulp-ng-annotate](https://www.npmjs.org/package/gulp-ng-annotate) o [grunt-ng-annotate](https://www.npmjs.org/package/grunt-ng-annotate) in un task di build automatizzato. Inietta `/* @ngInject */` prima di qualunque funzione che abbia delle dipendenze. @@ -1537,6 +1571,7 @@ Nonostante questa guida spieghi i *cosa*, *come* e *perché*, trovo che sia di a ## Gestione delle eccezioni ### decoratori (decorator) +###### [Stile [Y110](#stile-y110)] - Usa un [decorator](https://docs.angularjs.org/api/auto/service/$provide#decorator), al momento del config una un servizio [`$provide`](https://docs.angularjs.org/api/auto/service/$provide), sul servizio [`$exceptionHandler`](https://docs.angularjs.org/api/ng/service/$exceptionHandler) per eseguire azioni ad hoc quando l'eccezione occorre. @@ -1577,6 +1612,7 @@ Nonostante questa guida spieghi i *cosa*, *come* e *perché*, trovo che sia di a ``` ### Ricevitore di eccezioni +###### [Stile [Y111](#stile-y111)] - Crea una factory che espone un'interfaccia per ricevere ed elegantemente gestire le eccezioni. @@ -1607,6 +1643,7 @@ Nonostante questa guida spieghi i *cosa*, *come* e *perché*, trovo che sia di a ``` ### Errori di routing +###### [Stile [Y112](#stile-y112)] - Gestisti e fai il log di tutti gli errori di routing usando [`$routeChangeError`](https://docs.angularjs.org/api/ngRoute/service/$route#$routeChangeError). @@ -1646,6 +1683,7 @@ Nonostante questa guida spieghi i *cosa*, *come* e *perché*, trovo che sia di a ## Nomenclatura ### Linee guida per assegnare i nomi +###### [Stile [Y120](#stile-y120)] - Usa nomi consistenti per tutti i componenti seguendo uno schema che descriva le funzionalità dei componenti e poi (a scelta) il suo tipo. Lo schema che consiglio è `feature.type.js`. Ci sono 2 nomi per la maggior parte dei componenti: * il nome del file (`avengers.controller.js`) @@ -1656,6 +1694,7 @@ Nonostante questa guida spieghi i *cosa*, *come* e *perché*, trovo che sia di a *Perché?*: Le convezioni sulla nomenclatura dovrebbe semplicemente aiutare a trovare il tuo codice più rapidamente e renderlo più semplice da comprendere. ### Nomi dei file per funzionalità +###### [Stile [Y121](#stile-y121)] - Usa nomi consistenti per tutti i componenti seguendo uno schema che descriva le funzionalità dei componenti e poi (a scelta) il suo tipo. Lo schema che consiglio è `feature.type.js`. @@ -1722,6 +1761,7 @@ Nonostante questa guida spieghi i *cosa*, *come* e *perché*, trovo che sia di a ``` ### Nomi dei file di test +###### [Stile [Y122](#stile-y122)] - Nomina le specifiche dei test in modo similare al componente che testano aggiundendo il suffisso `spec`. @@ -1740,6 +1780,7 @@ Nonostante questa guida spieghi i *cosa*, *come* e *perché*, trovo che sia di a ``` ### Nomi dei controller +###### [Stile [Y123](#stile-y123)] - Usa nomi consistenti per tutti i controller nominandoli come le loro funzionalità. Usa UpperCamelCase per i controller, dal momento che sono costruttori. @@ -1761,6 +1802,7 @@ Nonostante questa guida spieghi i *cosa*, *come* e *perché*, trovo che sia di a ``` ### Suffisso nel nome di un controller +###### [Stile [Y124](#stile-y124)] - Aggiungi `Controller` alla fine del nome del controller o no. Segli 1 non entrambi. @@ -1795,6 +1837,7 @@ Nonostante questa guida spieghi i *cosa*, *come* e *perché*, trovo che sia di a ``` ### Nomi delle factory +###### [Stile [Y125](#stile-y125)] - Usa una nomenclatura consistente per tutte le factory dando i nomi date le loro funzionalità. Usa il camel-case per service e factory. @@ -1814,6 +1857,7 @@ Nonostante questa guida spieghi i *cosa*, *come* e *perché*, trovo che sia di a ``` ### Nomi dei componenti directive +###### [Stile [Y126](#stile-y126)] - Usa nomi consistenti per putte le directive usando il camel-case. Usa un breve prefisso che descriva l'area alla quale la directive appartiene (alcuni esempi sono prefissi relativi all'azienda o al progetto). @@ -1835,6 +1879,7 @@ Nonostante questa guida spieghi i *cosa*, *come* e *perché*, trovo che sia di a ``` ### Moduli +###### [Stile [Y127](#stile-y127)] - Quando i sono moduli multipli, il modulo principale è nominato come `app.module.js` mentre altri moduli dipendenti prendono i nomi da ciò che rappresentano. Per esempio, un modulo admin è nominato `admin.module.js`. I rispettivi nomi con i quali sono registrati saranno `app` e `admin`. Una app a modulo singolo si chiamerà `app.js`, omettendo l'appellativo module. @@ -1845,6 +1890,7 @@ Nonostante questa guida spieghi i *cosa*, *come* e *perché*, trovo che sia di a *Perché?*: Fornisci un modo semplice al fine di usare processi automatici per caricare prima tutte le definizioni di moduli, successivamente tutti gli altri file di Angular (per il bundling). ### Configurazione +###### [Stile [Y128](#stile-y128)] - Separa la configurazione di un modulo nel proprio file chiamato come il modulo. Un file di configurazione per il modulo principale `app` è chiamato `app.config.js` (o semplicemente `config.js`). Un file di configurazione per un modulo chiamato `admin.module.js` sarà `admin.config.js`. @@ -1853,6 +1899,7 @@ Nonostante questa guida spieghi i *cosa*, *come* e *perché*, trovo che sia di a *Perché?*: Fornisci una posizione identificabile per settare la configurazione di un modulo. ### Route +###### [Stile [Y129](#stile-y129)] - Separa la configurazione delle route nei propri file. Esempi possono essere `app.route.js` per il modulo principale e `admin.route.js` per il modulo `admin`. Anche in piccole app preferisco questa separazione dal resto della configurazione. Una alternativa è un nome più esteso quale `admin.config.route.js`. @@ -1860,6 +1907,7 @@ Nonostante questa guida spieghi i *cosa*, *come* e *perché*, trovo che sia di a ## Principio "LIFT" per la struttura dell'applicazione ### LIFT +###### [Stile [Y140](#stile-y140)] - Struttura la tua app tale da poter `L`ocate (localizzare) il codice facilmente, `I`dentify (identificare) il codice con uno sguardo, tenere la struttura più `F`lattest (piatta) che puoi, e `T`ry (provare) a rimanere DRY (Don't Repeat Yourself - Non ripetersi). La struttura dovrebbe seguire queste 4 linee guida basilari. @@ -1873,6 +1921,7 @@ Nonostante questa guida spieghi i *cosa*, *come* e *perché*, trovo che sia di a 4. `T`ry (prova) a restare DRY (Don’t Repeat Yourself) o T-DRY ### Locate - localizzare +###### [Stile [Y141](#stile-y141)] - Rendi intuitivo, semplice e facile localizzare il codice. @@ -1897,12 +1946,14 @@ Nonostante questa guida spieghi i *cosa*, *come* e *perché*, trovo che sia di a ``` ### Identify - identificare +###### [Stile [Y142](#stile-y142)] - Guardando un file dovresti istantaneamente sapere ciò che contiene e cosa rappresenta. *Perché?*: Spendi meno tempo a rintracciare e beccare il codice e diventa più efficiente. Se per fare ciò hai bisogno di nomi dei file più lunghi, fallo. Si descrittivo con i nomi dei file e tieni il contenuto del file con esattamente 1 componente. Evita file con più di un controller, diversi service o un misto. Ci sono delle eccezioni alla regola "1 per file" ovvero quando ho una serie di piccole funzionalità correlate l'un l'altra: continuano ad essere facilmente identificabili. ### Flat - piatto +###### [Stile [Y143](#stile-y143)] - Tieni la struttura delle cartelle piatta il più a lungo possibile. Quando arrivi ad avere 7 o più file, inizia a considerarne una separazione. @@ -1910,6 +1961,7 @@ Nonostante questa guida spieghi i *cosa*, *come* e *perché*, trovo che sia di a *Perché?*: Nessuno vuole cercare 7 livelli di cartelle per trovare un file. Pensa ai menù di un sito web.. qualunque cosa oltre i 2 livelli dovrebbe esser presa in considerazione. Nella struttura di cartella non c'è una regola con un numero esattamente definito ma quando una cartella contiene 7-10 file, è il momento di creare una sottocartella. Basalo su un livello a te comodo. Usa una struttura più piatta fino a che c'è l'ovvia necessità (praticando il resto dei principi LIFT) di creare una nuova cartella. ### T-DRY (Try to Stick to DRY) - Prova a non ripeterti +###### [Stile [Y144](#stile-y144)] - Si DRY, ma non diventare pazzo e sacrificare la leggibilità. @@ -1920,18 +1972,21 @@ Nonostante questa guida spieghi i *cosa*, *come* e *perché*, trovo che sia di a ## Struttura dell'applicazione ### Linee guida generali +###### [Stile [Y150](#stile-y150)] - Abbi una visione a breve termine dell'implementazione e una a lunga scadenza. In altre parole, parti in piccolo ma tieni in mente su dove l'app è diretta lungo il percorso. Tutto il codice dell'app va nella cartella principale chiamata `app`. Tutti i contenuti rispettano 1 funzione per file. Ogni controller, service, module, view nel proprio file. Tutti gli script di terze party sono poste in una altra cartella principale e non nella cartella `app`. Non le ho scritte e non voglio facciano disordine nella mia app (`bower_components`, `scripts`, `lib`). Nota: Trovi più dettagli e le motivazioni di questa struttura nel [post originale sulla struttura delle applicazioni](http://www.johnpapa.net/angular-app-structuring-guidelines/) (in inglese). ### Layout +###### [Stile [Y151](#stile-y151)] - Metti i componenti che definiscono il layout globale dell'applicazione in una cartella con il nome `layout`. Questi possono includere un shell view e controller che agiscono come contenitori per l'app, navigazione, menù, aree per i contenuti ed altre regioni. *Perché?*: Organizza tutto il layout in una sola posizione riutilizzabile lungo tutta l'applicazione. ### Struttura Cartella-per-Funzionalità +###### [Stile [Y152](#stile-y152)] - Crea cartelle che abbiamo in nome per la funzionalità che rappresentano. Quando una cartella cresce fino a contenere più di 7 file, inizia a considerare la creazione di un'altra cartella. La tua soglia potrebbe essere differente, aggiustala di conseguenza. @@ -2029,24 +2084,28 @@ Nonostante questa guida spieghi i *cosa*, *come* e *perché*, trovo che sia di a ## Modularità ### Molti moduli piccoli e autonomi +###### [Stile [Y160](#stile-y160)] - Crea moduli piccoli che incapsulino una responsabilità. *Perché?*: Applicazioni modulari rendono semplice l'inclusione dal momento che consentono ai team di sviluppo la costruzione di tagli verticali dell'applicazione e il suo roll out incrementale. Questo significa che è possibile aggiungere nuove funzionalità mentre vengono sviluppate. ### Creare un modulo App +###### [Stile [Y161](#stile-y161)] - Crea un modulo principale per l'applicazione il cui ruolo sia di mettere insieme tutti gli altri moduli e funzionalità della tua applicazione. Chiamalo con il nome della tua applicazione. *Perché?*: AngularJS incoraggia la modularità e schemi di separazione. La creazione di un modulo principale il cui ruolo sia quello di legante tra gli altri moduli consente un modo lineare di aggiungere o rimuovere moduli dall'applicazione. ### Tenere il modulo App snello +###### [Stile [Y162](#stile-y162)] - Nel modulo principale metti solo la logica che serva da collante per l'app. Lascia le funzioni ognuno al proprio modulo. *Perché?*: L'aggiunta di ruoli addizionali al modulo principale per il recupero dei dati, il mostrare viste o altra logica non correlata al tenere insieme l'applicazione sporca il modulo principale e rende entrambi gli insiemi di funzionalità più complessi da riusare o rimuovere. ### Aree di funzionalità sono Moduli +###### [Stile [Y163](#stile-y163)] - Crea moduli che rappresentino aree di funzionalità come layout, servizi riusabili e condivisi, pannelli di controllo e funzioni specifiche all'app (p.e. clienti, amministrazione, vendite). @@ -2057,12 +2116,14 @@ Nonostante questa guida spieghi i *cosa*, *come* e *perché*, trovo che sia di a *Perché?*: Separare aree di funzioni in moduli rende più semplice testare i moduli in isolamento e il riutilizzo del codice. ### Blocchi riutilizzabili sono Moduli +###### [Stile [Y164](#stile-y164)] - Crea moduli che rappresentino blocchi di applicazione riutilizzabili per servizi comuni quali la gestione delle eccezioni, il log, la diagnostica, sicurezza e il data stashing locale. *Perché?*: Questi tipi di funzionalità sono richieste in molte applicazioni, perciò tenerle separate in moduli possono essere generiche l'applicazione e riutilizzate in applicazioni diverse. ### Dipendenze dei Moduli +###### [Stile [Y165](#stile-y165)] - Il modulo principale dell'applicazione dipende dai moduli di funzionalità specifiche dell'app, i moduli delle funzionalità non hanno dipendenze dirette, moduli trans-applicazione dipendono da moduli generici. @@ -2083,6 +2144,7 @@ Nonostante questa guida spieghi i *cosa*, *come* e *perché*, trovo che sia di a ## Logica di Startup ### Configurazione +###### [Stile [Y170](#stile-y170)] - Inietta codice nel [modulo di configurazione](https://docs.angularjs.org/guide/module#module-loading-dependencies) che deve essere configurato prima dell'esecuzione dell'app angular. I candidati ideali includono provider e costanti. @@ -2114,6 +2176,7 @@ Nonostante questa guida spieghi i *cosa*, *come* e *perché*, trovo che sia di a ``` ### Blocchi Run +###### [Stile [Y171](#stile-y171)] - Qualunque codice che necessiti di essere eseguito quando un'applicazione si avvia dovrebbe essere dichiarato in una factory, esposto tramite funzione ed iniettato nel [blocco run](https://docs.angularjs.org/guide/module#module-loading-dependencies). @@ -2137,12 +2200,14 @@ Nonostante questa guida spieghi i *cosa*, *come* e *perché*, trovo che sia di a ## Wrapper dei Servizi $ di Angular ### $document e $window +###### [Stile [Y180](#stile-y180)] - Usa [`$document`](https://docs.angularjs.org/api/ng/service/$document) e [`$window`](https://docs.angularjs.org/api/ng/service/$window) al posto di `document` e `window`. *Perché?*: Questi servizi sono gestiti da Angular e più facilmente testabili che l'uso di document e window nei test. Ciò ti aiuta ad evitare di fare mock di document e window. ### $timeout e $interval +###### [Stile [Y181](#stile-y181)] - Usa [`$timeout`](https://docs.angularjs.org/api/ng/service/$timeout) e [`$interval`](https://docs.angularjs.org/api/ng/service/$interval) al posto di `setTimeout` e `setInterval` . @@ -2154,6 +2219,7 @@ Nonostante questa guida spieghi i *cosa*, *come* e *perché*, trovo che sia di a Gli unit test aiutano a mantenere il codice più chiaro, perciò ho incluso alcune mie raccomandazioni fondamentali per lo unit testing con link e ulteriori informazioni. ### Scrivi i test con le Storie +###### [Stile [Y190](#stile-y190)] - Scrivi un set di test per ogni storia. Inizia con un test vuoto e riempilo fino a scrivere il codice per la storia. @@ -2179,7 +2245,8 @@ Gli unit test aiutano a mantenere il codice più chiaro, perciò ho incluso alcu // continuare ``` -### Testing Library +### Librerie per i test +###### [Stile [Y191](#stile-y191)] - Usa [Jasmine](http://jasmine.github.io/) oppure [Mocha](http://visionmedia.github.io/mocha/) per lo unit testing. @@ -2188,6 +2255,7 @@ Gli unit test aiutano a mantenere il codice più chiaro, perciò ho incluso alcu Nota: Usando Mocha, tieni in considerazione di usare anche una libreria di asserzione come [Chai](http://chaijs.com). ### Esecutori di Test +###### [Stile [Y192](#stile-y192)] - Usa [Karma](http://karma-runner.github.io) come esecutore di test. @@ -2200,6 +2268,7 @@ Gli unit test aiutano a mantenere il codice più chiaro, perciò ho incluso alcu *Perché?*: Karma lavora bene con leader di automazione di processo quali [Grunt](http://www.gruntjs.com) (con [grunt-karma](https://github.com/karma-runner/grunt-karma)) e [Gulp](http://www.gulpjs.com) (con [gulp-karma](https://github.com/lazd/gulp-karma)). ### Stubbing e Spying +###### [Stile [Y193](#stile-y193)] - Usa Sinon per lo stubbing e spying. @@ -2208,6 +2277,7 @@ Gli unit test aiutano a mantenere il codice più chiaro, perciò ho incluso alcu *Perché?*: Sinon rende più semplice il passaggio tra Jasmine e Mocha, nel caso voglia usarli entrambi. ### Headless Browser +###### [Stile [Y194](#stile-y194)] - Usa [PhantomJS](http://phantomjs.org/) per eseguire i test su un server. @@ -2216,12 +2286,14 @@ Gli unit test aiutano a mantenere il codice più chiaro, perciò ho incluso alcu Nota: Dovresti in ogni caso testare tutti i browser del tuo ambiente, come appropriato per il pubblico che è il target. ### Analisi del codice +###### [Stile [Y195](#stile-y195)] - Esegui JSHint sui tuoi test. *Perché?*: I test sono codice. JSHint può aiutare ad identificare problemi di qualità del codice che causano l’improprio funzionamento del test. ### Alleviare le regole sulle variabili globali di JSHint per i Test +###### [Stile [Y196](#stile-y196)] - Rilassa le regole sul codice dei test per consentendoli per variabili globali comuni quali `describe` ed `expect`. @@ -2238,6 +2310,7 @@ Gli unit test aiutano a mantenere il codice più chiaro, perciò ho incluso alcu ## Animazioni ### Utilizzo +###### [Stile [Y210](#stile-y210)] - Usa sfumate [animazioni con AngularJS](https://docs.angularjs.org/guide/animations) per fare transizioni tra stati per viste ed elementi visuali primari. Includi il [modulo ngAnimate](https://docs.angularjs.org/api/ngAnimate). Le 3 chiavi sono sfumate, dolci e continue. @@ -2246,12 +2319,14 @@ Gli unit test aiutano a mantenere il codice più chiaro, perciò ho incluso alcu *Perché?*: Animazioni sfumate possono migliorare la percezione di prestazioni nella transizione tra le viste. ### Sotto il secondo +###### [Stile [Y211](#stile-y211)] - Usa animazioni che abbiano una durata breve. Generalmente parto con 300 ms e aggiusto finché non è appropriato. *Perché?*: Long animations can have the reverse affect on User Experience and perceived performance by giving the appearance of a slow application. ### animate.css +###### [Stile [Y212](#stile-y212)] - Usa [animate.css](http://daneden.github.io/animate.css/) per animazioni convenzionali. @@ -2268,6 +2343,7 @@ Gli unit test aiutano a mantenere il codice più chiaro, perciò ho incluso alcu ## Commenti ### jsDoc +###### [Stile [Y220](#stile-y220)] - Se hai intenzione di produrre documentazione, usa la sintassi di [`jsDoc`](http://usejsdoc.org/) per documentare nomi di funzione, descrizione, parametri e ciò che ritorna. Usa `@namespace` e `@memberOf` per adattarlo alla stuttura della tua app. @@ -2319,6 +2395,7 @@ Gli unit test aiutano a mantenere il codice più chiaro, perciò ho incluso alcu ## JSHint ### Usa un file di opzioni +###### [Stile [Y230](#stile-y230)] - Usa JS Hint per spazzolare il tuo JavaScript ed assicurati di ritagliare il file di opzioni di JS Hint e di includerlo nel source control . Vedi la [documentazione di JS Hint](http://www.jshint.com/docs/) per i dettagli sulle opzioni. @@ -2395,6 +2472,7 @@ Gli unit test aiutano a mantenere il codice più chiaro, perciò ho incluso alcu ## Costanti ### Variabili globali delle terze parti +###### [Stile [Y240](#stile-y240)] - Crea una costante di AngularJS per le variabili globali delle librerie di terze parti. @@ -2420,6 +2498,7 @@ Gli unit test aiutano a mantenere il codice più chiaro, perciò ho incluso alcu Usa file template o snippet che ti aiutino a seguire stili e schemi consistentemente. Qui trovi alcuni template e/o snippet per alcuni degli editor per lo sviluppo wbe e IDE. ### Sublime Text +###### [Stile [Y250](#stile-y250)] - Snippet di AngularJS che seguono questi stili e linee guida. @@ -2436,6 +2515,7 @@ Usa file template o snippet che ti aiutino a seguire stili e schemi consistentem ``` ### Visual Studio +###### [Stile [Y251](#stile-y251)] - I file dei template per Angular che seguono questi stili e linee guida possono essere trovati su [SideWaffle](http://www.sidewaffle.com) @@ -2444,6 +2524,7 @@ Usa file template o snippet che ti aiutino a seguire stili e schemi consistentem - Riavvia Visual Studio ### WebStorm +###### [Stile [Y252](#stile-y252)] - Snippet di Angular JS e file di template che seguono queste linee guida. Le puoi importare dentro i tuoi settaggi di WebStorm: From b2b63ff88484c5553b0b22058ba721e1a0d8b71a Mon Sep 17 00:00:00 2001 From: Vinicius Sabadim Fernandes Date: Fri, 21 Nov 2014 10:40:31 -0200 Subject: [PATCH 027/567] Translate for the topic 'Directives' (PT-BR) --- i18n/PT-BR.md | 81 ++++++++++++++++++++++++++++----------------------- 1 file changed, 44 insertions(+), 37 deletions(-) diff --git a/i18n/PT-BR.md b/i18n/PT-BR.md index 5a029998..abba315d 100644 --- a/i18n/PT-BR.md +++ b/i18n/PT-BR.md @@ -979,50 +979,53 @@ ou *Retorne uma promessa de chamadas de dados* **[⬆ De volta ao topo ⬆](#tabela-de-conte%C3%BAdo)** ## Directives +ou *Diretivas* + ### Limit 1 Per File +ou *Limite 1 por arquivo* - - Create one directive per file. Name the file for the directive. + - Crie uma diretiva (directive) por arquivo. Nomeie o arquivo pela diretiva. - *Why?*: It is easy to mash all the directives in one file, but difficult to then break those out so some are shared across apps, some across modules, some just for one module. + **Por que?**: É fácil misturar todas as diretivas em um arquivo, mas é difícil depois separá-las, já que algumas são compartilhadas entre aplicativos, outras pelos módulos (modules) e algumas somente para um módulo. - *Why?*: One directive per file is easy to maintain. + **Por que?**: Uma diretiva (directive) por arquivo é mais fácil de dar manutenção. ```javascript - /* avoid */ + /* evite */ /* directives.js */ angular .module('app.widgets') - /* order directive that is specific to the order module */ + /* diretiva de pedido (order) que é específica para o módulo de pedido */ .directive('orderCalendarRange', orderCalendarRange) - /* sales directive that can be used anywhere across the sales app */ + /* diretiva de vendas (sales) que pode ser usada em qualquer lugar do aplicativo de vendas */ .directive('salesCustomerInfo', salesCustomerInfo) - /* spinner directive that can be used anywhere across apps */ + /* diretiva de spinner que pode ser usada em qualquer lugar dos aplicativos */ .directive('sharedSpinner', sharedSpinner); function orderCalendarRange() { - /* implementation details */ + /* detalhes de implementação */ } function salesCustomerInfo() { - /* implementation details */ + /* detalhes de implementação */ } function sharedSpinner() { - /* implementation details */ + /* detalhes de implementação */ } ``` ```javascript - /* recommended */ + /* recomendado */ /* calendarRange.directive.js */ /** - * @desc order directive that is specific to the order module at a company named Acme + * @desc diretiva de pedido (order) que é específica para o módulo de pedido em uma companhia chamada Acme * @example
*/ angular @@ -1030,16 +1033,16 @@ ou *Retorne uma promessa de chamadas de dados* .directive('acmeOrderCalendarRange', orderCalendarRange); function orderCalendarRange() { - /* implementation details */ + /* detalhes de implementação */ } ``` ```javascript - /* recommended */ + /* recomendado */ /* customerInfo.directive.js */ /** - * @desc spinner directive that can be used anywhere across the sales app at a company named Acme + * @desc diretiva de spinner que pode ser usada em qualquer lugar de um aplicativo de vendas em uma companhia chamada Acme * @example
*/ angular @@ -1047,16 +1050,16 @@ ou *Retorne uma promessa de chamadas de dados* .directive('acmeSalesCustomerInfo', salesCustomerInfo); function salesCustomerInfo() { - /* implementation details */ + /* detalhes de implementação */ } ``` ```javascript - /* recommended */ + /* recomendado */ /* spinner.directive.js */ /** - * @desc spinner directive that can be used anywhere across apps at a company named Acme + * @desc diretiva de spinner que pode ser usada em qualquer lugar de aplicativo em uma companhia chamada Acme * @example
*/ angular @@ -1064,43 +1067,46 @@ ou *Retorne uma promessa de chamadas de dados* .directive('acmeSharedSpinner', sharedSpinner); function sharedSpinner() { - /* implementation details */ + /* detalhes de implementação */ } ``` - Note: There are many naming options for directives, especially since they can be used in narrow or wide scopes. Choose one that makes the directive and it's file name distinct and clear. Some examples are below, but see the naming section for more recommendations. + Nota: Há diferentes opções de nomear diretivas (directives), especialmente quando elas podem ser usadas em escopes (scopes) variados. Escolha uma que faça a diretiva e o nome do arquivo distinto e simples. Alguns exemplos são mostrados abaixo, mas veja a seção de nomeação para mais recomendações. ### Limit DOM Manipulation +ou *Limite a manipulação do DOM* - - When manipulating the DOM directly, use a directive. If alternative ways can be used such as using CSS to set styles or the [animation services](https://docs.angularjs.org/api/ngAnimate), Angular templating, [`ngShow`](https://docs.angularjs.org/api/ng/directive/ngShow) or [`ngHide`](https://docs.angularjs.org/api/ng/directive/ngHide), then use those instead. For example, if the directive simply hides and shows, use ngHide/ngShow. + - Quando estiver manipulando o DOM diretamente, utilize uma diretiva (directive). Se formas alternativas podem ser utilizadas, como utilizar CSS para setar estilos ou [serviços de animação (animation services)](https://docs.angularjs.org/api/ngAnimate), Angular templating, [`ngShow`](https://docs.angularjs.org/api/ng/directive/ngShow) ou [`ngHide`](https://docs.angularjs.org/api/ng/directive/ngHide), então prefira utilizá-los. Por exemplo, se uma diretiva simplesmente esconde ou mostra um elemento, use ngHide/ngShow. - *Why?*: DOM manipulation can be difficult to test, debug, and there are often better ways (e.g. CSS, animations, templates) + **Por que?**: A manipulação do DOM pode ser difícil de testar, debugar, e há melhores maneiras (ex: CSS, animações (animations), templates). ### Provide a Unique Directive Prefix +ou *Forneça um prefixo único para as diretivas* - - Provide a short, unique and descriptive directive prefix such as `acmeSalesCustomerInfo` which is declared in HTML as `acme-sales-customer-info`. + - Forneça um curto, único e descritivo prefixo para a diretiva, como `acmeSalesCustomerInfo`, que é declarado no HTML como `acme-sales-customer-info`. - *Why?*: The unique short prefix identifies the directive's context and origin. For example a prefix of `cc-` may indicate that the directive is part of a CodeCamper app while `acme-` may indicate a directive for the Acme company. + **Por que?**: Um prefixo curto e único identifica o contexto e a origem da diretiva. Por exemplo, o prefixo `cc-` pode indicar que a diretiva é parte de um aplicativo da CodeCamper, enquanto a diretiva `acme-` pode indicar uma diretiva para a companhia Acme. - Note: Avoid `ng-` as these are reserved for AngularJS directives.Research widely used directives to avoid naming conflicts, such as `ion-` for the [Ionic Framework](http://ionicframework.com/). + Nota: Evite `ng-`, pois são reservadas para as diretivas do AngularJS. Pesquisa largamente as diretivas utilizadas para evitar conflitos de nomes, como `ion-` que são utilizadas para o [Ionic Framework](http://ionicframework.com/). ### Restrict to Elements and Attributes +ou *Restringir para elementos e atributos* - - When creating a directive that makes sense as a standalone element, allow restrict `E` (custom element) and optionally restrict `A` (custom attribute). Generally, if it could be its own control, `E` is appropriate. General guideline is allow `EA` but lean towards implementing as an element when its standalone and as an attribute when it enhances its existing DOM element. + - Quando criar uma diretiva que faça sentido por si só como um elemento, utilize restrição `E` (elemento personalizado) e opcionalmente `A` (atributo personalizado). Geralmente, se ela pode ter o seu próprio controlador (controller), `E` é o apropriado. Em linhas gerais, `EA` é permitido, mas atente para a implementação como elemento quando faz sentido por si só e como atributo quando estende algo existente no DOM. - *Why?*: It makes sense. + **Por que?**: Faz sentido. - *Why?*: While we can allow the directive to be used as a class, if the directive is truly acting as an element it makes more sense as an element or at least as an attribute. + **Por que?**: Nós podemos utilizar uma diretiva como uma classe (class), mas se a diretiva está realmente agindo como um elemento, faz mais sentido utilizar como um elemento, ou pelo menos como um atributo. - Note: EA is the default for AngularJS 1.3 + + Nota: EA é o padrão para o AngularJS 1.3 + ```html - +
``` ```javascript - /* avoid */ + /* evite */ angular .module('app.widgets') .directive('myCalendarRange', myCalendarRange); @@ -1120,13 +1126,13 @@ ou *Retorne uma promessa de chamadas de dados* ``` ```html - +
``` ```javascript - /* recommended */ + /* recomendado */ angular .module('app.widgets') .directive('myCalendarRange', myCalendarRange); @@ -1146,12 +1152,13 @@ ou *Retorne uma promessa de chamadas de dados* ``` ### Directives and ControllerAs +ou *Diretivas e "ControladorComo"* - - Use `controller as` syntax with a directive to be consistent with using `controller as` with view and controller pairings. + - Utilize a sintaxe `controller as` com uma diretiva para consistência com o uso de `controller as` com os pares view e controlador (controller). - *Why?*: It makes sense and it's not difficult. + **Por que?**: Faz sentido e não é difícil. - Note: The directive below demonstrates some of the ways you can use scope inside of link and directive controllers, using controllerAs. I in-lined the template just to keep it all in one place. + Nota: A diretiva (directive) abaixo demonstra algumas maneiras que você pode utilizar escopos (scopes) dentro de link e controller de uma diretiva, utilizando controllerAs. Eu coloquei o template somente para manter tudo em um mesmo local. ```html
@@ -1177,7 +1184,7 @@ ou *Retorne uma promessa de chamadas de dados* ExampleController.$inject = ['$scope']; function ExampleController($scope) { - // Injecting $scope just for comparison + // Injetando $scope somente para comparação /* jshint validthis:true */ var vm = this; From d6ad8f5437d7f46751a5a596d11b0e9364c089fc Mon Sep 17 00:00:00 2001 From: Vinicius Sabadim Fernandes Date: Fri, 21 Nov 2014 10:43:16 -0200 Subject: [PATCH 028/567] Put my name as one of the collaborators --- i18n/PT-BR.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/i18n/PT-BR.md b/i18n/PT-BR.md index 5a029998..9d484535 100644 --- a/i18n/PT-BR.md +++ b/i18n/PT-BR.md @@ -2,7 +2,7 @@ *Guia de Estilo opinativo de AngularJS para times. Por [@john_papa](//twitter.com/john_papa)* -*Traduzido por [Eric Douglas](https://github.com/ericdouglas), [Ciro Nunes](https://github.com/cironunes) e [Jean Lucas de Carvalho](https://github.com/jlcarvalho)* +*Traduzido por [Eric Douglas](https://github.com/ericdouglas), [Ciro Nunes](https://github.com/cironunes), [Jean Lucas de Carvalho](https://github.com/jlcarvalho) e [Vinicius Sabadim Fernandes](https://github.com/vinicius-sabadim)* >The [original English version](http://jpapa.me/ngstyles) is the source of truth, as it is maintained and updated first. >A [versão original em inglês](http://jpapa.me/ngstyles) é a fonte da verdade, já que é corrigida e atualizada primeiro. From d6b460a75609863b716cc9a22c643ab3402f6349 Mon Sep 17 00:00:00 2001 From: Vinicius Sabadim Fernandes Date: Fri, 21 Nov 2014 11:34:08 -0200 Subject: [PATCH 029/567] Translate for the topic 'Resolving Promises for a Controller' (PT-BR) --- i18n/PT-BR.md | 31 +++++++++++++++++-------------- 1 file changed, 17 insertions(+), 14 deletions(-) diff --git a/i18n/PT-BR.md b/i18n/PT-BR.md index e664281c..134f7a13 100644 --- a/i18n/PT-BR.md +++ b/i18n/PT-BR.md @@ -1213,17 +1213,19 @@ ou *Diretivas e "ControladorComo"* **[⬆ De volta ao topo ⬆](#tabela-de-conte%C3%BAdo)** ## Resolving Promises for a Controller +ou *Resolvendo promessas para um controlador* ### Controller Activation Promises +ou *Ativação de promessas no controlador* - - Resolve start-up logic for a controller in an `activate` function. + - Resolva a lógica de inicialização no controlador (controller) em uma função `iniciar`. - *Why?*: Placing start-up logic in a consistent place in the controller makes it easier to locate, more consistent to test, and helps avoid spreading out the activation logic across the controller. + **Por que?**: Colocando a lógica de inicialização em um lugar consistente no controlador (controller), torna mais fácil de localizar, mais consistente para testar e ajuda a evitar o espalhamento da lógica de inicialização pelo controlador (controller). - Note: If you need to conditionally cancel the route before you start use the controller, use a route resolve instead. + Nota: Se vocẽ precisa cancelar a rota condicionalmente antes de utilizar o controlador (controller), utilize uma resolução de rota (route resolve). ```javascript - /* avoid */ + /* evite */ function Avengers(dataservice) { var vm = this; vm.avengers = []; @@ -1237,17 +1239,17 @@ ou *Diretivas e "ControladorComo"* ``` ```javascript - /* recommended */ + /* recomendado */ function Avengers(dataservice) { var vm = this; vm.avengers = []; vm.title = 'Avengers'; - activate(); + iniciar(); //////////// - function activate() { + function iniciar() { return dataservice.getAvengers().then(function(data) { vm.avengers = data; return vm.avengers; @@ -1257,22 +1259,23 @@ ou *Diretivas e "ControladorComo"* ``` ### Route Resolve Promises +ou *Resolução de promessas na rota* - - When a controller depends on a promise to be resolved, resolve those dependencies in the `$routeProvider` before the controller logic is executed. If you need to conditionally cancel a route before the controller is activated, use a route resolver. + - Quando o controlador (controller) depende de uma promessa ser resolvida, resolva as dependências no `$routeProvider` antes da lógica do controlador (controller) ser executada. Se vocẽ precisa cancelar a rota condicionalmente antes do controlador (controller) ser ativado, utilize uma resolução de rota (route resolve). - *Why?*: A controller may require data before it loads. That data may come from a promise via a custom factory or [$http](https://docs.angularjs.org/api/ng/service/$http). Using a [route resolve](https://docs.angularjs.org/api/ngRoute/provider/$routeProvider) allows the promise to resolve before the controller logic executes, so it might take action based on that data from the promise. + **Por que?**: Um controlador (controller) pode precisar de dados antes de ser carregado. Esses dados podem vir de uma promessa (promise) através de uma factory personalizada ou [$http](https://docs.angularjs.org/api/ng/service/$http). Utilizando [resolução de rota (route resolve)](https://docs.angularjs.org/api/ngRoute/provider/$routeProvider) permite as promessas (promises) serem resolvidas antes da lógica do controlador (controller) ser executada, então ele pode executar ações através dos dados dessa promessa (promise). ```javascript - /* avoid */ + /* evite */ angular .module('app') .controller('Avengers', Avengers); function Avengers(movieService) { var vm = this; - // unresolved + // não resolvida vm.movies; - // resolved asynchronously + // resolvida assíncrona movieService.getMovies().then(function(response) { vm.movies = response.movies; }); @@ -1280,7 +1283,7 @@ ou *Diretivas e "ControladorComo"* ``` ```javascript - /* better */ + /* melhor */ // route-config.js angular @@ -1314,7 +1317,7 @@ ou *Diretivas e "ControladorComo"* } ``` - Note: The code example's dependency on `movieService` is not minification safe on its own. For details on how to make this code minification safe, see the sections on [dependency injection](#manual-annotating-for-dependency-injection) and on [minification and annotation](#minification-and-annotation). + Nota: As dependências no código de exemplos do `movieService` não estão seguras da minificação. Para mais detalhes de como fazer o código minificado seguro, veja as seções [injeção de dependência (dependency injection)](#manual-annotating-for-dependency-injection) e [minificação e anotação (minification and annotation)](#minification-and-annotation). **[⬆ De volta ao topo ⬆](#tabela-de-conte%C3%BAdo)** From 13c69d09bfe06d61afc89ecd5c6e359e0f901099 Mon Sep 17 00:00:00 2001 From: Jean Lucas de Carvalho Date: Fri, 21 Nov 2014 14:59:43 -0200 Subject: [PATCH 030/567] Update PT-BR.md --- i18n/PT-BR.md | 1 + 1 file changed, 1 insertion(+) diff --git a/i18n/PT-BR.md b/i18n/PT-BR.md index 134f7a13..84431120 100644 --- a/i18n/PT-BR.md +++ b/i18n/PT-BR.md @@ -288,6 +288,7 @@ ou *Definindo* vs *Obtendo* **[⬆ De volta ao topo ⬆](#tabela-de-conte%C3%BAdo)** ## Controllers +ou *Controladores* ### controllerAs View Syntax From 23b60bfee8e01e01011c8100dff38c7989c41321 Mon Sep 17 00:00:00 2001 From: Jean Lucas de Carvalho Date: Fri, 21 Nov 2014 15:06:43 -0200 Subject: [PATCH 031/567] Update PT-BR.md --- i18n/PT-BR.md | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/i18n/PT-BR.md b/i18n/PT-BR.md index 134f7a13..2786b90f 100644 --- a/i18n/PT-BR.md +++ b/i18n/PT-BR.md @@ -179,9 +179,10 @@ ou *Responsabilidade Única* **[⬆ De volta ao topo ⬆](#tabela-de-conte%C3%BAdo)** ## Modules -ou Módulos +ou *Módulos* -### Evitando Colisão de Nomes +### Avoid Naming Collisions +ou *Evitando Colisão de Nomes* - Use uma única convenção de nomes com separadores para sub-módulos. @@ -251,7 +252,8 @@ ou *Definindo* vs *Obtendo* - Use `angular.module('app', []);` para definir (*set*) um módulo. - Use `angular.module('app');` para pegar (*get*) este módulo. -### Funções Nomeadas vs Funções Anônimas +### Named vs Anonymous Functions +ou *unções Nomeadas vs Funções Anônimas* - Use funções nomeadas ao invés de passar uma função anônima como um callback. @@ -644,6 +646,7 @@ ou *Definindo* vs *Obtendo* **[⬆ De volta ao topo ⬆](#tabela-de-conte%C3%BAdo)** ## Services +ou *Serviços* ### Singletons From fcdd0ce59250f626699e882724a4b04b34394904 Mon Sep 17 00:00:00 2001 From: ericdouglas Date: Sat, 22 Nov 2014 20:22:10 -0200 Subject: [PATCH 032/567] testing --- i18n/PT-BR.md | 2452 ------------------------------------------------- 1 file changed, 2452 deletions(-) diff --git a/i18n/PT-BR.md b/i18n/PT-BR.md index 64fda36c..e69de29b 100644 --- a/i18n/PT-BR.md +++ b/i18n/PT-BR.md @@ -1,2452 +0,0 @@ -# Guia de Estilo AngularJS - -*Guia de Estilo Opinativo para times sobre AngularJS por [@john_papa](//twitter.com/john_papa)* - -*Traduzido por [Eric Douglas](https://github.com/ericdouglas) e [Ciro Nunes](https://github.com/cironunes)* - ->A [versão original em inglês](http://jpapa.me/ngstyles) é a *fonte da verdade*, por ser mantida e atualizada primeiro. - -Se você procura por um guia de estilo opinativo para sintaxe, convenções e estruturação de aplicações AngularJS, então siga em frente! Estes estilos são baseados em minha experiência com desenvolvimento [AngularJS](//angularjs.org), apresentações, [cursos de treinamento na Plurasight](http://pluralsight.com/training/Authors/Details/john-papa) e trabalho em times. - -> Se você gostar deste estilo, olhe meu curso [AngularJS Patterns: Clean Code](http://jpapa.me/ngclean) na Plurasight. - -A proposta deste guia de estilo é fornecer uma direção na construção de aplicações AngularJS mostrando convenções que eu uso e, o mais importante, porque eu as escolhi. - -## Créditos e uma Grande Comunidade - -Nunca trabalhe no vazio. Acho que a comunidade AngularJS é um grupo incrível que é apaixonado em compartilhar experiências. Dessa forma, Todd Motto, um amigo e expert em AngularJS e eu temos colaborado com vários estilo e convenções. Nós concordamos na maioria, e discordamos em alguns. Eu encorajo você a conferir o [guia do Todd](https://github.com/toddmotto/angularjs-styleguide) para ter uma noção sobre sua abordagem e como ela se compara a esta. - -Vários de meus estilos vieram de várias sessões de programação em par que [Ward Bell](http://twitter.com/wardbell) e eu tivemos. Embora nem sempre concordamos, meu amigo Ward certamente me ajudou influenciando na última evolução deste guia. - -## Veja os estilos em um aplicativo de exemplo - -Embora este guia explique o **o quê**, **porque** e **como**, acho útil ver tudo isso em prática. Este guia é acompanhado de uma aplicação de amostra que segue estes estilos e padrões. Você pode encontrar a [aplicação de exemplo (chamada "modular") aqui](https://github.com/johnpapa/ng-demos) na pasta `modular`. Sinta-se livre para pegâ-la, cloná-la e *forká-la*. [Instruções de como rodar o aplicativo estão em seu README](https://github.com/johnpapa/ng-demos/tree/master/modular). - -> **Nota de tradução**: Os títulos originais de cada seção será mantido, pois caso você queira buscar mais sobre estes assuntos futuramente, fazendo tal busca em inglês será obtido um resultado **imensamente** melhor. -> -> Após o titúlo, estará a tradução auxiliar, quando necessária, visto que alguns termos são mais facilmente entendidos quando não traduzidos, por fazerem parte do núcleo do estudo em questão. -> -> Para eventuais erros de digitação e/ou tradução, favor enviar um pull-request! - -## Tabela de Conteúdo - - 1. [Single Responsibility](#single-responsibility) - 1. [IIFE](#iife) - 1. [Modules](#modules) - 1. [Controllers](#controllers) - 1. [Services](#services) - 1. [Factories](#factories) - 1. [Data Services](#data-services) - 1. [Directives](#directives) - 1. [Resolving Promises for a Controller](#resolving-promises-for-a-controller) - 1. [Manual Annotating for Dependency Injection](#manual-annotating-for-dependency-injection) - 1. [Minification and Annotation](#minification-and-annotation) - 1. [Exception Handling](#exception-handling) - 1. [Naming](#naming) - 1. [Application Structure LIFT Principle](#application-structure-lift-principle) - 1. [Application Structure](#application-structure) - 1. [Modularity](#modularity) - 1. [Angular $ Wrapper Services](#angular--wrapper-services) - 1. [Testing](#testing) - 1. [Animations](#animations) - 1. [Comments](#comments) - 1. [JSHint](#js-hint) - 1. [Constants](#constants) - 1. [File Templates and Snippets](#file-templates-and-snippets) - 1. [AngularJS Docs](#angularjs-docs) - 1. [Contributing](#contributing) - 1. [License](#license) - -## Single Responsibility -ou *Responsabilidade Única* - -### Regra nº 1 - - - Defina um componente por arquivo. - - O exemplo seguinte define um módulo `app` e suas dependências, define um controller e define um factory, todos no mesmo arquivo. - - ```javascript - /* evite */ - angular - .module('app', ['ngRoute']) - .controller('SomeController' , SomeController) - .factory('someFactory' , someFactory); - - function SomeController() { } - - function someFactory() { } - ``` - - Os mesmos componentes agora estão separados em seus próprios arquivos. - - ```javascript - /* recomendado */ - - // app.module.js - angular - .module('app', ['ngRoute']); - ``` - - ```javascript - /* recomendado */ - - // someController.js - angular - .module('app') - .controller('SomeController' , SomeController); - - function SomeController() { } - ``` - - ```javascript - /* recomendado */ - - // someFactory.js - angular - .module('app') - .factory('someFactory' , someFactory); - - function someFactory() { } - ``` - -**[⬆ De volta ao topo ⬆](#tabela-de-conte%C3%BAdo)** - -## IIFE -### JavaScript Closures - - - Envolva os componentes AngularJS em uma *Immediately Invoked Function Expression (IIFE - Expressão de função imediatamente invocada)*. - - **Por que?** Uma IIFE remove as variáveis do escopo global. Isso ajuda a prevenir declarações de variáveis e funções de viverem por mais tempo que o esperado no escopo global, que também auxilia evitar colisões de variáveis. - - **Por que?** Quando seu código é minificado e empacotado dentro de um único arquivo para *deployment* no servidor de produção, você pode ter conflitos de variáveis e muitas variáveis globais. Uma IIFE o protege em todos estes aspectos provendo escopo de variável para cada arquivo. - - ```javascript - /* evite */ - // logger.js - angular - .module('app') - .factory('logger', logger); - - // função logger é adicionada como uma variável global - function logger() { } - - // storage.js - angular - .module('app') - .factory('storage', storage); - - // função storage é adicionada como uma variável global - function storage() { } - ``` - - - ```javascript - /** - * recomendado - * - * nenhuma global é deixada para trás - */ - - // logger.js - (function() { - 'use strict'; - - angular - .module('app') - .factory('logger', logger); - - function logger() { } - })(); - - // storage.js - (function() { - 'use strict'; - - angular - .module('app') - .factory('storage', storage); - - function storage() { } - })(); - ``` - - - **Nota**: Apenas para agilizar, o resto dos exemplos neste guia omitirão a sintaxe IIFE. - - - **Nota**: IIFE impede que códigos de teste alcancem membros privados como expressões regulares ou funções auxiliares que são frequentemente boas para testes unitários. Entretanto você pode testá-las através de membros acessíveis ou expondo-os pelo próprio componente. Por exemplo, colocando funções auxiliares, expressões regulares ou constantes em sua própria *factory* ou constante. - -**[⬆ De volta ao topo ⬆](#tabela-de-conte%C3%BAdo)** - -## Modules -ou Módulos - -### Evitando Colisão de Nomes - - - Use uma única convenção de nomes com separadores para sub-módulos. - - **Por que?** Nomes únicos ajudam a evitar colisão de nomes no módulo. Separadores ajudam a definir a hierarquia de módulos e submódulos. Por exemplo, `app` pode ser seu módulo raiz, enquanto `app.dashboard` e `app.users` podem ser módulos que são usados como dependências de `app`. - -### Definições (*aka Setters*) - -> ps: **aka** é o acrônimo de **A**lso **Know** **A**s, de forma traduzida, **também conhecido como**. - - - Declare os módulos sem uma variável usando a sintaxe *setter*. - - **Por que?** Com 1 componente por arquivo, raramente será necessário criar uma variável para o módulo. - - ```javascript - /* evite */ - var app = angular.module('app', [ - 'ngAnimate', - 'ngRoute', - 'app.shared', - 'app.dashboard' - ]); - ``` - - Ao invés, use a simples sintaxe *setter*. - - ```javascript - /* recomendado */ - angular - .module('app', [ - 'ngAnimate', - 'ngRoute', - 'app.shared', - 'app.dashboard' - ]); - ``` - -### *Getters* - - - Quando usando um módulo, evite usar as variáveis e então use o encadeamento com a sintaxe *getter*. - - **Por que?** Isso produz um código mais legível e evite colisão de variáveis ou vazamentos. - - ```javascript - /* evite */ - var app = angular.module('app'); - app.controller('SomeController' , SomeController); - - function SomeController() { } - ``` - - ```javascript - /* recomendado */ - angular - .module('app') - .controller('SomeController' , SomeController); - - function SomeController() { } - ``` - -### *Setting* vs *Getting* -ou *Definindo* vs *Obtendo* - - - Apenas *set* (configure) uma vez e *get* (receba) em todas as outras instâncias. - - **Por que?** Um módulo deve ser criado somente uma vez, então recupere-o deste ponto em diante. - - - Use `angular.module('app', []);` para definir (*set*) um módulo. - - Use `angular.module('app');` para pegar (*get*) este módulo. - -### Funções Nomeadas vs Funções Anônimas - - - Use funções nomeadas ao invés de passar uma função anônima como um callback. - - *Why?*: This produces more readable code, is much easier to debug, and reduces the amount of nested callback code. - **Por que?** Isso produz um código mais legível, é muito fácil de *debugar*, e reduz a quantidade de callbacks aninhados no código. - - ```javascript - /* evite */ - angular - .module('app') - .controller('Dashboard', function() { }); - .factory('logger', function() { }); - ``` - - ```javascript - /* recomendado */ - - // dashboard.js - angular - .module('app') - .controller('Dashboard', Dashboard); - - function Dashboard() { } - ``` - - ```javascript - // logger.js - angular - .module('app') - .factory('logger', logger); - - function logger() { } - ``` - -**[⬆ De volta ao topo ⬆](#tabela-de-conte%C3%BAdo)** - -## Controllers - -### controllerAs View Syntax - - - Use the [`controllerAs`](http://www.johnpapa.net/do-you-like-your-angular-controllers-with-or-without-sugar/) syntax over the `classic controller with $scope` syntax. - - *Why?*: Controllers are constructed, "newed" up, and provide a single new instance, and the `controllerAs` syntax is closer to that of a JavaScript constructor than the `classic $scope syntax`. - - *Why?*: It promotes the use of binding to a "dotted" object in the View (e.g. `customer.name` instead of `name`), which is more contextual, easier to read, and avoids any reference issues that may occur without "dotting". - - *Why?*: Helps avoid using `$parent` calls in Views with nested controllers. - - ```html - -
- {{ name }} -
- ``` - - ```html - -
- {{ customer.name }} -
- ``` - -### controllerAs Controller Syntax - - - Use the `controllerAs` syntax over the `classic controller with $scope` syntax. - - - The `controllerAs` syntax uses `this` inside controllers which gets bound to `$scope` - - *Why?*: `controllerAs` is syntactic sugar over `$scope`. You can still bind to the View and still access `$scope` methods. - - *Why?*: Helps avoid the temptation of using `$scope` methods inside a controller when it may otherwise be better to avoid them or move them to a factory. Consider using `$scope` in a factory, or if in a controller just when needed. For example when publishing and subscribing events using [`$emit`](https://docs.angularjs.org/api/ng/type/$rootScope.Scope#$emit), [`$broadcast`](https://docs.angularjs.org/api/ng/type/$rootScope.Scope#$broadcast), or [`$on`](https://docs.angularjs.org/api/ng/type/$rootScope.Scope#$on) consider moving these uses to a factory and invoke from the controller. - - ```javascript - /* avoid */ - function Customer($scope) { - $scope.name = {}; - $scope.sendMessage = function() { }; - } - ``` - - ```javascript - /* recommended - but see next section */ - function Customer() { - this.name = {}; - this.sendMessage = function() { }; - } - ``` - -### controllerAs with vm - - - Use a capture variable for `this` when using the `controllerAs` syntax. Choose a consistent variable name such as `vm`, which stands for ViewModel. - - *Why?*: The `this` keyword is contextual and when used within a function inside a controller may change its context. Capturing the context of `this` avoids encountering this problem. - - ```javascript - /* avoid */ - function Customer() { - this.name = {}; - this.sendMessage = function() { }; - } - ``` - - ```javascript - /* recommended */ - function Customer() { - var vm = this; - vm.name = {}; - vm.sendMessage = function() { }; - } - ``` - - Note: You can avoid any [jshint](http://www.jshint.com/) warnings by placing the comment below above the line of code. - - ```javascript - /* jshint validthis: true */ - var vm = this; - ``` - - Note: When creating watches in a controller using `controller as`, you can watch the `vm.*` member using the following syntax. (Create watches with caution as they add more load to the digest cycle.) - - ```javascript - $scope.$watch('vm.title', function(current, original) { - $log.info('vm.title was %s', original); - $log.info('vm.title is now %s', current); - }); - ``` - -### Bindable Members Up Top - - - Place bindable members at the top of the controller, alphabetized, and not spread through the controller code. - - *Why?*: Placing bindable members at the top makes it easy to read and helps you instantly identify which members of the controller can be bound and used in the View. - - *Why?*: Setting anonymous functions in-line can be easy, but when those functions are more than 1 line of code they can reduce the readability. Defining the functions below the bindable members (the functions will be hoisted) moves the implementation details down, keeps the bindable members up top, and makes it easier to read. - - ```javascript - /* avoid */ - function Sessions() { - var vm = this; - - vm.gotoSession = function() { - /* ... */ - }; - vm.refresh = function() { - /* ... */ - }; - vm.search = function() { - /* ... */ - }; - vm.sessions = []; - vm.title = 'Sessions'; - ``` - - ```javascript - /* recommended */ - function Sessions() { - var vm = this; - - vm.gotoSession = gotoSession; - vm.refresh = refresh; - vm.search = search; - vm.sessions = []; - vm.title = 'Sessions'; - - //////////// - - function gotoSession() { - /* */ - } - - function refresh() { - /* */ - } - - function search() { - /* */ - } - ``` - - ![Controller Using "Above the Fold"](https://raw.githubusercontent.com/johnpapa/angularjs-styleguide/master/assets/above-the-fold-1.png) - - Note: If the function is a 1 liner consider keeping it right up top, as long as readability is not affected. - - ```javascript - /* avoid */ - function Sessions(data) { - var vm = this; - - vm.gotoSession = gotoSession; - vm.refresh = function() { - /** - * lines - * of - * code - * affects - * readability - */ - }; - vm.search = search; - vm.sessions = []; - vm.title = 'Sessions'; - ``` - - ```javascript - /* recommended */ - function Sessions(dataservice) { - var vm = this; - - vm.gotoSession = gotoSession; - vm.refresh = dataservice.refresh; // 1 liner is OK - vm.search = search; - vm.sessions = []; - vm.title = 'Sessions'; - ``` - -### Function Declarations to Hide Implementation Details - - - Use function declarations to hide implementation details. Keep your bindable members up top. When you need to bind a function in a controller, point it to a function declaration that appears later in the file. This is tied directly to the section Bindable Members Up Top. For more details see [this post](http://www.johnpapa.net/angular-function-declarations-function-expressions-and-readable-code). - - *Why?*: Placing bindable members at the top makes it easy to read and helps you instantly identify which members of the controller can be bound and used in the View. (Same as above.) - - *Why?*: Placing the implementation details of a function later in the file moves that complexity out of view so you can see the important stuff up top. - - *Why?*: Function declaration are hoisted so there are no concerns over using a function before it is defined (as there would be with function expressions). - - *Why?*: You never have to worry with function declarations that moving `var a` before `var b` will break your code because `a` depends on `b`. - - *Why?*: Order is critical with function expressions - - ```javascript - /** - * avoid - * Using function expressions. - */ - function Avengers(dataservice, logger) { - var vm = this; - vm.avengers = []; - vm.title = 'Avengers'; - - var activate = function() { - return getAvengers().then(function() { - logger.info('Activated Avengers View'); - }); - } - - var getAvengers = function() { - return dataservice.getAvengers().then(function(data) { - vm.avengers = data; - return vm.avengers; - }); - } - - vm.getAvengers = getAvengers; - - activate(); - } - ``` - - Notice that the important stuff is scattered in the preceding example. In the example below, notice that the important stuff is up top. For example, the members bound to the controller such as `vm.avengers` and `vm.title`. The implementation details are down below. This is just easier to read. - - ```javascript - /* - * recommend - * Using function declarations - * and bindable members up top. - */ - function Avengers(dataservice, logger) { - var vm = this; - vm.avengers = []; - vm.getAvengers = getAvengers; - vm.title = 'Avengers'; - - activate(); - - function activate() { - return getAvengers().then(function() { - logger.info('Activated Avengers View'); - }); - } - - function getAvengers() { - return dataservice.getAvengers().then(function(data) { - vm.avengers = data; - return vm.avengers; - }); - } - } - ``` - -### Defer Controller Logic - - - Defer logic in a controller by delegating to services and factories. - - *Why?*: Logic may be reused by multiple controllers when placed within a service and exposed via a function. - - *Why?*: Logic in a service can more easily be isolated in a unit test, while the calling logic in the controller can be easily mocked. - - *Why?*: Removes dependencies and hides implementation details from the controller. - - ```javascript - /* avoid */ - function Order($http, $q) { - var vm = this; - vm.checkCredit = checkCredit; - vm.total = 0; - - function checkCredit() { - var orderTotal = vm.total; - return $http.get('api/creditcheck').then(function(data) { - var remaining = data.remaining; - return $q.when(!!(remaining > orderTotal)); - }); - }; - } - ``` - - ```javascript - /* recommended */ - function Order(creditService) { - var vm = this; - vm.checkCredit = checkCredit; - vm.total = 0; - - function checkCredit() { - return creditService.check(); - }; - } - ``` - -### Keep Controllers Focused - - - Define a controller for a view, and try not to reuse the controller for other views. Instead, move reusable logic to factories and keep the controller simple and focused on its view. - - *Why?*: Reusing controllers with several views is brittle and good end to end (e2e) test coverage is required to ensure stability across large applications. - -### Assigning Controllers - - - When a controller must be paired with a view and either component may be re-used by other controllers or views, define controllers along with their routes. - - Note: If a View is loaded via another means besides a route, then use the `ng-controller="Avengers as vm"` syntax. - - *Why?*: Pairing the controller in the route allows different routes to invoke different pairs of controllers and views. When controllers are assigned in the view using [`ng-controller`](https://docs.angularjs.org/api/ng/directive/ngController), that view is always associated with the same controller. - - ```javascript - /* avoid - when using with a route and dynamic pairing is desired */ - - // route-config.js - angular - .module('app') - .config(config); - - function config($routeProvider) { - $routeProvider - .when('/avengers', { - templateUrl: 'avengers.html' - }); - } - ``` - - ```html - -
-
- ``` - - ```javascript - /* recommended */ - - // route-config.js - angular - .module('app') - .config(config); - - function config($routeProvider) { - $routeProvider - .when('/avengers', { - templateUrl: 'avengers.html', - controller: 'Avengers', - controllerAs: 'vm' - }); - } - ``` - - ```html - -
-
- ``` - -**[⬆ De volta ao topo ⬆](#tabela-de-conte%C3%BAdo)** - -## Services - -### Singletons - - - Services are instantiated with the `new` keyword, use `this` for public methods and variables. Since these are so similar to factories, use a factory instead for consistency. - - Note: [All AngularJS services are singletons](https://docs.angularjs.org/guide/services). This means that there is only one instance of a given service per injector. - - ```javascript - // service - angular - .module('app') - .service('logger', logger); - - function logger() { - this.logError = function(msg) { - /* */ - }; - } - ``` - - ```javascript - // factory - angular - .module('app') - .factory('logger', logger); - - function logger() { - return { - logError: function(msg) { - /* */ - } - }; - } - ``` - -**[⬆ De volta ao topo ⬆](#tabela-de-conte%C3%BAdo)** - -## Factories - -### Single Responsibility - - - Factories should have a [single responsibility](http://en.wikipedia.org/wiki/Single_responsibility_principle), that is encapsulated by its context. Once a factory begins to exceed that singular purpose, a new factory should be created. - -### Singletons - - - Factories are singletons and return an object that contains the members of the service. - - Note: [All AngularJS services are singletons](https://docs.angularjs.org/guide/services). - -### Accessible Members Up Top - - - Expose the callable members of the service (it's interface) at the top, using a technique derived from the [Revealing Module Pattern](http://addyosmani.com/resources/essentialjsdesignpatterns/book/#revealingmodulepatternjavascript). - - *Why?*: Placing the callable members at the top makes it easy to read and helps you instantly identify which members of the service can be called and must be unit tested (and/or mocked). - - *Why?*: This is especially helpful when the file gets longer as it helps avoid the need to scroll to see what is exposed. - - *Why?*: Setting functions as you go can be easy, but when those functions are more than 1 line of code they can reduce the readability and cause more scrolling. Defining the callable interface via the returned service moves the implementation details down, keeps the callable interface up top, and makes it easier to read. - - ```javascript - /* avoid */ - function dataService() { - var someValue = ''; - function save() { - /* */ - }; - function validate() { - /* */ - }; - - return { - save: save, - someValue: someValue, - validate: validate - }; - } - ``` - - ```javascript - /* recommended */ - function dataService() { - var someValue = ''; - var service = { - save: save, - someValue: someValue, - validate: validate - }; - return service; - - //////////// - - function save() { - /* */ - }; - - function validate() { - /* */ - }; - } - ``` - - This way bindings are mirrored across the host object, primitive values cannot update alone using the revealing module pattern - - ![Factories Using "Above the Fold"](https://raw.githubusercontent.com/johnpapa/angularjs-styleguide/master/assets/above-the-fold-2.png) - -### Function Declarations to Hide Implementation Details - - - Use function declarations to hide implementation details. Keep your acessible members of the factory up top. Point those to function declarations that appears later in the file. For more details see [this post](http://www.johnpapa.net/angular-function-declarations-function-expressions-and-readable-code). - - *Why?*: Placing accessible members at the top makes it easy to read and helps you instantly identify which functions of the factory you can access externally. - - *Why?*: Placing the implementation details of a function later in the file moves that complexity out of view so you can see the important stuff up top. - - *Why?*: Function declaration are hoisted so there are no concerns over using a function before it is defined (as there would be with function expressions). - - *Why?*: You never have to worry with function declarations that moving `var a` before `var b` will break your code because `a` depends on `b`. - - *Why?*: Order is critical with function expressions - - ```javascript - /** - * avoid - * Using function expressions - */ - function dataservice($http, $location, $q, exception, logger) { - var isPrimed = false; - var primePromise; - - var getAvengers = function() { - // implementation details go here - }; - - var getAvengerCount = function() { - // implementation details go here - }; - - var getAvengersCast = function() { - // implementation details go here - }; - - var prime = function() { - // implementation details go here - }; - - var ready = function(nextPromises) { - // implementation details go here - }; - - var service = { - getAvengersCast: getAvengersCast, - getAvengerCount: getAvengerCount, - getAvengers: getAvengers, - ready: ready - }; - - return service; - } - ``` - - ```javascript - /** - * recommended - * Using function declarations - * and accessible members up top. - */ - function dataservice($http, $location, $q, exception, logger) { - var isPrimed = false; - var primePromise; - - var service = { - getAvengersCast: getAvengersCast, - getAvengerCount: getAvengerCount, - getAvengers: getAvengers, - ready: ready - }; - - return service; - - //////////// - - function getAvengers() { - // implementation details go here - } - - function getAvengerCount() { - // implementation details go here - } - - function getAvengersCast() { - // implementation details go here - } - - function prime() { - // implementation details go here - } - - function ready(nextPromises) { - // implementation details go here - } - } - ``` - -**[⬆ De volta ao topo ⬆](#tabela-de-conte%C3%BAdo)** - -## Data Services - -### Separate Data Calls - - - Refactor logic for making data operations and interacting with data to a factory. Make data services responsible for XHR calls, local storage, stashing in memory, or any other data operations. - - *Why?*: The controller's responsibility is for the presentation and gathering of information for the view. It should not care how it gets the data, just that it knows who to ask for it. Separating the data services moves the logic on how to get it to the data service, and lets the controller be simpler and more focused on the view. - - *Why?*: This makes it easier to test (mock or real) the data calls when testing a controller that uses a data service. - - *Why?*: Data service implementation may have very specific code to handle the data repository. This may include headers, how to talk to the data, or other services such as $http. Separating the logic into a data service encapsulates this logic in a single place hiding the implementation from the outside consumers (perhaps a controller), also making it easier to change the implementation. - - ```javascript - /* recommended */ - - // dataservice factory - angular - .module('app.core') - .factory('dataservice', dataservice); - - dataservice.$inject = ['$http', 'logger']; - - function dataservice($http, logger) { - return { - getAvengers: getAvengers - }; - - function getAvengers() { - return $http.get('/api/maa') - .then(getAvengersComplete) - .catch(getAvengersFailed); - - function getAvengersComplete(response) { - return response.data.results; - } - - function getAvengersFailed(error) { - logger.error('XHR Failed for getAvengers.' + error.data); - } - } - } - ``` - - Note: The data service is called from consumers, such as a controller, hiding the implementation from the consumers, as shown below. - - ```javascript - /* recommended */ - - // controller calling the dataservice factory - angular - .module('app.avengers') - .controller('Avengers', Avengers); - - Avengers.$inject = ['dataservice', 'logger']; - - function Avengers(dataservice, logger) { - var vm = this; - vm.avengers = []; - - activate(); - - function activate() { - return getAvengers().then(function() { - logger.info('Activated Avengers View'); - }); - } - - function getAvengers() { - return dataservice.getAvengers() - .then(function(data) { - vm.avengers = data; - return vm.avengers; - }); - } - } - ``` - -### Return a Promise from Data Calls - - - When calling a data service that returns a promise such as $http, return a promise in your calling function too. - - *Why?*: You can chain the promises together and take further action after the data call completes and resolves or rejects the promise. - - ```javascript - /* recommended */ - - activate(); - - function activate() { - /** - * Step 1 - * Ask the getAvengers function for the - * avenger data and wait for the promise - */ - return getAvengers().then(function() { - /** - * Step 4 - * Perform an action on resolve of final promise - */ - logger.info('Activated Avengers View'); - }); - } - - function getAvengers() { - /** - * Step 2 - * Ask the data service for the data and wait - * for the promise - */ - return dataservice.getAvengers() - .then(function(data) { - /** - * Step 3 - * set the data and resolve the promise - */ - vm.avengers = data; - return vm.avengers; - }); - } - ``` - - **[⬆ De volta ao topo ⬆](#tabela-de-conte%C3%BAdo)** - -## Directives -### Limit 1 Per File - - - Create one directive per file. Name the file for the directive. - - *Why?*: It is easy to mash all the directives in one file, but difficult to then break those out so some are shared across apps, some across modules, some just for one module. - - *Why?*: One directive per file is easy to maintain. - - ```javascript - /* avoid */ - /* directives.js */ - - angular - .module('app.widgets') - - /* order directive that is specific to the order module */ - .directive('orderCalendarRange', orderCalendarRange) - - /* sales directive that can be used anywhere across the sales app */ - .directive('salesCustomerInfo', salesCustomerInfo) - - /* spinner directive that can be used anywhere across apps */ - .directive('sharedSpinner', sharedSpinner); - - - function orderCalendarRange() { - /* implementation details */ - } - - function salesCustomerInfo() { - /* implementation details */ - } - - function sharedSpinner() { - /* implementation details */ - } - ``` - - ```javascript - /* recommended */ - /* calendarRange.directive.js */ - - /** - * @desc order directive that is specific to the order module at a company named Acme - * @example
- */ - angular - .module('sales.order') - .directive('acmeOrderCalendarRange', orderCalendarRange); - - function orderCalendarRange() { - /* implementation details */ - } - ``` - - ```javascript - /* recommended */ - /* customerInfo.directive.js */ - - /** - * @desc spinner directive that can be used anywhere across the sales app at a company named Acme - * @example
- */ - angular - .module('sales.widgets') - .directive('acmeSalesCustomerInfo', salesCustomerInfo); - - function salesCustomerInfo() { - /* implementation details */ - } - ``` - - ```javascript - /* recommended */ - /* spinner.directive.js */ - - /** - * @desc spinner directive that can be used anywhere across apps at a company named Acme - * @example
- */ - angular - .module('shared.widgets') - .directive('acmeSharedSpinner', sharedSpinner); - - function sharedSpinner() { - /* implementation details */ - } - ``` - - Note: There are many naming options for directives, especially since they can be used in narrow or wide scopes. Choose one that makes the directive and it's file name distinct and clear. Some examples are below, but see the naming section for more recommendations. - -### Limit DOM Manipulation - - - When manipulating the DOM directly, use a directive. If alternative ways can be used such as using CSS to set styles or the [animation services](https://docs.angularjs.org/api/ngAnimate), Angular templating, [`ngShow`](https://docs.angularjs.org/api/ng/directive/ngShow) or [`ngHide`](https://docs.angularjs.org/api/ng/directive/ngHide), then use those instead. For example, if the directive simply hides and shows, use ngHide/ngShow. - - *Why?*: DOM manipulation can be difficult to test, debug, and there are often better ways (e.g. CSS, animations, templates) - -### Provide a Unique Directive Prefix - - - Provide a short, unique and descriptive directive prefix such as `acmeSalesCustomerInfo` which is declared in HTML as `acme-sales-customer-info`. - - *Why?*: The unique short prefix identifies the directive's context and origin. For example a prefix of `cc-` may indicate that the directive is part of a CodeCamper app while `acme-` may indicate a directive for the Acme company. - - Note: Avoid `ng-` as these are reserved for AngularJS directives.Research widely used directives to avoid naming conflicts, such as `ion-` for the [Ionic Framework](http://ionicframework.com/). - -### Restrict to Elements and Attributes - - - When creating a directive that makes sense as a standalone element, allow restrict `E` (custom element) and optionally restrict `A` (custom attribute). Generally, if it could be its own control, `E` is appropriate. General guideline is allow `EA` but lean towards implementing as an element when its standalone and as an attribute when it enhances its existing DOM element. - - *Why?*: It makes sense. - - *Why?*: While we can allow the directive to be used as a class, if the directive is truly acting as an element it makes more sense as an element or at least as an attribute. - - Note: EA is the default for AngularJS 1.3 + - - ```html - -
- ``` - - ```javascript - /* avoid */ - angular - .module('app.widgets') - .directive('myCalendarRange', myCalendarRange); - - function myCalendarRange() { - var directive = { - link: link, - templateUrl: '/template/is/located/here.html', - restrict: 'C' - }; - return directive; - - function link(scope, element, attrs) { - /* */ - } - } - ``` - - ```html - - -
- ``` - - ```javascript - /* recommended */ - angular - .module('app.widgets') - .directive('myCalendarRange', myCalendarRange); - - function myCalendarRange() { - var directive = { - link: link, - templateUrl: '/template/is/located/here.html', - restrict: 'EA' - }; - return directive; - - function link(scope, element, attrs) { - /* */ - } - } - ``` - -### Directives and ControllerAs - - - Use `controller as` syntax with a directive to be consistent with using `controller as` with view and controller pairings. - - *Why?*: It makes sense and it's not difficult. - - Note: The directive below demonstrates some of the ways you can use scope inside of link and directive controllers, using controllerAs. I in-lined the template just to keep it all in one place. - - ```html -
- ``` - - ```javascript - angular - .module('app') - .directive('myExample', myExample); - - function myExample() { - var directive = { - restrict: 'EA', - templateUrl: 'app/feature/example.directive.html', - scope: { - max: '=' - }, - link: linkFunc, - controller : ExampleController, - controllerAs: 'vm' - }; - return directive; - - ExampleController.$inject = ['$scope']; - function ExampleController($scope) { - // Injecting $scope just for comparison - /* jshint validthis:true */ - var vm = this; - - vm.min = 3; - vm.max = $scope.max; - console.log('CTRL: $scope.max = %i', $scope.max); - console.log('CTRL: vm.min = %i', vm.min); - console.log('CTRL: vm.max = %i', vm.max); - } - - function linkFunc(scope, el, attr, ctrl) { - console.log('LINK: scope.max = %i', scope.max); - console.log('LINK: scope.vm.min = %i', scope.vm.min); - console.log('LINK: scope.vm.max = %i', scope.vm.max); - } - } - ``` - - ```html - /* example.directive.html */ -
hello world
-
max={{vm.max}}
-
min={{vm.min}}
- ``` - -**[⬆ De volta ao topo ⬆](#tabela-de-conte%C3%BAdo)** - -## Resolving Promises for a Controller - -### Controller Activation Promises - - - Resolve start-up logic for a controller in an `activate` function. - - *Why?*: Placing start-up logic in a consistent place in the controller makes it easier to locate, more consistent to test, and helps avoid spreading out the activation logic across the controller. - - Note: If you need to conditionally cancel the route before you start use the controller, use a route resolve instead. - - ```javascript - /* avoid */ - function Avengers(dataservice) { - var vm = this; - vm.avengers = []; - vm.title = 'Avengers'; - - dataservice.getAvengers().then(function(data) { - vm.avengers = data; - return vm.avengers; - }); - } - ``` - - ```javascript - /* recommended */ - function Avengers(dataservice) { - var vm = this; - vm.avengers = []; - vm.title = 'Avengers'; - - activate(); - - //////////// - - function activate() { - return dataservice.getAvengers().then(function(data) { - vm.avengers = data; - return vm.avengers; - }); - } - } - ``` - -### Route Resolve Promises - - - When a controller depends on a promise to be resolved, resolve those dependencies in the `$routeProvider` before the controller logic is executed. If you need to conditionally cancel a route before the controller is activated, use a route resolver. - - *Why?*: A controller may require data before it loads. That data may come from a promise via a custom factory or [$http](https://docs.angularjs.org/api/ng/service/$http). Using a [route resolve](https://docs.angularjs.org/api/ngRoute/provider/$routeProvider) allows the promise to resolve before the controller logic executes, so it might take action based on that data from the promise. - - ```javascript - /* avoid */ - angular - .module('app') - .controller('Avengers', Avengers); - - function Avengers(movieService) { - var vm = this; - // unresolved - vm.movies; - // resolved asynchronously - movieService.getMovies().then(function(response) { - vm.movies = response.movies; - }); - } - ``` - - ```javascript - /* better */ - - // route-config.js - angular - .module('app') - .config(config); - - function config($routeProvider) { - $routeProvider - .when('/avengers', { - templateUrl: 'avengers.html', - controller: 'Avengers', - controllerAs: 'vm', - resolve: { - moviesPrepService: function(movieService) { - return movieService.getMovies(); - } - } - }); - } - - // avengers.js - angular - .module('app') - .controller('Avengers', Avengers); - - Avengers.$inject = ['moviesPrepService']; - function Avengers(moviesPrepService) { - /* jshint validthis:true */ - var vm = this; - vm.movies = moviesPrepService.movies; - } - ``` - - Note: The code example's dependency on `movieService` is not minification safe on its own. For details on how to make this code minification safe, see the sections on [dependency injection](#manual-annotating-for-dependency-injection) and on [minification and annotation](#minification-and-annotation). - -**[⬆ De volta ao topo ⬆](#tabela-de-conte%C3%BAdo)** - -## Manual Annotating for Dependency Injection - -### UnSafe from Minification - - - Avoid using the shortcut syntax of declaring dependencies without using a minification-safe approach. - - *Why?*: The parameters to the component (e.g. controller, factory, etc) will be converted to mangled variables. For example, `common` and `dataservice` may become `a` or `b` and not be found by AngularJS. - - ```javascript - /* avoid - not minification-safe*/ - angular - .module('app') - .controller('Dashboard', Dashboard); - - function Dashboard(common, dataservice) { - } - ``` - - This code may produce mangled variables when minified and thus cause runtime errors. - - ```javascript - /* avoid - not minification-safe*/ - angular.module('app').controller('Dashboard', d);function d(a, b) { } - ``` - -### Manually Identify Dependencies - - - Use `$inject` to manually identify your dependencies for AngularJS components. - - *Why?*: This technique mirrors the technique used by [`ng-annotate`](https://github.com/olov/ng-annotate), which I recommend for automating the creation of minification safe dependencies. If `ng-annotate` detects injection has already been made, it will not duplicate it. - - *Why?*: This safeguards your dependencies from being vulnerable to minification issues when parameters may be mangled. For example, `common` and `dataservice` may become `a` or `b` and not be found by AngularJS. - - *Why?*: Avoid creating in-line dependencies as long lists can be difficult to read in the array. Also it can be confusing that the array is a series of strings while the last item is the component's function. - - ```javascript - /* avoid */ - angular - .module('app') - .controller('Dashboard', - ['$location', '$routeParams', 'common', 'dataservice', - function Dashboard($location, $routeParams, common, dataservice) {} - ]); - ``` - - ```javascript - /* avoid */ - angular - .module('app') - .controller('Dashboard', - ['$location', '$routeParams', 'common', 'dataservice', Dashboard]); - - function Dashboard($location, $routeParams, common, dataservice) { - } - ``` - - ```javascript - /* recommended */ - angular - .module('app') - .controller('Dashboard', Dashboard); - - Dashboard.$inject = ['$location', '$routeParams', 'common', 'dataservice']; - - function Dashboard($location, $routeParams, common, dataservice) { - } - ``` - - Note: When your function is below a return statement the $inject may be unreachable (this may happen in a directive). You can solve this by either moving the $inject above the return statement or by using the alternate array injection syntax. - - Note: [`ng-annotate 0.10.0`](https://github.com/olov/ng-annotate) introduced a feature where it moves the `$inject` to where it is reachable. - - ```javascript - // inside a directive definition - function outer() { - return { - controller: DashboardPanel, - }; - - DashboardPanel.$inject = ['logger']; // Unreachable - function DashboardPanel(logger) { - } - } - ``` - - ```javascript - // inside a directive definition - function outer() { - DashboardPanel.$inject = ['logger']; // reachable - return { - controller: DashboardPanel, - }; - - function DashboardPanel(logger) { - } - } - ``` - -### Manually Identify Route Resolver Dependencies - - - Use $inject to manually identify your route resolver dependencies for AngularJS components. - - *Why?*: This technique breaks out the anonymous function for the route resolver, making it easier to read. - - *Why?*: An `$inject` statement can easily precede the resolver to handle making any dependencies minification safe. - - ```javascript - /* recommended */ - function config($routeProvider) { - $routeProvider - .when('/avengers', { - templateUrl: 'avengers.html', - controller: 'Avengers', - controllerAs: 'vm', - resolve: { - moviesPrepService: moviePrepService - } - }); - } - - moviePrepService.$inject = ['movieService']; - function moviePrepService(movieService) { - return movieService.getMovies(); - } - ``` - -**[⬆ De volta ao topo ⬆](#tabela-de-conte%C3%BAdo)** - -## Minification and Annotation - -### ng-annotate - - - Use [ng-annotate](//github.com/olov/ng-annotate) for [Gulp](http://gulpjs.com) or [Grunt](http://gruntjs.com) and comment functions that need automated dependency injection using `/** @ngInject */` - - *Why?*: This safeguards your code from any dependencies that may not be using minification-safe practices. - - *Why?*: [`ng-min`](https://github.com/btford/ngmin) is deprecated - - >I prefer Gulp as I feel it is easier to write, to read, and to debug. - - The following code is not using minification safe dependencies. - - ```javascript - angular - .module('app') - .controller('Avengers', Avengers); - - /* @ngInject */ - function Avengers(storageService, avengerService) { - var vm = this; - vm.heroSearch = ''; - vm.storeHero = storeHero; - - function storeHero(){ - var hero = avengerService.find(vm.heroSearch); - storageService.save(hero.name, hero); - } - } - ``` - - When the above code is run through ng-annotate it will produce the following output with the `$inject` annotation and become minification-safe. - - ```javascript - angular - .module('app') - .controller('Avengers', Avengers); - - /* @ngInject */ - function Avengers(storageService, avengerService) { - var vm = this; - vm.heroSearch = ''; - vm.storeHero = storeHero; - - function storeHero(){ - var hero = avengerService.find(vm.heroSearch); - storageService.save(hero.name, hero); - } - } - - Avengers.$inject = ['storageService', 'avengerService']; - ``` - - Note: If `ng-annotate` detects injection has already been made (e.g. `@ngInject` was detected), it will not duplicate the `$inject` code. - - Note: When using a route resolver you can prefix the resolver's function with `/* @ngInject */` and it will produce properly annotated code, keeping any injected dependencies minification safe. - - ```javascript - // Using @ngInject annotations - function config($routeProvider) { - $routeProvider - .when('/avengers', { - templateUrl: 'avengers.html', - controller: 'Avengers', - controllerAs: 'vm', - resolve: { /* @ngInject */ - moviesPrepService: function(movieService) { - return movieService.getMovies(); - } - } - }); - } - ``` - - > Note: Starting from AngularJS 1.3 use the [`ngApp`](https://docs.angularjs.org/api/ng/directive/ngApp) directive's `ngStrictDi` parameter. When present the injector will be created in "strict-di" mode causing the application to fail to invoke functions which do not use explicit function annotation (these may not be minification safe). Debugging info will be logged to the console to help track down the offending code. - `` - -### Use Gulp or Grunt for ng-annotate - - - Use [gulp-ng-annotate](https://www.npmjs.org/package/gulp-ng-annotate) or [grunt-ng-annotate](https://www.npmjs.org/package/grunt-ng-annotate) in an automated build task. Inject `/* @ngInject */` prior to any function that has dependencies. - - *Why?*: ng-annotate will catch most dependencies, but it sometimes requires hints using the `/* @ngInject */` syntax. - - The following code is an example of a gulp task using ngAnnotate - - ```javascript - gulp.task('js', ['jshint'], function() { - var source = pkg.paths.js; - return gulp.src(source) - .pipe(sourcemaps.init()) - .pipe(concat('all.min.js', {newLine: ';'})) - // Annotate before uglify so the code get's min'd properly. - .pipe(ngAnnotate({ - // true helps add where @ngInject is not used. It infers. - // Doesn't work with resolve, so we must be explicit there - add: true - })) - .pipe(bytediff.start()) - .pipe(uglify({mangle: true})) - .pipe(bytediff.stop()) - .pipe(sourcemaps.write('./')) - .pipe(gulp.dest(pkg.paths.dev)); - }); - - ``` - -**[⬆ De volta ao topo ⬆](#tabela-de-conte%C3%BAdo)** - -## Exception Handling - -### decorators - - - Use a [decorator](https://docs.angularjs.org/api/auto/service/$provide#decorator), at config time using the [`$provide`](https://docs.angularjs.org/api/auto/service/$provide) service, on the [`$exceptionHandler`](https://docs.angularjs.org/api/ng/service/$exceptionHandler) service to perform custom actions when exceptions occur. - - *Why?*: Provides a consistent way to handle uncaught AngularJS exceptions for development-time or run-time. - - Note: Another option is to override the service instead of using a decorator. This is a fine option, but if you want to keep the default behavior and extend it a decorator is recommended. - - ```javascript - /* recommended */ - angular - .module('blocks.exception') - .config(exceptionConfig); - - exceptionConfig.$inject = ['$provide']; - - function exceptionConfig($provide) { - $provide.decorator('$exceptionHandler', extendExceptionHandler); - } - - extendExceptionHandler.$inject = ['$delegate', 'toastr']; - - function extendExceptionHandler($delegate, toastr) { - return function(exception, cause) { - $delegate(exception, cause); - var errorData = { - exception: exception, - cause: cause - }; - /** - * Could add the error to a service's collection, - * add errors to $rootScope, log errors to remote web server, - * or log locally. Or throw hard. It is entirely up to you. - * throw exception; - */ - toastr.error(exception.msg, errorData); - }; - } - ``` - -### Exception Catchers - - - Create a factory that exposes an interface to catch and gracefully handle exceptions. - - *Why?*: Provides a consistent way to catch exceptions that may be thrown in your code (e.g. during XHR calls or promise failures). - - Note: The exception catcher is good for catching and reacting to specific exceptions from calls that you know may throw one. For example, when making an XHR call to retrieve data from a remote web service and you want to catch any exceptions from that service and react uniquely. - - ```javascript - /* recommended */ - angular - .module('blocks.exception') - .factory('exception', exception); - - exception.$inject = ['logger']; - - function exception(logger) { - var service = { - catcher: catcher - }; - return service; - - function catcher(message) { - return function(reason) { - logger.error(message, reason); - }; - } - } - ``` - -### Route Errors - - - Handle and log all routing errors using [`$routeChangeError`](https://docs.angularjs.org/api/ngRoute/service/$route#$routeChangeError). - - *Why?*: Provides a consistent way handle all routing errors. - - *Why?*: Potentially provides a better user experience if a routing error occurs and you route them to a friendly screen with more details or recovery options. - - ```javascript - /* recommended */ - function handleRoutingErrors() { - /** - * Route cancellation: - * On routing error, go to the dashboard. - * Provide an exit clause if it tries to do it twice. - */ - $rootScope.$on('$routeChangeError', - function(event, current, previous, rejection) { - var destination = (current && (current.title || current.name || current.loadedTemplateUrl)) || - 'unknown target'; - var msg = 'Error routing to ' + destination + '. ' + (rejection.msg || ''); - /** - * Optionally log using a custom service or $log. - * (Don't forget to inject custom service) - */ - logger.warning(msg, [current]); - } - ); - } - ``` - -**[⬆ De volta ao topo ⬆](#tabela-de-conte%C3%BAdo)** - -## Naming - -### Naming Guidelines - - - Use consistent names for all components following a pattern that describes the component's feature then (optionally) its type. My recommended pattern is `feature.type.js`. There are 2 names for most assets: - * the file name (`avengers.controller.js`) - * the registered component name with Angular (`AvengersController`) - - *Why?*: Naming conventions help provide a consistent way to find content at a glance. Consistency within the project is vital. Consistency with a team is important. Consistency across a company provides tremendous efficiency. - - *Why?*: The naming conventions should simply help you find your code faster and make it easier to understand. - -### Feature File Names - - - Use consistent names for all components following a pattern that describes the component's feature then (optionally) its type. My recommended pattern is `feature.type.js`. - - *Why?*: Provides a consistent way to quickly identify components. - - *Why?*: Provides pattern matching for any automated tasks. - - ```javascript - /** - * common options - */ - - // Controllers - avengers.js - avengers.controller.js - avengersController.js - - // Services/Factories - logger.js - logger.service.js - loggerService.js - ``` - - ```javascript - /** - * recommended - */ - - // controllers - avengers.controller.js - avengers.controller.spec.js - - // services/factories - logger.service.js - logger.service.spec.js - - // constants - constants.js - - // module definition - avengers.module.js - - // routes - avengers.routes.js - avengers.routes.spec.js - - // configuration - avengers.config.js - - // directives - avenger-profile.directive.js - avenger-profile.directive.spec.js - ``` - - Note: Another common convention is naming controller files without the word `controller` in the file name such as `avengers.js` instead of `avengers.controller.js`. All other conventions still hold using a suffix of the type. Controllers are the most common type of component so this just saves typing and is still easily identifiable. I recommend you choose 1 convention and be consistent for your team. - - ```javascript - /** - * recommended - */ - // Controllers - avengers.js - avengers.spec.js - ``` - -### Test File Names - - - Name test specifications similar to the component they test with a suffix of `spec`. - - *Why?*: Provides a consistent way to quickly identify components. - - *Why?*: Provides pattern matching for [karma](http://karma-runner.github.io/) or other test runners. - - ```javascript - /** - * recommended - */ - avengers.controller.spec.js - logger.service.spec.js - avengers.routes.spec.js - avenger-profile.directive.spec.js - ``` - -### Controller Names - - - Use consistent names for all controllers named after their feature. Use UpperCamelCase for controllers, as they are constructors. - - *Why?*: Provides a consistent way to quickly identify and reference controllers. - - *Why?*: UpperCamelCase is conventional for identifying object that can be instantiated using a constructor. - - ```javascript - /** - * recommended - */ - - // avengers.controller.js - angular - .module - .controller('HeroAvengers', HeroAvengers); - - function HeroAvengers(){ } - ``` - -### Controller Name Suffix - - - Append the controller name with the suffix `Controller` or with no suffix. Choose 1, not both. - - *Why?*: The `Controller` suffix is more commonly used and is more explicitly descriptive. - - *Why?*: Omitting the suffix is more succinct and the controller is often easily identifiable even without the suffix. - - ```javascript - /** - * recommended: Option 1 - */ - - // avengers.controller.js - angular - .module - .controller('Avengers', Avengers); - - function Avengers(){ } - ``` - - ```javascript - /** - * recommended: Option 2 - */ - - // avengers.controller.js - angular - .module - .controller('AvengersController', AvengersController); - - function AvengersController(){ } - ``` - -### Factory Names - - - Use consistent names for all factories named after their feature. Use camel-casing for services and factories. - - *Why?*: Provides a consistent way to quickly identify and reference factories. - - ```javascript - /** - * recommended - */ - - // logger.service.js - angular - .module - .factory('logger', logger); - - function logger(){ } - ``` - -### Directive Component Names - - - Use consistent names for all directives using camel-case. Use a short prefix to describe the area that the directives belong (some example are company prefix or project prefix). - - *Why?*: Provides a consistent way to quickly identify and reference components. - - ```javascript - /** - * recommended - */ - - // avenger.profile.directive.js - angular - .module - .directive('xxAvengerProfile', xxAvengerProfile); - - // usage is - - function xxAvengerProfile(){ } - ``` - -### Modules - - - When there are multiple modules, the main module file is named `app.module.js` while other dependent modules are named after what they represent. For example, an admin module is named `admin.module.js`. The respective registered module names would be `app` and `admin`. A single module app might be named `app.js`, omitting the module moniker. - - *Why?*: An app with 1 module is named `app.js`. It is the app, so why not be super simple. - - *Why?*: Provides consistency for multiple module apps, and for expanding to large applications. - - *Why?*: Provides easy way to use task automation to load all module definitions first, then all other angular files (for bundling). - -### Configuration - - - Separate configuration for a module into its own file named after the module. A configuration file for the main `app` module is named `app.config.js` (or simply `config.js`). A configuration for a module named `admin.module.js` is named `admin.config.js`. - - *Why?*: Separates configuration from module definition, components, and active code. - - *Why?*: Provides a identifiable place to set configuration for a module. - -### Routes - - - Separate route configuration into its own file. Examples might be `app.route.js` for the main module and `admin.route.js` for the `admin` module. Even in smaller apps I prefer this separation from the rest of the configuration. An alternative is a longer name such as `admin.config.route.js`. - -**[⬆ De volta ao topo ⬆](#tabela-de-conte%C3%BAdo)** - -## Application Structure LIFT Principle -### LIFT - - - Structure your app such that you can `L`ocate your code quickly, `I`dentify the code at a glance, keep the `F`lattest structure you can, and `T`ry to stay DRY. The structure should follow these 4 basic guidelines. - - *Why LIFT?*: Provides a consistent structure that scales well, is modular, and makes it easier to increase developer efficiency by finding code quickly. Another way to check your app structure is to ask yourself: How quickly can you open and work in all of the related files for a feature? - - When I find my structure is not feeling comfortable, I go back and revisit these LIFT guidelines - - 1. `L`ocating our code is easy - 2. `I`dentify code at a glance - 3. `F`lat structure as long as we can - 4. `T`ry to stay DRY (Don’t Repeat Yourself) or T-DRY - -### Locate - - - Make locating your code intuitive, simple and fast. - - *Why?*: I find this to be super important for a project. If the team cannot find the files they need to work on quickly, they will not be able to work as efficiently as possible, and the structure needs to change. You may not know the file name or where its related files are, so putting them in the most intuitive locations and near each other saves a ton of time. A descriptive folder structure can help with this. - - ``` - /bower_components - /client - /app - /avengers - /blocks - /exception - /logger - /core - /dashboard - /data - /layout - /widgets - /content - index.html - .bower.json - ``` - -### Identify - - - When you look at a file you should instantly know what it contains and represents. - - *Why?*: You spend less time hunting and pecking for code, and become more efficient. If this means you want longer file names, then so be it. Be descriptive with file names and keeping the contents of the file to exactly 1 component. Avoid files with multiple controllers, multiple services, or a mixture. There are deviations of the 1 per file rule when I have a set of very small features that are all related to each other, they are still easily identifiable. - -### Flat - - - Keep a flat folder structure as long as possible. When you get to 7+ files, begin considering separation. - - *Why?*: Nobody wants to search 7 levels of folders to find a file. Think about menus on web sites … anything deeper than 2 should take serious consideration. In a folder structure there is no hard and fast number rule, but when a folder has 7-10 files, that may be time to create subfolders. Base it on your comfort level. Use a flatter structure until there is an obvious value (to help the rest of LIFT) in creating a new folder. - -### T-DRY (Try to Stick to DRY) - - - Be DRY, but don't go nuts and sacrifice readability. - - *Why?*: Being DRY is important, but not crucial if it sacrifices the others in LIFT, which is why I call it T-DRY. I don’t want to type session-view.html for a view because, well, it’s obviously a view. If it is not obvious or by convention, then I name it. - -**[⬆ De volta ao topo ⬆](#tabela-de-conte%C3%BAdo)** - -## Application Structure - -### Overall Guidelines - - - Have a near term view of implementation and a long term vision. In other words, start small and but keep in mind on where the app is heading down the road. All of the app's code goes in a root folder named `app`. All content is 1 feature per file. Each controller, service, module, view is in its own file. All 3rd party vendor scripts are stored in another root folder and not in the `app` folder. I didn't write them and I don't want them cluttering my app (`bower_components`, `scripts`, `lib`). - - Note: Find more details and reasoning behind the structure at [this original post on application structure](http://www.johnpapa.net/angular-app-structuring-guidelines/). - -### Layout - - - Place components that define the overall layout of the application in a folder named `layout`. These may include a shell view and controller may act as the container for the app, navigation, menus, content areas, and other regions. - - *Why?*: Organizes all layout in a single place re-used throughout the application. - -### Folders-by-Feature Structure - - - Create folders named for the feature they represent. When a folder grows to contain more than 7 files, start to consider creating a folder for them. Your threshold may be different, so adjust as needed. - - *Why?*: A developer can locate the code, identify what each file represents at a glance, the structure is flat as can be, and there is no repetitive nor redundant names. - - *Why?*: The LIFT guidelines are all covered. - - *Why?*: Helps reduce the app from becoming cluttered through organizing the content and keeping them aligned with the LIFT guidelines. - - *Why?*: When there are a lot of files (10+) locating them is easier with a consistent folder structures and more difficult in flat structures. - - ```javascript - /** - * recommended - */ - - app/ - app.module.js - app.config.js - app.routes.js - components/ - calendar.directive.js - calendar.directive.html - user-profile.directive.js - user-profile.directive.html - layout/ - shell.html - shell.controller.js - topnav.html - topnav.controller.js - people/ - attendees.html - attendees.controller.js - speakers.html - speakers.controller.js - speaker-detail.html - speaker-detail.controller.js - services/ - data.service.js - localstorage.service.js - logger.service.js - spinner.service.js - sessions/ - sessions.html - sessions.controller.js - session-detail.html - session-detail.controller.js - ``` - - ![Sample App Structure](https://raw.githubusercontent.com/johnpapa/angularjs-styleguide/master/assets/modularity-2.png) - - Note: Do not use structuring using folders-by-type. This requires moving to multiple folders when working on a feature and gets unwieldy quickly as the app grows to 5, 10 or 25+ views and controllers (and other features), which makes it more difficult than folder-by-feature to locate files. - - ```javascript - /* - * avoid - * Alternative folders-by-type. - * I recommend "folders-by-feature", instead. - */ - - app/ - app.module.js - app.config.js - app.routes.js - controllers/ - attendees.js - session-detail.js - sessions.js - shell.js - speakers.js - speaker-detail.js - topnav.js - directives/ - calendar.directive.js - calendar.directive.html - user-profile.directive.js - user-profile.directive.html - services/ - dataservice.js - localstorage.js - logger.js - spinner.js - views/ - attendees.html - session-detail.html - sessions.html - shell.html - speakers.html - speaker-detail.html - topnav.html - ``` - -**[⬆ De volta ao topo ⬆](#tabela-de-conte%C3%BAdo)** - -## Modularity - -### Many Small, Self Contained Modules - - - Create small modules that encapsulate one responsibility. - - *Why?*: Modular applications make it easy to plug and go as they allow the development teams to build vertical slices of the applications and roll out incrementally. This means we can plug in new features as we develop them. - -### Create an App Module - - - Create an application root module whose role is pull together all of the modules and features of your application. Name this for your application. - - *Why?*: AngularJS encourages modularity and separation patterns. Creating an application root module whose role is to tie your other modules together provides a very straightforward way to add or remove modules from your application. - -### Keep the App Module Thin - - - Only put logic for pulling together the app in the application module. Leave features in their own modules. - - *Why?*: Adding additional roles to the application root to get remote data, display views, or other logic not related to pulling the app together muddies the app module and make both sets of features harder to reuse or turn off. - -### Feature Areas are Modules - - - Create modules that represent feature areas, such as layout, reusable and shared services, dashboards, and app specific features (e.g. customers, admin, sales). - - *Why?*: Self contained modules can be added to the application will little or no friction. - - *Why?*: Sprints or iterations can focus on feature areas and turn them on at the end of the sprint or iteration. - - *Why?*: Separating feature areas into modules makes it easier to test the modules in isolation and reuse code. - -### Reusable Blocks are Modules - - - Create modules that represent reusable application blocks for common services such as exception handling, logging, diagnostics, security, and local data stashing. - - *Why?*: These types of features are needed in many applications, so by keeping them separated in their own modules they can be application generic and be reused across applications. - -### Module Dependencies - - - The application root module depends on the app specific feature modules, the feature modules have no direct dependencies, the cross-application modules depend on all generic modules. - - ![Modularity and Dependencies](https://raw.githubusercontent.com/johnpapa/angularjs-styleguide/master/assets/modularity-1.png) - - *Why?*: The main app module contains a quickly identifiable manifest of the application's features. - - *Why?*: Cross application features become easier to share. The features generally all rely on the same cross application modules, which are consolidated in a single module (`app.core` in the image). - - *Why?*: Intra-App features such as shared data services become easy to locate and share from within `app.core` (choose your favorite name for this module). - - Note: This is a strategy for consistency. There are many good options here. Choose one that is consistent, follows AngularJS's dependency rules, and is easy to maintain and scale. - - > My structures vary slightly between projects but they all follow these guidelines for structure and modularity. The implementation may vary depending on the features and the team. In other words, don't get hung up on an exact like-for-like structure but do justify your structure using consistency, maintainability, and efficiency in mind. - -**[⬆ De volta ao topo ⬆](#tabela-de-conte%C3%BAdo)** - -## Angular $ Wrapper Services - -### $document and $window - - - Use [`$document`](https://docs.angularjs.org/api/ng/service/$document) and [`$window`](https://docs.angularjs.org/api/ng/service/$window) instead of `document` and `window`. - - *Why?*: These services are wrapped by Angular and more easily testable than using document and window in tests. This helps you avoid having to mock document and window yourself. - -### $timeout and $interval - - - Use [`$timeout`](https://docs.angularjs.org/api/ng/service/$timeout) and [`$interval`](https://docs.angularjs.org/api/ng/service/$interval) instead of `setTimeout` and `setInterval` . - - *Why?*: These services are wrapped by Angular and more easily testable and handle AngularJS's digest cycle thus keeping data binding in sync. - -**[⬆ De volta ao topo ⬆](#tabela-de-conte%C3%BAdo)** - -## Testing -Unit testing helps maintain clean code, as such I included some of my recommendations for unit testing foundations with links for more information. - -### Write Tests with Stories - - - Write a set of tests for every story. Start with an empty test and fill them in as you write the code for the story. - - *Why?*: Writing the test descriptions helps clearly define what your story will do, will not do, and how you can measure success. - - ```javascript - it('should have Avengers controller', function() { - //TODO - }); - - it('should find 1 Avenger when filtered by name', function() { - //TODO - }); - - it('should have 10 Avengers', function() {} - //TODO (mock data?) - }); - - it('should return Avengers via XHR', function() {} - //TODO ($httpBackend?) - }); - - // and so on - ``` - -### Testing Library - - - Use [Jasmine](http://jasmine.github.io/) or [Mocha](http://visionmedia.github.io/mocha/) for unit testing. - - *Why?*: Both Jasmine and Mocha are widely used in the AngularJS community. Both are stable, well maintained, and provide robust testing features. - - Note: When using Mocha, also consider choosing an assert library such as [Chai](http://chaijs.com). - -### Test Runner - - - Use [Karma](http://karma-runner.github.io) as a test runner. - - *Why?*: Karma is easy to configure to run once or automatically when you change your code. - - *Why?*: Karma hooks into your Continuous Integration process easily on its own or through Grunt or Gulp. - - *Why?*: Some IDE's are beginning to integrate with Karma, such as [WebStorm](http://www.jetbrains.com/webstorm/) and [Visual Studio](http://visualstudiogallery.msdn.microsoft.com/02f47876-0e7a-4f6c-93f8-1af5d5189225). - - *Why?*: Karma works well with task automation leaders such as [Grunt](http://www.gruntjs.com) (with [grunt-karma](https://github.com/karma-runner/grunt-karma)) and [Gulp](http://www.gulpjs.com) (with [gulp-karma](https://github.com/lazd/gulp-karma)). - -### Stubbing and Spying - - - Use Sinon for stubbing and spying. - - *Why?*: Sinon works well with both Jasmine and Mocha and extends the stubbing and spying features they offer. - - *Why?*: Sinon makes it easier to toggle between Jasmine and Mocha, if you want to try both. - -### Headless Browser - - - Use [PhantomJS](http://phantomjs.org/) to run your tests on a server. - - *Why?*: PhantomJS is a headless browser that helps run your tests without needing a "visual" browser. So you do not have to install Chrome, Safari, IE, or other browsers on your server. - - Note: You should still test on all browsers in your environment, as appropriate for your target audience. - -### Code Analysis - - - Run JSHint on your tests. - - *Why?*: Tests are code. JSHint can help identify code quality issues that may cause the test to work improperly. - -### Alleviate Globals for JSHint Rules on Tests - - - Relax the rules on your test code to allow for common globals such as `describe` and `expect`. - - *Why?*: Your tests are code and require the same attention and code quality rules as all of your production code. However, global variables used by the testing framework, for example, can be relaxed by including this in your test specs. - - ```javascript - /* global sinon, describe, it, afterEach, beforeEach, expect, inject */ - ``` - - ![Testing Tools](https://raw.githubusercontent.com/johnpapa/angularjs-styleguide/master/assets/testing-tools.png) - -**[⬆ De volta ao topo ⬆](#tabela-de-conte%C3%BAdo)** - -## Animations - -### Usage - - - Use subtle [animations with AngularJS](https://docs.angularjs.org/guide/animations) to transition between states for views and primary visual elements. Include the [ngAnimate module](https://docs.angularjs.org/api/ngAnimate). The 3 keys are subtle, smooth, seamless. - - *Why?*: Subtle animations can improve User Experience when used appropriately. - - *Why?*: Subtle animations can improve perceived performance as views transition. - -### Sub Second - - - Use short durations for animations. I generally start with 300ms and adjust until appropriate. - - *Why?*: Long animations can have the reverse affect on User Experience and perceived performance by giving the appearance of a slow application. - -### animate.css - - - Use [animate.css](http://daneden.github.io/animate.css/) for conventional animations. - - *Why?*: The animations that animate.css provides are fast, smooth, and easy to add to your application. - - *Why?*: Provides consistency in your animations. - - *Why?*: animate.css is widely used and tested. - - Note: See this [great post by Matias Niemelä on AngularJS animations](http://www.yearofmoo.com/2013/08/remastered-animation-in-angularjs-1-2.html) - -**[⬆ De volta ao topo ⬆](#tabela-de-conte%C3%BAdo)** - -## Comments - -### jsDoc - - - If planning to produce documentation, use [`jsDoc`](http://usejsdoc.org/) syntax to document function names, description, params and returns. Use `@namespace` and `@memberOf` to match your app structure. - - *Why?*: You can generate (and regenerate) documentation from your code, instead of writing it from scratch. - - *Why?*: Provides consistency using a common industry tool. - - ```javascript - /** - * Logger Factory - * @namespace Factories - */ - (function() { - angular - .module('app') - .factory('logger', logger); - - /** - * @namespace Logger - * @desc Application wide logger - * @memberOf Factories - */ - function logger($log) { - var service = { - logError: logError - }; - return service; - - //////////// - - /** - * @name logError - * @desc Logs errors - * @param {String} msg Message to log - * @returns {String} - * @memberOf Factories.Logger - */ - function logError(msg) { - var loggedMsg = 'Error: ' + msg; - $log.error(loggedMsg); - return loggedMsg; - }; - } - })(); - ``` - -**[⬆ De volta ao topo ⬆](#tabela-de-conte%C3%BAdo)** - -## JS Hint - -### Use an Options File - - - Use JS Hint for linting your JavaScript and be sure to customize the JS Hint options file and include in source control. See the [JS Hint docs](http://www.jshint.com/docs/) for details on the options. - - *Why?*: Provides a first alert prior to committing any code to source control. - - *Why?*: Provides consistency across your team. - - ```javascript - { - "bitwise": true, - "camelcase": true, - "curly": true, - "eqeqeq": true, - "es3": false, - "forin": true, - "freeze": true, - "immed": true, - "indent": 4, - "latedef": "nofunc", - "newcap": true, - "noarg": true, - "noempty": true, - "nonbsp": true, - "nonew": true, - "plusplus": false, - "quotmark": "single", - "undef": true, - "unused": false, - "strict": false, - "maxparams": 10, - "maxdepth": 5, - "maxstatements": 40, - "maxcomplexity": 8, - "maxlen": 120, - - "asi": false, - "boss": false, - "debug": false, - "eqnull": true, - "esnext": false, - "evil": false, - "expr": false, - "funcscope": false, - "globalstrict": false, - "iterator": false, - "lastsemic": false, - "laxbreak": false, - "laxcomma": false, - "loopfunc": true, - "maxerr": false, - "moz": false, - "multistr": false, - "notypeof": false, - "proto": false, - "scripturl": false, - "shadow": false, - "sub": true, - "supernew": false, - "validthis": false, - "noyield": false, - - "browser": true, - "node": true, - - "globals": { - "angular": false, - "$": false - } - } - ``` - -**[⬆ De volta ao topo ⬆](#tabela-de-conte%C3%BAdo)** - -## Constants - -### Vendor Globals - - - Create an AngularJS Constant for vendor libraries' global variables. - - *Why?*: Provides a way to inject vendor libraries that otherwise are globals. This improves code testability by allowing you to more easily know what the dependencies of your components are (avoids leaky abstractions). It also allows you to mock these dependencies, where it makes sense. - - ```javascript - // constants.js - - /* global toastr:false, moment:false */ - (function() { - 'use strict'; - - angular - .module('app.core') - .constant('toastr', toastr) - .constant('moment', moment); - })(); - ``` - -**[⬆ De volta ao topo ⬆](#tabela-de-conte%C3%BAdo)** - -## File Templates and Snippets -Use file templates or snippets to help follow consistent styles and patterns. Here are templates and/or snippets for some of the web development editors and IDEs. - -### Sublime Text - - - AngularJS snippets that follow these styles and guidelines. - - - Download the [Sublime Angular snippets](assets/sublime-angular-snippets.zip) - - Place it in your Packages folder - - Restart Sublime - - In a JavaScript file type these commands followed by a `TAB` - - ```javascript - ngcontroller // creates an Angular controller - ngdirective // creates an Angular directive - ngfactory // creates an Angular factory - ngmodule // creates an Angular module - ``` - -### Visual Studio - - - AngularJS file templates that follow these styles and guidelines can be found at [SideWaffle](http://www.sidewaffle.com) - - - Download the [SideWaffle](http://www.sidewaffle.com) Visual Studio extension (vsix file) - - Run the vsix file - - Restart Visual Studio - -### WebStorm - - - AngularJS snippets and file templates that follow these styles and guidelines. You can import them into your WebStorm settings: - - - Download the [WebStorm AngularJS file templates and snippets](assets/webstorm-angular-file-template.settings.jar) - - Open WebStorm and go to the `File` menu - - Choose the `Import Settings` menu option - - Select the file and click `OK` - - In a JavaScript file type these commands followed by a `TAB`: - - ```javascript - ng-c // creates an Angular controller - ng-f // creates an Angular factory - ng-m // creates an Angular module - ``` - -**[⬆ De volta ao topo ⬆](#tabela-de-conte%C3%BAdo)** - -## AngularJS docs -For anything else, API reference, check the [Angular documentation](//docs.angularjs.org/api). - -## Contributing - -Open an issue first to discuss potential changes/additions. If you have questions with the guide, feel free to leave them as issues in the repository. If you find a typo, create a pull request. The idea is to keep the content up to date and use github’s native feature to help tell the story with issues and PR’s, which are all searchable via google. Why? Because odds are if you have a question, someone else does too! You can learn more here at about how to contribute. - -*By contributing to this repository you are agreeing to make your content available subject to the license of this repository.* - -### Process - 1. Discuss the changes in an Issue. - 1. Open a Pull Request, reference the issue, and explain the change and why it adds value. - 1. The Pull Request will be evaluated and either merged or declined. - -## License - -_tldr; Use this guide. Attributions are appreciated._ - -### (The MIT License) - -Copyright (c) 2014 [John Papa](http://johnpapa.net) - -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. - -**[⬆ De volta ao topo ⬆](#tabela-de-conte%C3%BAdo)** From 9bfa0dd99b1e2fc2afe56bf2e68496e3ea11df3a Mon Sep 17 00:00:00 2001 From: ericdouglas Date: Sat, 22 Nov 2014 20:47:08 -0200 Subject: [PATCH 033/567] translated constants - pt-br --- i18n/PT-BR.md | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/i18n/PT-BR.md b/i18n/PT-BR.md index 84431120..1e07ae3d 100644 --- a/i18n/PT-BR.md +++ b/i18n/PT-BR.md @@ -2360,11 +2360,13 @@ Unit testing helps maintain clean code, as such I included some of my recommenda ## Constants -### Vendor Globals +*ou Constantes* - - Create an AngularJS Constant for vendor libraries' global variables. +### Globais de terceiros (*vendors*) - *Why?*: Provides a way to inject vendor libraries that otherwise are globals. This improves code testability by allowing you to more easily know what the dependencies of your components are (avoids leaky abstractions). It also allows you to mock these dependencies, where it makes sense. + - Cria uma *Constant* no AngularJS para variáveis globais de bibliotecas de terceiros. + + *Por que?*: Fornece uma forma de injetar bibliotecas de terceiros que de outra forma seriam globais. Isso melhora a testabilidade do código permitindo a você conhecer mais facilmente quais dependências os seus componentes têm (evita vazamento de abstrações). Também permite que você simule estas dependências, o que faz sentido. ```javascript // constants.js From b29377771c9c15148b7ff5312a54fdc9007a016d Mon Sep 17 00:00:00 2001 From: John Papa Date: Sun, 23 Nov 2014 10:46:52 -0500 Subject: [PATCH 034/567] dom manipulation title change --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 0a2372ad..5156b2fc 100644 --- a/README.md +++ b/README.md @@ -1071,7 +1071,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see Note: There are many naming options for directives, especially since they can be used in narrow or wide scopes. Choose one that makes the directive and it's file name distinct and clear. Some examples are below, but see the naming section for more recommendations. -### Limit DOM Manipulation +### Manipulate DOM in a Directive ###### [Style [Y072](#style-y072)] - When manipulating the DOM directly, use a directive. If alternative ways can be used such as using CSS to set styles or the [animation services](https://docs.angularjs.org/api/ngAnimate), Angular templating, [`ngShow`](https://docs.angularjs.org/api/ng/directive/ngShow) or [`ngHide`](https://docs.angularjs.org/api/ng/directive/ngHide), then use those instead. For example, if the directive simply hides and shows, use ngHide/ngShow. From a16e91ac0a1339d5eec5f194bb4b1b17d6058fce Mon Sep 17 00:00:00 2001 From: John Papa Date: Sun, 23 Nov 2014 10:51:36 -0500 Subject: [PATCH 035/567] directive controller outside closure --- README.md | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/README.md b/README.md index c77eb509..498e96af 100644 --- a/README.md +++ b/README.md @@ -1133,6 +1133,8 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see Note: Regarding dependency injection, see [Manually Identify Dependencies](#manual-annotating-for-dependency-injection). + Note: Note that the directive's controller is outside the directive's closure. This style eliminates issues where the injection gets created as unreachable code after a `return`. + ```html
``` @@ -1154,27 +1156,27 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see controllerAs: 'vm' }; - ExampleController.$inject = ['$scope']; - return directive; - function ExampleController($scope) { - // Injecting $scope just for comparison - var vm = this; - - vm.min = 3; - vm.max = $scope.max; - console.log('CTRL: $scope.max = %i', $scope.max); - console.log('CTRL: vm.min = %i', vm.min); - console.log('CTRL: vm.max = %i', vm.max); - } - function linkFunc(scope, el, attr, ctrl) { console.log('LINK: scope.max = %i', scope.max); console.log('LINK: scope.vm.min = %i', scope.vm.min); console.log('LINK: scope.vm.max = %i', scope.vm.max); } } + + ExampleController.$inject = ['$scope']; + + function ExampleController($scope) { + // Injecting $scope just for comparison + var vm = this; + + vm.min = 3; + vm.max = $scope.max; + console.log('CTRL: $scope.max = %i', $scope.max); + console.log('CTRL: vm.min = %i', vm.min); + console.log('CTRL: vm.max = %i', vm.max); + } ``` ```html From 1e0acec10042e6262aa0edc14e9bb301426bdff4 Mon Sep 17 00:00:00 2001 From: John Papa Date: Sun, 23 Nov 2014 11:01:10 -0500 Subject: [PATCH 036/567] removed some alternatiev naming for clarity --- README.md | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 498e96af..6f15a415 100644 --- a/README.md +++ b/README.md @@ -1816,7 +1816,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see * recommended */ - // avenger.profile.directive.js + // avenger-profile.directive.js angular .module .directive('xxAvengerProfile', xxAvengerProfile); @@ -1828,10 +1828,8 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see ### Modules - - When there are multiple modules, the main module file is named `app.module.js` while other dependent modules are named after what they represent. For example, an admin module is named `admin.module.js`. The respective registered module names would be `app` and `admin`. A single module app might be named `app.js`, omitting the module moniker. + - When there are multiple modules, the main module file is named `app.module.js` while other dependent modules are named after what they represent. For example, an admin module is named `admin.module.js`. The respective registered module names would be `app` and `admin`. - *Why?*: An app with 1 module is named `app.js`. It is the app, so why not be super simple. - *Why?*: Provides consistency for multiple module apps, and for expanding to large applications. *Why?*: Provides easy way to use task automation to load all module definitions first, then all other angular files (for bundling). @@ -1846,7 +1844,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see ### Routes - - Separate route configuration into its own file. Examples might be `app.route.js` for the main module and `admin.route.js` for the `admin` module. Even in smaller apps I prefer this separation from the rest of the configuration. An alternative is a longer name such as `admin.config.route.js`. + - Separate route configuration into its own file. Examples might be `app.route.js` for the main module and `admin.route.js` for the `admin` module. Even in smaller apps I prefer this separation from the rest of the configuration. **[Back to top](#table-of-contents)** From 083a580654810c5920c6f9a73f5d9df738339f8a Mon Sep 17 00:00:00 2001 From: John Papa Date: Sun, 23 Nov 2014 11:02:57 -0500 Subject: [PATCH 037/567] app manifest definition --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 6f15a415..1d766e5d 100644 --- a/README.md +++ b/README.md @@ -2035,6 +2035,8 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see *Why?*: Adding additional roles to the application root to get remote data, display views, or other logic not related to pulling the app together muddies the app module and make both sets of features harder to reuse or turn off. + *Why?*: The app module becomes a manifest that describes which modules help define the application. + ### Feature Areas are Modules - Create modules that represent feature areas, such as layout, reusable and shared services, dashboards, and app specific features (e.g. customers, admin, sales). From 4fedb3daef60c9ecfa14038f46397d3e30da5ce3 Mon Sep 17 00:00:00 2001 From: Rob Zolkos Date: Mon, 24 Nov 2014 17:00:43 +1100 Subject: [PATCH 038/567] Fix typo --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 86e25961..7e4f9eda 100644 --- a/README.md +++ b/README.md @@ -2100,7 +2100,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see - Create modules that represent feature areas, such as layout, reusable and shared services, dashboards, and app specific features (e.g. customers, admin, sales). - *Why?*: Self contained modules can be added to the application will little or no friction. + *Why?*: Self contained modules can be added to the application with little or no friction. *Why?*: Sprints or iterations can focus on feature areas and turn them on at the end of the sprint or iteration. From 3dbdbef29027cb8ace3dc6cd018768c751192295 Mon Sep 17 00:00:00 2001 From: angelochiello Date: Mon, 24 Nov 2014 09:15:15 +0100 Subject: [PATCH 039/567] PR #147 Updated as PR #147 --- i18n/it-IT.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/i18n/it-IT.md b/i18n/it-IT.md index 50ecc376..e4ae4628 100644 --- a/i18n/it-IT.md +++ b/i18n/it-IT.md @@ -2103,6 +2103,8 @@ Nonostante questa guida spieghi i *cosa*, *come* e *perché*, trovo che sia di a - Nel modulo principale metti solo la logica che serva da collante per l'app. Lascia le funzioni ognuno al proprio modulo. *Perché?*: L'aggiunta di ruoli addizionali al modulo principale per il recupero dei dati, il mostrare viste o altra logica non correlata al tenere insieme l'applicazione sporca il modulo principale e rende entrambi gli insiemi di funzionalità più complessi da riusare o rimuovere. + + *Perché?*: Il modulo app diventa un manifesto che descrive quali moduli aiutano a definire l'applicazione. ### Aree di funzionalità sono Moduli ###### [Stile [Y163](#stile-y163)] From af67f18a90e0f8e6efd0c453c656fa85ed18d20c Mon Sep 17 00:00:00 2001 From: angelochiello Date: Mon, 24 Nov 2014 09:30:57 +0100 Subject: [PATCH 040/567] PR #146 Updated as PR #146 --- i18n/it-IT.md | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/i18n/it-IT.md b/i18n/it-IT.md index e4ae4628..58bb7b8a 100644 --- a/i18n/it-IT.md +++ b/i18n/it-IT.md @@ -1164,6 +1164,8 @@ Nonostante questa guida spieghi i *cosa*, *come* e *perché*, trovo che sia di a Nota: Le directive sotto dimostrano alcuni dei modi in cui puoi usare lo scope all'interno di link e controller di directive usando controllerAs. Ho usato sulla stessa linea il template solo per mettere tutto in un unico posto. Nota: In relazione alla dependency injection, guarda [Annotazioni manuali per la Dependency Injection](#annotazioni-manuali-per-la-dependency-injection). + + Nota: Notare che il controller della directive è al di fuori della closure della directive. Questo stile elimina problematiche dove l'iniezione viene creata come codice non raggiungibile dopo un `return`. ```html
@@ -1187,25 +1189,25 @@ Nonostante questa guida spieghi i *cosa*, *come* e *perché*, trovo che sia di a }; return directive; - ExampleController.$inject = ['$scope']; - function ExampleController($scope) { - // Iniettare $scope solo per confronto - /* jshint validthis:true */ - var vm = this; - - vm.min = 3; - vm.max = $scope.max; - console.log('CTRL: $scope.max = %i', $scope.max); - console.log('CTRL: vm.min = %i', vm.min); - console.log('CTRL: vm.max = %i', vm.max); - } - function linkFunc(scope, el, attr, ctrl) { console.log('LINK: scope.max = %i', scope.max); console.log('LINK: scope.vm.min = %i', scope.vm.min); console.log('LINK: scope.vm.max = %i', scope.vm.max); } } + + ExampleController.$inject = ['$scope']; + + function ExampleController($scope) { + // Iniettare $scope solo per confronto + var vm = this; + + vm.min = 3; + vm.max = $scope.max; + console.log('CTRL: $scope.max = %i', $scope.max); + console.log('CTRL: vm.min = %i', vm.min); + console.log('CTRL: vm.max = %i', vm.max); + } ``` ```html @@ -1868,7 +1870,7 @@ Nonostante questa guida spieghi i *cosa*, *come* e *perché*, trovo che sia di a * consigliato */ - // avenger.profile.directive.js + // avenger-profile.directive.js angular .module .directive('xxAvengerProfile', xxAvengerProfile); @@ -1881,10 +1883,8 @@ Nonostante questa guida spieghi i *cosa*, *come* e *perché*, trovo che sia di a ### Moduli ###### [Stile [Y127](#stile-y127)] - - Quando i sono moduli multipli, il modulo principale è nominato come `app.module.js` mentre altri moduli dipendenti prendono i nomi da ciò che rappresentano. Per esempio, un modulo admin è nominato `admin.module.js`. I rispettivi nomi con i quali sono registrati saranno `app` e `admin`. Una app a modulo singolo si chiamerà `app.js`, omettendo l'appellativo module. + - Quando i sono moduli multipli, il modulo principale è nominato come `app.module.js` mentre altri moduli dipendenti prendono i nomi da ciò che rappresentano. Per esempio, un modulo admin è nominato `admin.module.js`. I rispettivi nomi con i quali sono registrati saranno `app` e `admin`. - *Perché?*: Una app con 1 modulo si chiama `app.js`. È l'app, quindi perché non estremamente semplice. - *Perché?*: Fornisce consistenza per app che hanno più di un modulo e per poter espandere verso applicazioni a larga scala. *Perché?*: Fornisci un modo semplice al fine di usare processi automatici per caricare prima tutte le definizioni di moduli, successivamente tutti gli altri file di Angular (per il bundling). @@ -1901,7 +1901,7 @@ Nonostante questa guida spieghi i *cosa*, *come* e *perché*, trovo che sia di a ### Route ###### [Stile [Y129](#stile-y129)] - - Separa la configurazione delle route nei propri file. Esempi possono essere `app.route.js` per il modulo principale e `admin.route.js` per il modulo `admin`. Anche in piccole app preferisco questa separazione dal resto della configurazione. Una alternativa è un nome più esteso quale `admin.config.route.js`. + - Separa la configurazione delle route nei propri file. Esempi possono essere `app.route.js` per il modulo principale e `admin.route.js` per il modulo `admin`. Anche in piccole app preferisco questa separazione dal resto della configurazione. **[Torna all'inizio](#tavola-dei-contenuti)** From 4139736e052aa56a12e14e2c7587a63603ad88e3 Mon Sep 17 00:00:00 2001 From: angelochiello Date: Mon, 24 Nov 2014 09:32:16 +0100 Subject: [PATCH 041/567] PR #145 Updated as PR #145 --- i18n/it-IT.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/i18n/it-IT.md b/i18n/it-IT.md index 58bb7b8a..8982953c 100644 --- a/i18n/it-IT.md +++ b/i18n/it-IT.md @@ -1076,7 +1076,7 @@ Nonostante questa guida spieghi i *cosa*, *come* e *perché*, trovo che sia di a Nota: Ci sono molte opzioni per i nomi delle directive, in particolare dal momento che possono essere usate in ambiti stretti o larghi. Scegline uno che sia chiaro e distino che dia senso alla directive e il suo nome del file. Alcuni esempi sono sotto ma vedi la sezione sulla nomenclatura per maggiori raccomandazioni. -### Limiti alla manipolazione del DOM +### Manipolare il DOM in una Directive ###### [Stile [Y072](#stile-y072)] - Quando devi manipolare direttamente il DOM, usa una directive. Se possono essere usate delle alternative come settare stili CSS o i [servizi di animazione](https://docs.angularjs.org/api/ngAnimate), templating di Angular, [`ngShow`](https://docs.angularjs.org/api/ng/directive/ngShow) oppure [`ngHide`](https://docs.angularjs.org/api/ng/directive/ngHide), piuttosto usa questi. Per esempio, se la directive semplicemente nasconde e mostra, usa ngHide/ngShow. From fd59f80544f5e3febdb32de9bd2f8c65fa8834d0 Mon Sep 17 00:00:00 2001 From: Aleksandar Bogatinov Date: Mon, 24 Nov 2014 17:51:43 +0100 Subject: [PATCH 042/567] Updated to latest version --- i18n/mk-MK.md | 215 ++++++++++++++++++++++++++------------------------ 1 file changed, 110 insertions(+), 105 deletions(-) diff --git a/i18n/mk-MK.md b/i18n/mk-MK.md index d688f35f..711659e8 100644 --- a/i18n/mk-MK.md +++ b/i18n/mk-MK.md @@ -2,6 +2,8 @@ *Своеволен AngularJS водич на кодирање за тимови од [@john_papa](//twitter.com/john_papa)* +*Преведено од [Александар Богатинов](https://github.com/Bogatinov)* + Доколку барате своеволен стил на кодирање за синтакса, конвенции и структурирање на AngularJS апликации, тогаш сте на правилното место. Овие стилови се базирани на моето искуство во развој на [AngularJS](//angularjs.org), презентации, [Pluralsight тренинг курсеви](http://pluralsight.com/training/Authors/Details/john-papa) и работа во тимови. @@ -54,6 +56,7 @@ ## Single Responsibility ### Правило од 1 +###### [Style [Y001](#style-y001)] - Дефинирај 1 компонента во датотека. @@ -107,7 +110,7 @@ ## IIFE ### JavaScript Closures - +###### [Style [Y010](#style-y010)] - Вгнездете ги AngularJS компоненти во Immediately Invoked Function Expression (IIFE). *Зошто?*: IIFE не ги покажува променливите на глобално ниво. Ова помага при спречување да променливите и декларациите на функциите да живеат подолго од очекуваното на глобалното ниво, што исто така помага во избегнување на судири на променливи со исто име. @@ -173,13 +176,13 @@ ## Modules ### Избегнувајте судири во именување - +###### [Style [Y020](#style-Y020)] - Користите уникатни шаблони на именување со разделувачи за под-модулите. *Зошто?*: Со уникатни имиња избегнувате судири на модули со исто име. Разделувачи ги одредуваат модулите и нивната хиерархија на подмодули. На пример `app` е главниот модул додека `app.dashboard` и `app.users` се модули кои можно е да се зависни од `app`. ### Дефинирање (познати како Setters) - +###### [Style [Y021](#style-Y021)] - Декларирај модули без променлива користејќи ја setter синтаксата. *Зошто?*: Со 1 компонента во датотека, реткост е да поставиш нова променлива во модулот. @@ -208,7 +211,7 @@ ``` ### Getters - +###### [Style [Y022](#style-Y022)] - Кога употребувате модул, избегнувајте користење на променливa. Наместо тоа употребете врзување со getter синтакса. *Зошто?* : Ова создава читлив код и избегнува судири на променливи или протекувања. @@ -231,7 +234,7 @@ ``` ### Setting vs Getting - +###### [Style [Y023](#style-Y023)] - Само еднаш создади и земај го за сите други инстанци. *Зошто?*: Модул треба еднаш да биде создаден, и од тој момент да биде само превземен. @@ -240,7 +243,7 @@ - Употреби `angular.module('app');` за да го превземеш тој модул. ### Именувани vs Анонимни функции - +###### [Style [Y024](#style-Y024)] - Употреби именувани функции наместо да проследиш анонимни функции како повратни повици (callback). *Зошто?*: Ова создава читлив код, кој е полесен за дебагирање и го намалува бројот на вгнездени повратни повици. @@ -278,7 +281,7 @@ ## Controllers ### controllerAs синтакса во Изглед - +###### [Style [Y030](#style-Y030)] - Употреби ја [`controllerAs`](http://www.johnpapa.net/do-you-like-your-angular-controllers-with-or-without-sugar/) синтаксата наместо `класичниот контролер со $scope` синтакса. *Зошто?*: Контролерите се создаваат, се ажурираат и потоа се пристапуваат преку единствена нова инстанца. `controllerAs` синтаксата е поблиску до JavaScript конструктор наспроти `класичната $scope синтакса`. @@ -302,7 +305,7 @@ ``` ### controllerAs синтакса во контролери - +###### [Style [Y031](#style-Y031)] - Употреби `controllerAs` наместо `класичен контролер со $scope` синтакса. - `controllerAs` синтакса користи `this` во контролерите што се поврзува со `$scope` @@ -328,7 +331,7 @@ ``` ### controllerAs со vm - +###### [Style [Y032](#style-Y032)] - Употребете нова променлива за `this` кога употребувате `controllerAs` синтакса. Одлучете се за постојано име на променлива како на пример `vm`, што е кратеница за ViewModel. *Зошто?*: `this` зборот е контекстуален и може да ја промени својата состојба кога се употребува во функција која е во контролерот. Со употреба на нова променлива за `this`, се избегнува овој проблем. @@ -349,14 +352,13 @@ vm.sendMessage = function() { }; } ``` + Забелешка: Можете да ги избегнете предупредувањата од [jshint](http://www.jshint.com/) со поставување коментар над таа линија код. Но, немате потреба доколку функцијата е именувана со ГолемиБукви, што значи дека е конструктор функција т.е. контролер во Ангулар. - Забелешка: Можете да ги избегнете предупредувањата на [jshint](http://www.jshint.com/) со поставување коментар над таа линија на код. - ```javascript /* jshint validthis: true */ var vm = this; - ``` - + ``` + Забелешка: Кога создавате watches во контролерот кога ја користите `controller as` синтаксата, тогаш можете да го надгледувате `vm.*` членот со следната синтакса. (Создавање watches претпазливо бидејќи можат да додадат товар на digest циклусот.) ```javascript @@ -367,7 +369,7 @@ ``` ### Поврзување на членовите на почеток - +###### [Style [Y033](#style-Y033)] - Постави ги членовите кои ќе се поврзат според алфабетски редослед. Наместо да бидат поставени низ кодот во контролерот. *Зошто?*: Поставување на поврзувањата на почетокот го прави кодот полесен за читање и помага за да го најдеш кој член од контролерот е поврзан и употребуван во Прегледот. @@ -455,7 +457,7 @@ ``` ### Декларација на функции за да ја скрие имплементацијата - +###### [Style [Y034](#style-Y034)] - Употребу декларации на функции за да ги скриеш нивните имплементации. Нека членовите за поврзување останат горе. Кога треба да поврзеш функција во контролерот, посочи ја кон декларацијата на таа функција која се појавува подоле во датотеката. Ова е директно поврзано со секцијата Поврзување на членови на почеток. За повеќе детали, проверете го [овој пост](http://www.johnpapa.net/angular-function-declarations-function-expressions-and-readable-code). *Зошто?*: Поставување членови за поврзување на почеток го прави кодот полесен за читање и лесно да забележиме кој член од контролерот може да биде повзан и искористен во Прегледот. (Исто како погоре.) @@ -529,7 +531,7 @@ ``` ### Одлагање Логика во Контролерот - +###### [Style [Y035](#style-Y036)] - Одлагајте логика на во контролерот со делегирање до сервиси и фабрики. *Зошто?*: Логиката може да биде повторно искористена кога е во сервис, од повеќе контролери и изложена преку функција. @@ -569,13 +571,13 @@ ``` ### Контролерите треба да бидат фокусирани - +###### [Style [Y037](#style-Y037)] - Дефинирајте контролер за преглед, и пробајте да не го искористите истиот за други прегледи. Наместо тоа, преместете ја повторно употребливата логика во фабрики и поставете го тој контролер фокусиран за својот преглед. *Why?*: Повторно искористување на контролери со повеќе прегледи е лесно кршливо и тешко за одржување стабилност низ повеќе апликации во е2е тестирање. ### Назначување Контролери - +###### [Style [Y038](#style-Y038)] - Кога контролерот е во пар со прегледот и кога било кој од нив треба да биде повторно искористен од други контролери или прегледи тогаш дефинирај ги контролерите со нивните рута. Забелешка: Доколку Прегледот е вчитан преку други начини наместо рути, тогаш искористете ја `ng-controller="Avengers as vm"` синтаксата. @@ -633,7 +635,7 @@ ## Services ### Singletons - +###### [Style [Y040](#style-Y040)] - Сервиси се инстанцирани со `new` зборот, и се употребуваат со `this` за јавни методи и променливи. Бидејќи се слични со фабрики, користете фабрика за конзистентност. Забелешка: [Сите AngularJS сервиси се singletons](https://docs.angularjs.org/guide/services). Тоа значи дека има само една инстанца од сервис за injector. @@ -671,17 +673,17 @@ ## Factories ### Единствена одговорност - +###### [Style [Y050](#style-Y050)] - Фабрики треба да имаат [единствена одговорност](http://en.wikipedia.org/wiki/Single_responsibility_principle), што е обопштена од својот контекст. Чим фабриката ја надмине единствената цел, тогаш нова фабрика треба да биде создадена. ### Singletons - +###### [Style [Y051](#style-Y051)] - Фабрики се singletons и враќаат објект што ги содржини членовите од тој сервис. Забелешка: [Сите AngularJS сервиси се singletons](https://docs.angularjs.org/guide/services). ### Членовите за пристап на почеток - +###### [Style [Y052](#style-Y052)] - Изложи ги членовите на сервисот кои треба да се повикаат (неговиот интерфејс) на почетокот, користејќи ја техниката [Revealing Module Pattern](http://addyosmani.com/resources/essentialjsdesignpatterns/book/#revealingmodulepatternjavascript). *Зошто?*: Поставување на повикувачките членови на почетокот го прави кодот полесен за читање и помага при лесно забележување на кои членови можат да се повикаат и мораат да бидат тестирани (и/или излажани при тестирање). @@ -737,7 +739,7 @@ ![Фабрики искористуваат "Above the Fold"](https://raw.githubusercontent.com/johnpapa/angularjs-styleguide/master/assets/above-the-fold-2.png) ### Декларации на функции ја кријат имплементацијата - +###### [Style [Y053](#style-Y053)] - Употребете декларации на функции за да ја сокриете имплементацијата. Нека пристапните членови на фабриката бидат поставени на почеток. Додека имплементацијата на декларациите на функциите биде поставена подоле во датотеката. За повеќе детали, посочете со до [овој пост](http://www.johnpapa.net/angular-function-declarations-function-expressions-and-readable-code). *Зошто?*: Поставување на пристапните членови на почеток е лесно за читање и помага при лесно забележување на кои функции на фабриката можат да се пристапат од надвор. @@ -838,7 +840,7 @@ ## Data Services ### Одделени податочни повици - +###### [Style [Y060](#style-Y060)] - Рефакторирај ја логиката со податочни операции и интеракција на податоците во фабриката. Податочни сервиси се одговорни за XHR повици, локално складирање, поставување во меморија и останати податочни операции. *Зошто?*: Одговорноста на контролерот е во презентацијата и собирање информации за прегледот. Нема потреба да се засега како ги добива податоците, само да знае кого да праша за нив. Одделување на податочните сервиси ја преместува логиката за пристап на податоците на податочниот сервис, додека контролерот е поедноставен и фокусиран на прегледот. @@ -913,7 +915,7 @@ ``` ### Вратете Promise од податочни повици - +###### [Style [Y061](#style-Y061)] - Кога повикувате податочен сервис кој враќа promise како што е $http, вратете promise во вашата повикувачка функција. *Зошто?*: Можете да врзете повеќе promise заедно со повеќе акции над податоците откако податочниот повик заврши и го прифати или одбие promise-от. @@ -960,7 +962,7 @@ ## Directives ### Ограничувајте се на 1 на датотека - +###### [Style [Y070](#style-Y070)] - Создадете една директива по датотека. Именувајте ја според директивата. *Зошто?*: Полесно е да ги споите повеќе директиви во една датотека, но потешко да ги разделите тие со цел да бидат споделени низ апликации, модули или само еден модул. @@ -1050,14 +1052,14 @@ Забелешка: Постојат повеќе начини на именување на директиви, посебно што можат да се искористат во широк или краток обем. Одлучете се за еден кој ја прави директивата и нејзиното име јасно и различно. Има неколку примери подоле, но посоветувајте се до секцијата за именување. -### Ограничете DOM манипулација - +### Манипулирајте DOM во директивата +###### [Style [Y072](#style-Y072)] - Кога манипулирате директно со DOM, употребете директива. Ако можат да се употребат други начини, како CSS за стилови или [анимациски сервиси](https://docs.angularjs.org/api/ngAnimate), Angular темплејти, [`ngShow`](https://docs.angularjs.org/api/ng/directive/ngShow) или [`ngHide`](https://docs.angularjs.org/api/ng/directive/ngHide), тогаш употребете ги тие. На пример, ако директивата само се појавува/исчезнува, тогаш употребете ngHide/ngShow. *Зошто?*: Манипулација на DOM е тешка да се тестира, дебагира и притоа постојат подобри начини. (на пример CSS, анимации, темплејти) ### Обезбедете уникатен префикс на директивата - +###### [Style [Y073](#style-Y073)] - Обезбедете краток, уникатен и описен префикс на директивата како `acmeSalesCustomerInfo` што е декларирана во HTML како `acme-sales-customer-info`. *Зошто?*: Уникатниот краток префикс ја идентификува смислата на директивата и нејзиното потекло. На пример, префиксот `cc-` може да укажува дека директивата дел од CodeCamper апликацијата додека `acme-` може да укажува дека директивата е за компанијата Acme. @@ -1065,7 +1067,7 @@ Забелешка: Избегнувајте `ng-` бидејќи тие се резервирани за директивите на AngularJS. Проучете најчесто употребувани директиви со цел да избегнувате судири со имињата, како `ion-` за [Ionic Framework](http://ionicframework.com/). ### Ограничете се на Елементи и Атрибути - +###### [Style [Y074](#style-Y074)] - Кога создавате директива која има смисла како единечен елемент, тогаш ограничете ја на `E` (сопствен елемент) и како опција `A` (сопствен атрибут). Обично, ако треба да биде сопствена контролна единка, тогаш `A` е препорачливо. Најчести водичи дозволуваат `EA`, но насочете се кон имплементација како елемент кога е самостоен и како атрибут доколку го подобрува постоечкиот DOM елемент. *Зошто?*: Има смисла. @@ -1126,7 +1128,7 @@ ``` ### Директиви и ControllerAs - +###### [Style [Y075](#style-Y075)] - Употребете `controller as` синтакса со директива доколку сакате да бидете во согласност со `controller as` на прегледот и неговиот контролер. *Зошто?*: Има смисла, и не е тешко.. @@ -1135,6 +1137,8 @@ Забелешка: Што се однесува до dependency injection, проверете [Рачна Идентификација на Зависности](#manual-annotating-for-dependency-injection). + Забелешка: Контролерот на директивата е надвор од директивата. Овој стил ги оневозможува грешките каде кодот за вметнување на зависностите не се извршува поради поставеност после `return`. + ```html
``` @@ -1155,12 +1159,20 @@ controller : ExampleController, controllerAs: 'vm' }; + return directive; - ExampleController.$inject = ['$scope']; - function ExampleController($scope) { + function linkFunc(scope, el, attr, ctrl) { + console.log('LINK: scope.max = %i', scope.max); + console.log('LINK: scope.vm.min = %i', scope.vm.min); + console.log('LINK: scope.vm.max = %i', scope.vm.max); + } + } + + ExampleController.$inject = ['$scope']; + + function ExampleController($scope) { // Внесување $scope за споредба - /* jshint validthis:true */ var vm = this; vm.min = 3; @@ -1168,14 +1180,7 @@ console.log('CTRL: $scope.max = %i', $scope.max); console.log('CTRL: vm.min = %i', vm.min); console.log('CTRL: vm.max = %i', vm.max); - } - - function linkFunc(scope, el, attr, ctrl) { - console.log('LINK: scope.max = %i', scope.max); - console.log('LINK: scope.vm.min = %i', scope.vm.min); - console.log('LINK: scope.vm.max = %i', scope.vm.max); - } - } + } ``` ```html @@ -1190,7 +1195,7 @@ ## Resolving Promises for a Controller ### Активација на Promises во контролерот - +###### [Style [Y080](#style-Y080)] - Решете се со логиката за започнување на контролерот во `activate` функцијата. *Зошто?*: Поставување на почетна логика во согласно место во контролерот е полесно за лоцирање, полесно за тестирање и го оневозможува распределувањето на почетната логика низ целиот контролер. @@ -1232,7 +1237,7 @@ ``` ### Решавање на патеката преку Promises - +###### [Style [Y081](#style-Y081)] - Кога контролер зависи на решавање на promise, решете ги сите зависности во `$routeProvider` пред логиката на контролерот да биде извршена. Ако треба опционално да ја спречите патеката пред да биде контролерот активиран, решете ја патеката. *Зошто?*: Контролерот може да зависи од податоци пред да се изврши. Овој податок може да дојде преку promise од сопствена фабрика или [$http](https://docs.angularjs.org/api/ng/service/$http). Со употреба на [route resolve](https://docs.angularjs.org/api/ngRoute/provider/$routeProvider) ќе овозможиме promise да се реши пред логиката на контролерот да биде извршена, така што може да зависи од акција во податокот. @@ -1283,7 +1288,6 @@ Avengers.$inject = ['moviesPrepService']; function Avengers(moviesPrepService) { - /* jshint validthis:true */ var vm = this; vm.movies = moviesPrepService.movies; } @@ -1296,7 +1300,7 @@ ## Manual Annotating for Dependency Injection ### Опасно за минифкација - +###### [Style [Y090](#style-Y090)] - Избегнувајте употреба на кратенки за декларација на зависности без употреба на безбеден пристап за минификација. *Зошто?*: Параметрите на компонентата (e.g. контролер, фабрика, итн) ќе бидат претворени во исчезнати променливи. На пример, `common` и `dataservice` може да постанат `a` или `b` и да не бидат најдени од AngularJS. @@ -1319,7 +1323,7 @@ ``` ### Рачна идентификација на зависности - +###### [Style [Y091](#style-Y091)] - Употребете `$inject` за рачна идентификација на вашиоте зависности во AngularJS компонентите. *Зошто?*: Оваа техника се користи во [`ng-annotate`](https://github.com/olov/ng-annotate), што ја препорачувам за автоматизација на создавање на безбедни зависности при минификација. Доколку `ng-annotate` забележи зависност доколку постои, нема да ја повтори. @@ -1392,7 +1396,7 @@ ``` ### Рачна идентификација на зависностите преку решавање на патеки - +###### [Style [Y092](#style-Y092)] - Употребете $inject за рачна идентификација на зависностите преку решавање на патеки во AngularJS компоненти. *Зошто?*: Оваа техника ги разделува анонимните функции за решавање на патеката, кое е полесно за читање. @@ -1424,7 +1428,7 @@ ## Minification and Annotation ### ng-annotate - +###### [Style [Y100](#style-Y100)] - Употребете [ng-annotate](//github.com/olov/ng-annotate) за [Gulp](http://gulpjs.com) или [Grunt](http://gruntjs.com) и поставете го коментарот `/** @ngInject */` над функциите кои им се потребни автоматизиран dependency injection. *Зошто?*: Го заштитува вашиот код од загуба на зависности при минификација. @@ -1500,7 +1504,7 @@ `` ### Употребете Gulp или Grunt за ng-annotate - +###### [Style [Y101](#style-Y101)] - Употребете [gulp-ng-annotate](https://www.npmjs.org/package/gulp-ng-annotate) или [grunt-ng-annotate](https://www.npmjs.org/package/grunt-ng-annotate) во автоматизиран build task. Внесете `/* @ngInject */` пред функцијата која има зависности. *Зошто?*: ng-annotate ќе ги фати повеќето зависности, но понекогаш потребни се навестувања во својата `/* @ngInject */` синтакса. @@ -1533,7 +1537,7 @@ ## Exception Handling ### Декоратори - +###### [Style [Y110](#style-Y110)] - Употребете [decorator](https://docs.angularjs.org/api/auto/service/$provide#decorator), при конфигурација со употреба на [`$provide`](https://docs.angularjs.org/api/auto/service/$provide) сервис, на [`$exceptionHandler`](https://docs.angularjs.org/api/ng/service/$exceptionHandler) сервисот за да извршите лични акции кога ќе се случи исклучок. *Зошто?*: Овозможува постојан начин да се справи со исклучоци кои AngularJS не може да ги фати во development-time или run-time. @@ -1573,7 +1577,7 @@ ``` ### Ловци на исклучоци - +###### [Style [Y111](#style-Y111)] - Создадете фабрика која изложува интерфејс за да улови и грациозно да се справи со исклучокот. *Зошто?*: Обезбедува самостоен начин да ги улови исклучоците кои може да бидат фрлени во вашиот код.(на пример при XHR повици или пад на Promise). @@ -1603,7 +1607,7 @@ ``` ### Грешки при рутирање - +###### [Style [Y112](#style-Y112)] - Справете се и логирајте сите рутирачки грешки со употреба на [`$routeChangeError`](https://docs.angularjs.org/api/ngRoute/service/$route#$routeChangeError). *Зошто?*: Обезбедува постојан начин да се справи со сите рутирачки грешки. @@ -1638,7 +1642,7 @@ ## Naming ### Водич во именување - +###### [Style [Y120](#style-Y120)] - Употребете самостојни имиња за сите компоненти следејќи го шаблонот кој ја опишува функцијата и после (опционално) неговиот тип. Мојот препорачан шаблон е `feature.type.js`. Постојат две имиња за повеќето датотеки: * името на датотеката (`avengers.controller.js`) * регистрираната компонента во Angular (`AvengersController`) @@ -1648,7 +1652,7 @@ *Зошто?*: Конвенцијата при именување треба едностанво да ви помогне побрзо да го најдете кодот и полесно да го разберете. ### Имиња на датотеки по функција - +###### [Style [Y121](#style-Y121)] - Употребете конзистентни имиња за сите компоненти следејќи шаблон што ја опишува функцијата на компонентата и после (опционално) нејзиниот тип. Мојата препорака е `feature.type.js`. *Зошто?*: Обезбедува конзистентен начин за лесна идентификација на компоненти. @@ -1714,7 +1718,7 @@ ``` ### Имиња на датотеки за тестови - +###### [Style [Y122](#style-Y122)] - Имињата на тестовите се слични со компонентата што ја тестираат со додавање на суфикс `spec`. *Зошто?*: Обезбедува конзистентен начин за лесно препознавање компоненти. @@ -1732,7 +1736,7 @@ ``` ### Имиња на контролер - +###### [Style [Y123](#style-Y123)] - Употребете конзистентни имиња за сите контролери именувани по нивните функции. Користете UpperCamelCase за контролери, бидејќи се контруктори. *Зошто?*: Обезбедува конзистентен начин за лесно препознавање и референцирање контролери. @@ -1753,7 +1757,7 @@ ``` ### Суфикс на името на контролерот - +###### [Style [Y124](#style-Y124)] - Додадете суфикс `Controller` на името или без него. Одберете едно, не двете. *Зошто?*: `Controller` суфиксот е почесто користен и експлицитно описен. @@ -1787,7 +1791,7 @@ ``` ### Имиња на фабрики - +###### [Style [Y125](#style-Y125)] - Употребете конзистентни имиња за сите фабрики според нивната функција. Употребете camel-casing за сервиси и фабрики. *Зошто?*: Обезбедува конзистентен начин за брзо препознавање и референцирање фабрики. @@ -1806,7 +1810,7 @@ ``` ### Имиња на директиви - +###### [Style [Y126](#style-Y126)] - Употребете конзистентни имиња за сите директиви со употреба на camel-case. Употребете краток префикс за да опише во која зона припаѓа директивата. (неколку примери се компаниски префикси или проект префикс). *Зошто?*: Обезбедува конзистентен начин за брзо препознавање и референцирање на компоненти. @@ -1816,7 +1820,7 @@ * препорачано */ - // avenger.profile.directive.js + // avenger-profile.directive.js angular .module .directive('xxAvengerProfile', xxAvengerProfile); @@ -1827,17 +1831,15 @@ ``` ### Модули - - - Кога постојат повеќе модули, името на главниот модул е `app.module.js` додека другите зависни модули се именувани според тоа што претставуваат. На пример, админ модул е именувам `admin.module.js`. Соодветниот регистрирани имиња на модули би биле `app` и `admin`. Апликација со еден модул би била наречена `app.js`, без модул прекарот. - - *Зошто?*: Апликација со 1 модул е именувана `app.js`. Тоа е апликацијата, па зошто да не бидеме супер едноставни. +###### [Style [Y127](#style-Y127)] + - Кога постојат повеќе модули, името на главниот модул е `app.module.js` додека другите зависни модули се именувани според тоа што претставуваат. На пример, админ модул е именувам `admin.module.js`. Соодветните регистрирани имиња на модули би биле `app` и `admin`. *Зошто?*: Обезбедува конзистентност за повеќе модуларни апликации како и проширување до огромни апликации. *Зошто?*: Обезбедува лесен начин да се автоматизираат задачите за создавање на дефинициите на модулите, па потоа сите останати angular датотеки (пакување на датотеки). ### Конфигурација - +###### [Style [Y128](#style-Y128)] - Разделете ја конфигурацијата по модул во своја датотека, именувана по модулот. На пример, конфигурациската датотека за модулот `app` е именувана `app.config.js`. Конфигурација за модул `admin.module.js` е `admin.config.js`. *Зошто?*: Ја разделува конфигурацијата од дефиницијата на модулот, компонентите и имплементацијата. @@ -1845,14 +1847,14 @@ *Зошто?*: Обезбедува лесна идентификација на конфигурацијата на модулот. ### Патеки - - - Разделете ги конфигурациите на патеките во посебна датотека. Примери како `app.route.js` за главниот модул и `admin.route.js` за `admin` модулот. Дури во помали апликации, преферирам да останат разделени од останатата конфигурација. Алтернатива би била да користиме подолги имиња како `admin.config.route.js`. +###### [Style [Y129](#style-Y129)] + - Разделете ги конфигурациите на патеките во посебна датотека. Примери како `app.route.js` за главниот модул и `admin.route.js` за `admin` модулот. Дури во помали апликации, преферирам да останат разделени од останатата конфигурација. **[Назад кон содржината](#table-of-contents)** ## Application Structure LIFT Principle ### LIFT - +###### [Style [Y140](#style-Y140)] - Поставете ја пликацијата така што `L` (брзо лоцирање на кодот), `I` (идентификација на кодот со поглед), `F` (најрамна структура што можете) и `T` (обидете се да останете DRY). Структурата треба да ги задоволува овие 4 основни водичи. *Зошто LIFT?*: Обезбедува конзистентна структура која лесно се скалира, која е модуларна, и лесно може да ја зголеми ефикасноста на програмерите преку брзо лоцирање на кодот. Друг начин да ја проверите вашата структура е да се запрашате: Колку брзо можете да ги отворите и работите во сите датотека со одредена функција? @@ -1865,7 +1867,7 @@ 4. `T` (обидете се да останеме DRY (Не Се Повторувај) или T-DRY) ### Лоцирање - +###### [Style [Y141](#style-Y141)] - Лоцирање на вашиот код треба да биде интуитивно, едноставно и брзо. *Зошто?*: Сметам дека е најважно за проект. Доколку тимот не може да брзо ги пронајде датотеките кои им се потребни да работат, тогаш не можат да работат ефикасно и структурата треба да се промени. Можете да го знаете името на датотеката или каде се наоѓаат сродните датотеки, така што доколку ги поставите на најинтуитивното место во блискост меѓу себе би се заштедило многу време. Описна структура на папки може да помогне. @@ -1889,19 +1891,19 @@ ``` ### Идентификација - +###### [Style [Y142](#style-Y142)] - Кога ќе погледнете во датотека, би требало одма да знаете што содржи и претставува. *Зошто?*: Ќе поминете помалку време на пребарување на кодот и со тоа поефикасен. Доколку тоа значи подолги имиња, нека биде така. Бидете описни со имињата на датотеките и нека содржината биде во една компонента. Избегнувајте датотеки со повеќе контролери, сервиси или мешавина од нив. Постои исклучок на 1 компонента по датотека кога постојат мали функционалности поврзани една со друга кои сеуште можат лесно да се идентифицираат. ### Рамна структура - +###### [Style [Y143](#style-Y143)] - Одржувајте рамна структура на папки колку што можете повеќе. Кога ќе се појават 7+ датотеки, започнете со поделба. *Зошто?*: Никој не би сакал да пребарува низ 7 нивоа од папки за да пронајде датотека. Размислете за мениа на веб страни... било што подлабоко од 2, треба да се размисли подобро во разделба. Во структурата не постои правило за број на папки, но кога папка има 7-10 датотеки, време е да се создадат подпапки. Нека биде поставена како што ви е удобно. Користете порамна структура се додека не е очигледно (со помош на LIFT) да создадете нова папка. ### T-DRY (Обидете се да останете DRY) - +###### [Style [Y144](#style-Y144)] - Бидете, но се во нормални граници без загуба на читливост. *Зошто?*: Да останете DRY е важно, но не е значајно доколку жртвувате на другите водичи во LIFT и зошто го нарекувам T-DRY. Не би сакал да пишувам session-view.html за преглед бидејќи очигледно е дека е преглед. Доколку не е очигледно под конвенција, тогаш ќе го именувам. @@ -1911,19 +1913,19 @@ ## Application Structure ### Целокупните водиши - +###### [Style [Y150](#style-Y150)] - Имајте блиска и широка визија на вашата имплементација. Со други зборови, започнете со мали компоненти и запазете каде се насочува апликацијата во иднината. Целокупниот код на апликацијата е во корен-папката наречена `app`. Целата содржина е 1 датотека по функција. Секој контролер, сервис, модул, преглед е во своја датотека. Сите 3rd party скрипти поставете ги во друга папка, не во `app` папката. Јас ги немам напишано нив и не би сакал да имам неред во мојата апликација (`bower_components`, `scripts`, `lib`). Забелешка: Најдете повеќе детали и расудувања за структурата во [овој оригинален пост за структура на апликација](http://www.johnpapa.net/angular-app-structuring-guidelines/). ### Изглед - +###### [Style [Y151](#style-Y151)] - Поставете компоненти која го отсликуваат целокупниот изглед на апликацијата во папката `layout`. Овде може да имаме поделеност на посебни секции од прегледот и контролер кој ќе биде контејнер за неговата апликација, навигација, мениа, области со содржина и други региони. *Зошто?*: Го организира целиот изглед во единствено место кое може да се употребува низ целата апликација. ### Папки-По-Функција структура - +###### [Style [Y152](#style-Y152)] - Создадете папки според нивната функција. Кога папката ќе порасне 7+ датотеки, почнете да размислувате за нови папки. Вашиот праг може да биде различен, така да поставете како што е препорачано. *Зошто?*: Програмерот може да го лоцира кодот, идентификува секоја датотека што претставува, структурата останува рамна и не постојат повторувачки или непотребни имиња. @@ -2020,25 +2022,27 @@ ## Modularity ### Многу мали, само содржани модулу - +###### [Style [Y160](#style-Y160)] - Создадете мали модули кои содржат една одговорност. *Зошто?*: Модуларни апликации се полесни за внесување на зависности во нив и овозможува за тимовите да ја прошират апликацијата вертикално во инкременти. Ова значи дека може да внесуваме нови функционалности како што ги развиваме. ### Создадете модул за апликацијата - +###### [Style [Y161](#style-Y161)] - Создадете корен модул за апликацијата која улога е да ги содржи сите модули и функционалности на вашата апликација. Именувајте го според вашето име на апликација. *Зошто?*: AngularJS охрабруба модуларност и поделба на грижи. Со создавање на корен модул на вашата апликација чија улога е да се поврзе со другите модули овозможува јасен начин за вклучување и исклучување модули од вашата апликација. ### Нека апликацискиот модул остане лесен - +###### [Style [Y162](#style-Y162)] - Внесете логика за поврзување на апликацијата во корен модулот. Нека функционалноста биде во останатите модули. - *Зошто?*: Со додавање на додатни улоги на корен модулот на апликацијата за земање на податоиц, прикажување изгледи и други логики кои не се поврзани со поврзување на модулите во апликацијата, се отежнува процесот на повторно искористување на функционалности како и нивно вклучување/исклучување. + *Зошто?*: Со додавање на додатни улоги на корен модулот на апликацијата за земање на податоци, прикажување изгледи и други логики кои не се поврзани со поврзување на модулите во апликацијата, се отежнува процесот на повторно искористување на функционалности како и нивно вклучување/исклучување. -### Областите за функционалност се Модулите + *Зошто?*: Модулот на апликацијата постанува манифест кој опишува кои модули ќе ја дефинираат апликацијата. +### Областите за функционалност се Модулите +###### [Style [Y163](#style-Y163)] - Создадете модули кои ги претставуваат областите на функционалности, како изгледот, повторно искористливи и заеднички сервиси, контролни табли и функционалности специфични за апликацијата (на пример, корисници, админ, продажба). *Зошто?*: Само содржани модули можат да се вклучат/исклучат без многу проблеми. @@ -2048,13 +2052,13 @@ *Зошто?*: Со разделба на областите на функционалности во модули овозможува полесно тестирање на модулите во изолација и повторно искористување на кодот. ### Повторно употребливи блокови се Модули - +###### [Style [Y164](#style-Y164)] - Создадете модули кои претставуваат повторно реискористливи блокови од апликацијата за заеднички сервиси како справување со исклучоци, логирање, дијагностика, безбедност и локално зачувување на податоци. *Зошто?*: Овие типови на функционалности се потребни во многу апликации, така што со одделување во нивните модули овозможува да бидат генерични и повторно употребливи во други апликации. ### Зависности на модули - +###### [Style [Y165](#style-Y165)] - Корен модулот на апликацијата зависи од функционалностите и нејзините модули, функционалните модули немаат директни зависности додека модулите потребни низ многу апликации зависат од генеричките модули. ![Модуларност и Зависности](https://raw.githubusercontent.com/johnpapa/angularjs-styleguide/master/assets/modularity-1.png) @@ -2074,6 +2078,7 @@ ## Startup Logic ### Конфигурација +###### [Style [Y170](#style-Y170)] - Внесете го кодот во [конфигурацијата на модулот](https://docs.angularjs.org/guide/module#module-loading-dependencies) што мора да биде извршен пред почетокот на апликацијата. Идеални кандидати се провајдери и константи. *Зошто?*: Имаме помалку места за конфигурација на апликацијата. @@ -2104,7 +2109,7 @@ ``` ### Извршувачки блокови - +###### [Style [Y171](#style-Y171)] - Било каков код што треба да се изврши кога ќе започне апликацијата треба да биде поставен во фабрика, изложен преку функција или вгнезден во [извршувачки блок](https://docs.angularjs.org/guide/module#module-loading-dependencies). *Зошто?*: Код во извршувачки блок е тежок за тестирање. Поставување на истиот во фабрика е полесен за абстракција и лажење во тестирање. @@ -2127,13 +2132,13 @@ ## Angular $ Wrapper Services ### $document и $window - +###### [Style [Y180](#style-Y180)] - Употребете [`$document`](https://docs.angularjs.org/api/ng/service/$document) и [`$window`](https://docs.angularjs.org/api/ng/service/$window) наместо `document` и `window`. *Зошто?*: Овие сервиси се завиткани од Angular и полесни за тестирање него со употреба на document и window во тестовите. Ова помага да се излажат document и window во самите тестови. ### $timeout и $interval - +###### [Style [Y181](#style-Y181)] - Употребете [`$timeout`](https://docs.angularjs.org/api/ng/service/$timeout) и [`$interval`](https://docs.angularjs.org/api/ng/service/$interval) наместо `setTimeout` и `setInterval` . *Зошто?*: Овие сервиси се завиткани од Angular и полесни се за тестирање. Исто така се ракува со AngularJS digest циклусот што овозможува полесно ажурирање на поврзаните податоци. @@ -2144,7 +2149,7 @@ Тестирање на единки се справува со чистење на кодот и затоа внесов неколку препораки во основи на тестирање во линковите подоле кои содржат повеќе информации за нив. ### Напишете тестови со Сценарија - +###### [Style [Y190](#style-Y190)] - Напишете неколку тестови за секое сценарио. Започнете со празен тест и внесете код како што пишувате код за сценариото. *Зошто?*: Со пишување на описи за тестовите се дефинира што ќе биде сценариото, што ќе прави и не прави, а и како ќе одреди дали е успешно. @@ -2170,7 +2175,7 @@ ``` ### Библиотеки за тестирање - +###### [Style [Y191](#style-Y191)] - Употребете [Jasmine](http://jasmine.github.io/) или [Mocha](http://visionmedia.github.io/mocha/) за тестирање на единки. *Зошто?*: И Jasmine и Mocha се широко употребувани во AngularJS заедницата. И двете се стабилни, добро одржувани и овозможуваат робустни функции за тестирање. @@ -2178,7 +2183,7 @@ Забелешка: Кога користите Mocha, исто така не заборавајте да употребите assert библиотека како што е [Chai](http://chaijs.com). ### Извршувач на тестови - +###### [Style [Y192](#style-Y192)] - Употребете [Karma](http://karma-runner.github.io) како извршувач на тестови. *Зошто?*: Karma е лесна за подесување за еднаш или автоматски кога ќе го промениш кодот. @@ -2190,7 +2195,7 @@ *Зошто?*: Karma работи добро со автоматизација на задачите кои водечки алатки се [Grunt](http://www.gruntjs.com) (with [grunt-karma](https://github.com/karma-runner/grunt-karma)) или [Gulp](http://www.gulpjs.com) (со [gulp-karma](https://github.com/lazd/gulp-karma)). ### Stubbing и Spying - +###### [Style [Y193](#style-Y193)] - Употребете [Sinon](http://sinonjs.org/) за stubbing и spying. *Зошто?*: Sinon работи добро со Jasmine и Mocha и ги проширува нивните stubbing и spying функционалности. @@ -2198,7 +2203,7 @@ *Зошто?*: Sinon овозможува полесно менување меѓу Jasmine и Mocha, доколку сакате да ги пробате двете. ### Без Пребарувач - +###### [Style [Y194](#style-Y194)] - Употребете [PhantomJS](http://phantomjs.org/) за да ги извршувате тестовите на вашиот сервер. *Зошто?*: PhantomJS е пребарувач кој ги започнува тестовите без потреба од кориснички интерфејс. Така што нема потреба да инсталирате Chrome, Safari, IE, или други пребарувачи на вашиот сервер. @@ -2206,13 +2211,13 @@ Забелешка: Сепак потребно е да ги извршите тестовите на сите пребарувачи во вашата околина како и вашата целна група. ### Анализа на код - +###### [Style [Y195](#style-Y195)] - Извршете JSHint на вашиот код. *Зошто?*: Тестовите се код. JSHint лесно ги прикажува грешките во квалитетот на кодот што може да предизвика неправилно извршување на тестовите. ### Изменете ги променливите на JSHint за правила на тестови - +###### [Style [Y196](#style-Y196)] - Олабавете ги правилата за вашиот тест код со цел да ви дозволи да користите глобални променливи како `describe` и `expect`. *Зошто?*: Вашите тестови се код и им е потребно истото внимание како вашиот продукциски код. Сепак, глобални променливи, како тие подоле, кои се користат од фрејмворкот за тестирање можат да бидат исклучени да не се проверуваат во вашите тестови. @@ -2228,7 +2233,7 @@ ## Animations ### Употреба - +###### [Style [Y210](#style-Y210)] - Употребете суптилни [анимации со AngularJS](https://docs.angularjs.org/guide/animations) да преминете низ состојбите на прегледите и главните визуелни елементи. Вклучете го [ngAnimate модулот](https://docs.angularjs.org/api/ngAnimate). Трите главни точки се суптилност, глаткост и беспрекорност. *Зошто?*: Суптилни анимации го подобруваат искуството на корисникот кога се употребуваат правилно. @@ -2236,13 +2241,13 @@ *Зошто?*: Суптилни анимации ги подобруваат перформансите како што имаме премин низ прегледи. ### Втора подточка - +###### [Style [Y211](#style-Y211)] - Употребете кратки анимации. Јас најчесто започнувам со 300ms и го изменувам се додека не е соодветно. *Зошто?*: Долги анимации може да имаат обратен ефект на искуството на корисникот со тоа што прикажуваме дека нашата апликација е со бавни перформанси. ### animate.css - +###### [Style [Y212](#style-Y212)] - Употребете [animate.css](http://daneden.github.io/animate.css/) за конвенционални анимации. *Зошто?*: Анимациите на animate.css се први, глатки и лесни да се додадат во вашата апликација. @@ -2258,7 +2263,7 @@ ## Comments ### jsDoc - +###### [Style [Y220](#style-Y220)] - Доколку планирате да направите документација, употребете го [`jsDoc`](http://usejsdoc.org/) со чија синтакса ќе документирате функциски имиња, нивен опис, нивни параметри и што враќа. Употребете `@namespace` и `@memberOf` за да се израмни со вашата апликациска структура. *Зошто?*: Можете да генерирате (и регенерирате) документација од вашиот код, наместо да ја пишувате од почеток. @@ -2309,7 +2314,7 @@ ## JS Hint ### Употребете датотека на можните опции - +###### [Style [Y230](#style-Y230)] - Употребете JS Hint за проверување на вашиот JavaScript код и не заборавајте да ја измените JS Hint датотеката на можни опции која мора да биде вклучена во вашиот управувач на изворниот код. Погледнете ја [JS Hint документација](http://www.jshint.com/docs/) за детали на можните опции. *Зошто?*: Обезбедува прво предупредување пред да го пратите кодот до управувачот на изворниот код. @@ -2385,7 +2390,7 @@ ## Constants ### Глобални од продавачот - +###### [Style [Y240](#style-Y240)] - Создадете AngularJS константа за глобалните променливи од библиотеки кои не се ваши. *Зошто?*: Обезбедува начин да ги внесете библиотеките кои се глобални. Ова го подобрува тестирањето на кодот што овозможува лесно да забележите кои зависности се во вашите компоненти (се справува со протекување на абстракции). Исто така овозможува да ги излажирате овие зависности, каде има смисла да направите. @@ -2410,7 +2415,7 @@ Употребете датотечни шаблони и кратки кодови за да следите конзистентен стил и шаблон во вашиот код. Евен неколку шаблони и/или кратки кодови од IDE и едитори за веб развој. ### Sublime Text - +###### [Style [Y250](#style-Y250)] - AngularJS кратки кодови кои ги следат овие водичи и стилови на код. - Симнете ги [Sublime Angular кратки кодови](assets/sublime-angular-snippets.zip) @@ -2426,7 +2431,7 @@ ``` ### Visual Studio - +###### [Style [Y251](#style-Y251)] - AngularJS датотечни шаблони што ги следат овие стилови и водичи на код можат да бидат најдени на [SideWaffle](http://www.sidewaffle.com) - Симнете ја [SideWaffle](http://www.sidewaffle.com) Visual Studio екстензија (vsix file) @@ -2434,7 +2439,7 @@ - Рестартирајте го Visual Studio ### WebStorm - +###### [Style [Y252](#style-Y252)] - AngularJS кратки кодови и датотечни шаблони кои ги следат овие стилови и водичи на код. Можете да ги внесете во вашите WebStorm подесувања: - Симнете ги [WebStorm AngularJS датотечни шаблони и кратки кодови](assets/webstorm-angular-file-template.settings.jar) @@ -2458,12 +2463,12 @@ Отворете Issue прво за да дискутираме за можни промени/додатоци. Доколку имате прашања со водичот, слободно отворете Issue во складиштето. Доколку најдете пропуст, создадете Pull Request. Идеата е да ја одржуваме содржината ажурирана и со функционалноста на github да си помогнеме во проширување на приказната со Issue и PR, кои може да се пронајдат од Google. Зошто? Бидејќи шансите се доколку имате прашање, може и некој друг да го има истото! Можете да научите повеќе за начинот на кој придонесуваме. -*Со придонесување до ова складиште, се придржувате вашата содржина да биде да подлежи на лиценцата на ова складиште.* +*Со придонесување до ова складиште, се придржувате вашата содржина да подлежи на лиценцата на ова складиште.* ### Процес 1. Дискусирајте за промените во Issue. - 1. Отворете Pull Request, поставете референца до Issue и објаснете ја промената и како додава на вредност. - 1. Pull Request ќе биде оценето и биде или споено или одбиено. + 2. Отворете Pull Request, поставете референца до Issue и објаснете ја промената и како додава на вредност. + 3. Pull Request ќе биде оценето и биде или споено или одбиено. ## License From 4dc5f541c1fe56fd31b01b794917dc0325bfa0cb Mon Sep 17 00:00:00 2001 From: Vinicius Sabadim Fernandes Date: Mon, 24 Nov 2014 18:27:30 -0200 Subject: [PATCH 043/567] Fix a typo --- i18n/PT-BR.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/i18n/PT-BR.md b/i18n/PT-BR.md index 05b3ee47..81a47c36 100644 --- a/i18n/PT-BR.md +++ b/i18n/PT-BR.md @@ -253,7 +253,7 @@ ou *Definindo* vs *Obtendo* - Use `angular.module('app');` para pegar (*get*) este módulo. ### Named vs Anonymous Functions -ou *unções Nomeadas vs Funções Anônimas* +ou *Funções Nomeadas vs Funções Anônimas* - Use funções nomeadas ao invés de passar uma função anônima como um callback. From cabe1c8923207e501ea5b3d97571bb4079cb60cd Mon Sep 17 00:00:00 2001 From: Aleksandar Bogatinov Date: Mon, 24 Nov 2014 22:43:30 +0100 Subject: [PATCH 044/567] Added translation to weird english translation --- i18n/mk-MK.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/i18n/mk-MK.md b/i18n/mk-MK.md index 711659e8..22389437 100644 --- a/i18n/mk-MK.md +++ b/i18n/mk-MK.md @@ -1074,7 +1074,7 @@ *Зошто?*: Иако овозможуваме директивите да се користат како класи, доколку навистина директивата се употребува како елемент тогаш има повеќе смисла да се користи како елемент или во најмал случај, како атрибут. - Note: EA е стандардно за AngularJS 1.3 + + Забелешка: EA е стандардно за AngularJS 1.3 + ```html From b2e09dfad9555d53b6f4e0e867bfd6e2759ccb53 Mon Sep 17 00:00:00 2001 From: Lucivaldo Costa Date: Wed, 26 Nov 2014 00:11:05 -0200 Subject: [PATCH 045/567] Translate for 'Manual Annotating for Dependency Injection' Translate for 'Manual Annotating for Dependency Injection' and minor typo fixes. --- i18n/PT-BR.md | 53 +++++++++++++++++++++++++++------------------------ 1 file changed, 28 insertions(+), 25 deletions(-) diff --git a/i18n/PT-BR.md b/i18n/PT-BR.md index 81a47c36..b5b10bc7 100644 --- a/i18n/PT-BR.md +++ b/i18n/PT-BR.md @@ -5,11 +5,10 @@ *Traduzido por [Eric Douglas](https://github.com/ericdouglas), [Ciro Nunes](https://github.com/cironunes), [Jean Lucas de Carvalho](https://github.com/jlcarvalho) e [Vinicius Sabadim Fernandes](https://github.com/vinicius-sabadim)* >The [original English version](http://jpapa.me/ngstyles) is the source of truth, as it is maintained and updated first. ->A [versão original em inglês](http://jpapa.me/ngstyles) é a fonte da verdade, já que é corrigida e atualizada primeiro. Se você procura por um guia de estilo opinativo para sintaxe, convenções e estruturação de aplicações AngularJS, então siga em frente! Estes estilos são baseados em minha experiência com desenvolvimento com [AngularJS](//angularjs.org), apresentações, [cursos de treinamento na Pluralsight](http://pluralsight.com/training/Authors/Details/john-papa) e trabalhando em equipes. -> Se você gostar deste estilo, confira meu curso [AngularJS Patterns: Clean Code](http://jpapa.me/ngclean) na Plurasight. +> Se você gostar deste estilo, confira meu curso [AngularJS Patterns: Clean Code](http://jpapa.me/ngclean) na Pluralsight. A proposta deste guia de estilo é fornecer uma direção na construção de aplicações AngularJS mostrando convenções que eu uso, e o mais importante, porque eu as escolhi. @@ -1321,20 +1320,22 @@ ou *Resolução de promessas na rota* } ``` - Nota: As dependências no código de exemplos do `movieService` não estão seguras da minificação. Para mais detalhes de como fazer o código minificado seguro, veja as seções [injeção de dependência (dependency injection)](#manual-annotating-for-dependency-injection) e [minificação e anotação (minification and annotation)](#minification-and-annotation). + Nota: As dependências no código de exemplos do `movieService` não estão seguras para minificação. Para mais detalhes de como fazer o código seguro para minificação, veja as seções [injeção de dependência (dependency injection)](#manual-annotating-for-dependency-injection) e [minificação e anotação (minification and annotation)](#minification-and-annotation). **[⬆ De volta ao topo ⬆](#tabela-de-conte%C3%BAdo)** ## Manual Annotating for Dependency Injection +ou *Anotação Manual para Injeção de Dependência* -### UnSafe from Minification +### UnSafe for Minification +ou *Não seguro para Minificação* - - Avoid using the shortcut syntax of declaring dependencies without using a minification-safe approach. + - Evite usar o atalho de sintaxe de declarar dependências sem usar uma abordagem segura para minificação. - *Why?*: The parameters to the component (e.g. controller, factory, etc) will be converted to mangled variables. For example, `common` and `dataservice` may become `a` or `b` and not be found by AngularJS. + *Por que?*: Os parâmetros do componente (por ex. controller, factory, etc) serão convertidos em variáveis encurtadas. Por exemplo, `common` e `dataservice` podem virar `a` ou `b` e não serem encontrados pelo AngularJS. ```javascript - /* avoid - not minification-safe*/ + /* evite - não seguro para minificação*/ angular .module('app') .controller('Dashboard', Dashboard); @@ -1343,25 +1344,26 @@ ou *Resolução de promessas na rota* } ``` - This code may produce mangled variables when minified and thus cause runtime errors. + Este código pode produzir variáveis encurtadas quando minificado e, assim, causar erro em tempo de execução. ```javascript - /* avoid - not minification-safe*/ + /* evite - não seguro para minificação*/ angular.module('app').controller('Dashboard', d);function d(a, b) { } ``` ### Manually Identify Dependencies +ou *Identifique Dependências Manualmente* - - Use `$inject` to manually identify your dependencies for AngularJS components. + - Use `$inject` para identificar manualmente suas dependências de componentes do AngularJS. - *Why?*: This technique mirrors the technique used by [`ng-annotate`](https://github.com/olov/ng-annotate), which I recommend for automating the creation of minification safe dependencies. If `ng-annotate` detects injection has already been made, it will not duplicate it. + *Por que?*: Esta técnica espelha a técnica usada por [`ng-annotate`](https://github.com/olov/ng-annotate), a qual eu recomendo para automatizar a criação de dependências seguras para minificação. Se `ng-annotate` detectar que a injeção já foi feita, ela não será duplicada. - *Why?*: This safeguards your dependencies from being vulnerable to minification issues when parameters may be mangled. For example, `common` and `dataservice` may become `a` or `b` and not be found by AngularJS. - - *Why?*: Avoid creating in-line dependencies as long lists can be difficult to read in the array. Also it can be confusing that the array is a series of strings while the last item is the component's function. + *Por que?*: Isto salvaguarda suas dependências de serem vulneráveis a problemas de minificação quando parâmetros podem ser encurtados. Por exemplo, `common` e `dataservice` podem se tornar `a` ou `b` e não serem encontrados pelo AngularJS. + + *Por que?*: Evite criar dependências in-line pois listas longas podem ser difíceis de ler no array. Além disso, pode ser confuso o array ser uma série de strings enquanto o último item é a função do componente. ```javascript - /* avoid */ + /* evite */ angular .module('app') .controller('Dashboard', @@ -1371,7 +1373,7 @@ ou *Resolução de promessas na rota* ``` ```javascript - /* avoid */ + /* evite */ angular .module('app') .controller('Dashboard', @@ -1382,7 +1384,7 @@ ou *Resolução de promessas na rota* ``` ```javascript - /* recommended */ + /* recomendado */ angular .module('app') .controller('Dashboard', Dashboard); @@ -1393,12 +1395,12 @@ ou *Resolução de promessas na rota* } ``` - Note: When your function is below a return statement the $inject may be unreachable (this may happen in a directive). You can solve this by either moving the $inject above the return statement or by using the alternate array injection syntax. + Nota: Quando sua função estiver abaixo de um return o $inject pode ficar inacessível (isso pode acontecer em uma diretiva). Você pode resolver isso movendo o $inject para acima do return ou usando a sintaxe alternativa de injeção de array. - Note: [`ng-annotate 0.10.0`](https://github.com/olov/ng-annotate) introduced a feature where it moves the `$inject` to where it is reachable. + Nota: [`ng-annotate 0.10.0`](https://github.com/olov/ng-annotate) introduziu um comportamento em que ele move o `$inject` para onde ele possa ser acessado. ```javascript - // inside a directive definition + // dentro da definição de diretiva function outer() { return { controller: DashboardPanel, @@ -1411,7 +1413,7 @@ ou *Resolução de promessas na rota* ``` ```javascript - // inside a directive definition + // dentro da definição de diretiva function outer() { DashboardPanel.$inject = ['logger']; // reachable return { @@ -1424,15 +1426,16 @@ ou *Resolução de promessas na rota* ``` ### Manually Identify Route Resolver Dependencies +ou *Identifique Dependências do Resolvedor de Rotas Manualmente* - - Use $inject to manually identify your route resolver dependencies for AngularJS components. + - Use $inject para identificar manualmente as dependências do seu resolvedor de rotas para componentes do AngularJS. - *Why?*: This technique breaks out the anonymous function for the route resolver, making it easier to read. + *Por que?*: Esta técnica separa a função anônima do resolvedor de rota, tornando-a mais fácil de ler. - *Why?*: An `$inject` statement can easily precede the resolver to handle making any dependencies minification safe. + *Por que?*: Uma chamada a `$inject` pode facilmente preceder o resolvedor para fazer qualquer dependência segura para minificação. ```javascript - /* recommended */ + /* recomendado */ function config($routeProvider) { $routeProvider .when('/avengers', { From fe560c5e1028eba3217e971159f09a47b8c65d6a Mon Sep 17 00:00:00 2001 From: natee Date: Wed, 26 Nov 2014 16:14:32 +0800 Subject: [PATCH 046/567] sync latest --- i18n/zh-CN.md | 129 +++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 107 insertions(+), 22 deletions(-) diff --git a/i18n/zh-CN.md b/i18n/zh-CN.md index 51896247..c86bee7d 100644 --- a/i18n/zh-CN.md +++ b/i18n/zh-CN.md @@ -54,6 +54,7 @@ ## 单一职责 ###规则一 +###### [Stile [Y001](#stile-y001)] - 一个文件只定义一个组件。 @@ -106,7 +107,8 @@ **[返回顶部](#目录)** ## IIFE -###IIFE +### JavaScript闭包 +###### [Stile [Y010](#stile-y010)] - 把AngularJS组件包装到一个立即调用函数表达式中(IIFE)。 @@ -172,12 +174,14 @@ ## Modules ###避免命名冲突 +###### [Style [Y020](#style-y020)] - 给独立子模块使用唯一的命名约定。 *为什么*:避免冲突,每个模块也可以方便定义子模块。 ###定义(aka Setters) +###### [Style [Y021](#style-y021)] - 不使用任何一个使用了setter语法的变量来定义modules。 @@ -207,6 +211,7 @@ ``` ###Getters +###### [Style [Y022](#style-y022)] - 当使用一个module的时候,避免使用一个变量,而是使用getter语法链接。 @@ -230,6 +235,7 @@ ``` ###Setting vs Getting +###### [Style [Y023](#style-y023)] - 设置一次,获取其它所有的实例。 @@ -239,6 +245,7 @@ - 用 `angular.module('app');` 获取一个module。 ###命名函数 vs 匿名函数 +###### [Style [Y024](#style-y024)] - 用一个命名函数而不是通过一个匿名函数作为回调函数。 @@ -277,6 +284,7 @@ ## Controllers ###controllerAs在View中的语法 +###### [Style [Y030](#style-y030)] - 使用[`controllerAs`](http://www.johnpapa.net/do-you-like-your-angular-controllers-with-or-without-sugar/) 语法代替直接用经典的$scope定义的controller的方式。 @@ -301,6 +309,7 @@ ``` ###controllerAs在controller中的语法 +###### [Style [Y031](#style-y031)] - 使用 `controllerAs` 语法代替 `经典的$scope语法` 语法。 @@ -349,7 +358,7 @@ } ``` - - 注:你可以按照下面的做法来避免 [jshint](http://www.jshint.com/)的警告。 + - 注:你可以按照下面的做法来避免 [jshint](http://www.jshint.com/)的警告。但是构造函数(函数名首字母大写)是不需要这个的. ```javascript /* jshint validthis: true */ @@ -366,6 +375,7 @@ ###可绑定成员放到顶部 +###### [Style [Y033](#style-y033)] - 把可绑定的成员放到controller的顶部,按字母排序,并且不要通过controller的代码传播。 @@ -454,6 +464,7 @@ ``` ###函数声明隐藏实现细节 +###### [Style [Y034](#style-y034)] - 函数声明隐藏实现细节,把绑定成员放到顶部,当你需要在controller中绑定一个函数时,把它指向一个函数声明,这个函数声明在文件的后面会出现。 @@ -529,6 +540,7 @@ ``` ###推迟Controller中的逻辑 +###### [Style [Y035](#style-y036)] - 通过委派到service和factory中来推迟controller中的逻辑。 @@ -569,12 +581,14 @@ ``` ###保持Controller的专一性 +###### [Style [Y037](#style-y037)] - 一个view定义一个controller,尽量不要在其它view中使用这个controller。把可重用的逻辑放到factory中,保证controller的单一,只专注于当前视图。 *为什么?*:不同的view用同一个controller是非常不科学的,良好的端对端测试覆盖率对于保证大型应用稳定性是必需的。 ###分配Controller +###### [Style [Y038](#style-y038)] - 当一个controller必须匹配一个view时或者任何一个组件可能被其它controller或是view重用时,连同controller的route一起定义。 @@ -633,6 +647,7 @@ ## Services ###单例 +###### [Style [Y040](#style-y040)] - 用`new`实例化service,用`this`实例化公共方法和变量,由于这和facotry是类似的,所以推荐用facotry来代替。 @@ -672,6 +687,7 @@ ## Factories ###单一职责 +###### [Style [Y051](#style-y051)] - factory应该是[单一职责](http://en.wikipedia.org/wiki/Single_responsibility_principle),这是由其上下文进行封装的。一旦一个factory将要处理超过单一的目的时,就应该创建一个新的factory。 @@ -682,6 +698,7 @@ 注:[所有的AngularJS services都是单例](https://docs.angularjs.org/guide/services),这意味着每个injector都只有一个实例化的service。 ###可访问的成员放到顶部### +###### [Style [Y052](#style-y052)] - 使用从[显露模块模式](http://addyosmani.com/resources/essentialjsdesignpatterns/book/#revealingmodulepatternjavascript)派生出来的技术把service中可调用的成员暴露到顶部, @@ -737,6 +754,7 @@ ![Factories Using "Above the Fold"](https://raw.githubusercontent.com/johnpapa/angularjs-styleguide/master/assets/above-the-fold-2.png) ###函数声明隐藏实现细节 +###### [Style [Y053](#style-y053)] - 函数声明隐藏实现细节,把绑定成员放到顶部,当你需要在controller中绑定一个函数时,把它指向一个函数声明,这个函数声明在文件的后面会出现。 @@ -838,6 +856,7 @@ ## Data Services ###独立的数据调用 +###### [Style [Y060](#style-y060)] - 把进行数据操作和数据交互的逻辑放到factory中,数据服务负责XHR请求、本地存储、内存存储和其它任何数据操作。 @@ -912,6 +931,7 @@ ``` ###从Data调用那里返回一个Promise +###### [Style [Y061](#style-y061)] - 就像$http一样,当调用data service时返回一个promise,在你的调用函数中也返回一个promise。 @@ -961,6 +981,7 @@ ## Directives ###一个文件限制一个 +###### [Style [Y070](#style-y070)] - 一个文件中只创建一个directive,并依照directive来命名文件。 @@ -1048,13 +1069,15 @@ 注:directive有很多命名选项,特别是从它们能够在一个狭隘的或者广泛的作用域中使用时,选择一个让directive和文件都清楚分明的名字。下面有一些例子,不过更多的建议去看命名章节。 -###限制DOM操作 +###在directive中操作DOM +###### [Style [Y072](#style-y072)] - 当需要直接操作DOM的时候,使用directive。如果有替代方法可以使用,例如:使用CSS来设置样式、[animation services](https://docs.angularjs.org/api/ngAnimate)、Angular模板、[`ngShow`](https://docs.angularjs.org/api/ng/directive/ngShow) or [`ngHide`](https://docs.angularjs.org/api/ng/directive/ngHide),那么就直接用这些即可。例如,如果一个directive只是想控制显示和隐藏,用ngHide/ngShow即可。 *为什么?*:DOM操作的测试和调试是很困难的,通常会有更好的方法(CSS、animations、templates)。 ###提供一个唯一的Directive前缀 +###### [Style [Y073](#style-y073)] - 提供一个短小、唯一、具有描述性的directive前缀,例如`acmeSalesCustomerInfo`在HTML中声明为`acme-sales-customer-info`。 @@ -1063,6 +1086,7 @@ 注:避免使用`ng-`为前缀,研究一下其它广泛使用的directive避免命名冲突,例如[Ionic Framework](http://ionicframework.com/)的`ion-`。 ###限制元素和属性 +###### [Style [Y074](#style-y074)] - 当创建一个directive需要作为一个独立元素是有意义时,允许限制`E`(自定义元素),可选限制`A`(自定义属性)。一般来说,如果它可能是它自己的控制,用`E`是合适的做法。一般原则是允许`EA`,但是当它是独立的时候这更倾向于作为一个元素来实施,当它是为了增强已存在的DOM元素时则更倾向于作为一个属性来实施。 @@ -1124,6 +1148,7 @@ ``` ###Directives和ControllerAs +###### [Style [Y075](#style-y075)] - directive使用`controller as`语法,和view使用`controller as`保持一致。 @@ -1133,6 +1158,9 @@ 注意:关于依赖注入的内容,请看[手动依赖注入](#手动依赖注入)。 + 注意:directive的控制器是在directive外部的,这种风格避免了由于注入造成的`return`之后的代码无法访问的情况。 + + ```html
``` @@ -1154,27 +1182,29 @@ controllerAs: 'vm' }; - ExampleController.$inject = ['$scope']; return directive; - - function ExampleController($scope) { - // Injecting $scope just for comparison - /* jshint validthis:true */ - var vm = this; - - vm.min = 3; - vm.max = $scope.max; - console.log('CTRL: $scope.max = %i', $scope.max); - console.log('CTRL: vm.min = %i', vm.min); - console.log('CTRL: vm.max = %i', vm.max); - } - + function linkFunc(scope, el, attr, ctrl) { console.log('LINK: scope.max = %i', scope.max); console.log('LINK: scope.vm.min = %i', scope.vm.min); console.log('LINK: scope.vm.max = %i', scope.vm.max); } } + + ExampleController.$inject = ['$scope']; + + function ExampleController($scope) { + // Injecting $scope just for comparison + var vm = this; + + vm.min = 3; + vm.max = $scope.max; + console.log('CTRL: $scope.max = %i', $scope.max); + console.log('CTRL: vm.min = %i', vm.min); + console.log('CTRL: vm.max = %i', vm.max); + } + + ``` ```html @@ -1189,6 +1219,7 @@ ## 解决Controller的Promises ###Controller Activation Promises +###### [Style [Y080](#style-y080)] - 在`activate`函数中解决controller的启动逻辑。 @@ -1231,6 +1262,7 @@ ``` ###Route Resolve Promises +###### [Style [Y081](#style-y081)] - 当一个controller依赖于一个promise来解决,那么就在controller的逻辑执行之前在`$routeProvider`中解决这些依赖。如果你需要在controller被激活之前有条件地取消一个路由,那么就用route resolver。 @@ -1294,6 +1326,7 @@ ## 手动依赖注入 ###缩写的不安全性 +###### [Style [Y090](#style-y090)] - 声明依赖时避免使用不安全缩写方法的缩写语法。 @@ -1317,6 +1350,7 @@ ``` ###手动添加依赖 +###### [Style [Y091](#style-y091)] - 用`$inject`手动添加AngularJS组件所需的依赖。 @@ -1391,6 +1425,7 @@ ``` ###手动确定路由解析器依赖 +###### [Style [Y092](#style-y092)] - 用$inject手动给AngularJS组件添加路由解析器依赖。 @@ -1424,6 +1459,7 @@ ## 压缩和注释 ###ng-annotate +###### [Style [Y100](#style-y100)] - 在[Gulp](http://gulpjs.com)或[Grunt](http://gruntjs.com)中使用[ng-annotate](//github.com/olov/ng-annotate),用`/** @ngInject */`对需要自动依赖注入的function进行注释。 @@ -1482,6 +1518,7 @@ `` ###使用Gulp或Grunt结合ng-annotate +###### [Style [Y101](#style-y101)] - 在自动化任务中使用[gulp-ng-annotate](https://www.npmjs.org/package/gulp-ng-annotate)或[grunt-ng-annotate](https://www.npmjs.org/package/grunt-ng-annotate),把`/* @ngInject */`注入到任何有依赖关系函数的前面。 @@ -1515,6 +1552,7 @@ ## 异常处理 ###修饰符 +###### [Style [Y110](#style-y110)] - 使用一个[decorator](https://docs.angularjs.org/api/auto/service/$provide#decorator),在配置的时候用[`$provide`](https://docs.angularjs.org/api/auto/service/$provide)服务,当发生异常时,在[`$exceptionHandler`](https://docs.angularjs.org/api/ng/service/$exceptionHandler)服务中执行自定义的处理方法。 @@ -1555,6 +1593,7 @@ ``` ###异常捕获器 +###### [Style [Y111](#style-y111)] - 创建一个暴露了一个接口的factory来捕获异常并以合适方式处理异常。 @@ -1585,6 +1624,7 @@ ``` ###路由错误 +###### [Style [Y112](#style-y112)] - 用[`$routeChangeError`](https://docs.angularjs.org/api/ngRoute/service/$route#$routeChangeError)来处理并打印出所有的路由错误信息。 @@ -1620,6 +1660,7 @@ ## 命名 ###命名原则 +###### [Style [Y120](#style-y120)] - 遵循以描述组件功能,然后是类型(可选)的方式来给所有的组件提供统一的命名,我推荐的做法是`feature.type.js`。大多数文件都有2个名字。 * 文件名 (`avengers.controller.js`) @@ -1630,6 +1671,7 @@ *为什么?*:命名约定应该只为代码的检索和沟通提供方便。 ###功能文件命名 +###### [Style [Y121](#style-y121)] - 遵循以描述组件功能,然后是类型(可选)的方式来给所有的组件提供统一的命名,我推荐的做法是`feature.type.js`。 @@ -1696,6 +1738,7 @@ ``` ###测试文件命名 +###### [Style [Y122](#style-y122)] - 和组件命名差不多,带上一个`spec`后缀。 @@ -1714,6 +1757,7 @@ ``` ###Controller命名 +###### [Style [Y123](#style-y123)] - 为所有controller提供统一的名称,特征然后名字,鉴于controller是构造函数,所以要采用UpperCamelCase(每个单词首字母大写)的方式。 @@ -1735,6 +1779,7 @@ ``` ###Controller命名后缀 +###### [Style [Y124](#style-y124)] - 使用`Controller`后缀或者不加后缀。 @@ -1769,6 +1814,7 @@ ``` ###Factory命名 +###### [Style [Y125](#style-y125)] - 一样要统一,对service和factory使用camel-casing(驼峰式,第一个单词首字母小写,后面单词首字母大写)方式。 @@ -1788,6 +1834,7 @@ ``` ###Directive组件命名 +###### [Style [Y126](#style-y126)] - 使用camel-case方式,用一个短的前缀来描述directive在哪个区域使用(一些例子中是使用公司前缀或是项目前缀)。 @@ -1798,7 +1845,7 @@ * recommended */ - // avenger.profile.directive.js + // avenger-profile.directive.js angular .module .directive('xxAvengerProfile', xxAvengerProfile); @@ -1809,16 +1856,16 @@ ``` ###模块 +###### [Style [Y127](#style-y127)] - - 当有很多的模块时,主模块文件命名成`app.module.js`,其它依赖模块以它们代表的东西来命名。例如,一个管理员模块命名成`admin.module.js`。它们各自的注册模块名字就是`app`和`admin`,一个单一的app模块也许被命名成省略了module尾巴的`app.js`。 + - 当有很多的模块时,主模块文件命名成`app.module.js`,其它依赖模块以它们代表的东西来命名。例如,一个管理员模块命名成`admin.module.js`,它们各自的注册模块名字就是`app`和`admin`。 - *为什么?*:一个只有一个模块的app命名成`app.js`,它就代表这个app,所以为什么不简单点呢? - *为什么?*:给多模块的应用提供统一的方式,这也是为了扩展大型应用。 *为什么?*:对使用任务来自动化加载所有模块的定义(先)和其它所有的angular文件(后)提供了一种简单的方式。 ###配置 +###### [Style [Y128](#style-y128)] - 把一个模块的配置独立到它自己的文件中,以这个模块为基础命名。`app`模块的配置文件命名成`app.config.js`(或是`config.js`),`admin.module.js`的配置文件命名成`admin.config.js`。 @@ -1827,8 +1874,9 @@ *为什么?*:为设置模块的配置提供了一个可识别的地方。 ###路由 +###### [Style [Y129](#style-y129)] - - 把路由的配置独立到单独的文件。主模块的路由可能是`app.route.js`,`admin`模块的路由可能是`admin.route.js`。即使是在很小的应用中,我也喜欢把路由的配置从其余的配置中分离出来。另一种方式是用一个很长的名字,例如`admin.config.route.js`。 + - 把路由的配置独立到单独的文件。主模块的路由可能是`app.route.js`,`admin`模块的路由可能是`admin.route.js`。即使是在很小的应用中,我也喜欢把路由的配置从其余的配置中分离出来。 **[返回顶部](#目录)** @@ -1836,6 +1884,7 @@ ## 应用程序结构的LIFT准则 ###LIFT +###### [Style [Y140](#style-y140)] - 构建一个可以快速定位(`L`ocate)代码、一目了然地识别(`I`dentify)代码、拥有一个平直(`F`lattest)的结构、尽量(`T`ry)坚持DRY(Don’t Repeat Yourself)的应用程序,其结构应该遵循这4项基本准则。 @@ -1849,6 +1898,7 @@ 4. 尽量保持不要写重复代码(T) ###Locate +###### [Style [Y141](#style-y141)] - 更直观、更简单、更快捷地定位代码 @@ -1873,18 +1923,21 @@ ``` ###Identify +###### [Style [Y142](#style-y142)] - 当你看到一个文件时你应该能够立即知道它包含了什么、代表了什么。 *为什么?*:你花费更少的时间来了解代码代表了什么,并且变得更加高效。如果这意味着你需要更长的名字,那么就这么干吧。文件名一定要具有描述性,保持和文件内容互为一体。避免文件中有多个controller,多个service,甚至是混合的。 ###Flat +###### [Style [Y143](#style-y143)] - 尽可能长时间地保持一个平直的文件夹结构,如果你的文件夹层级超过7+,那么就开始考虑分离。 *为什么?*:没有谁想在一个7级文件夹中寻找一个文件,你可以考虑一下网页导航栏有那么多层。文件夹结构没有硬性规则,但是当一个文件夹下的文件有7-10个,那么就是时候创建子文件夹了,文件夹的层级一定要把握好。一直使用一个平直的结构,直到确实有必要(帮助其它的LIFT)创建一个新的文件夹。 ###T-DRY(尽量坚持DRY) +###### [Style [Y144](#style-y144)] - 坚持DRY,但是不要疯了一样的做却牺牲了可读性。 @@ -1896,16 +1949,19 @@ ## 应用程序结构 ###总指南 +###### [Style [Y150](#style-y150)] - 有实施的短期看法和长远的目标,换句话说,从小处入手,但是要记住app的走向。app的所有代码都在一个叫做`app`的根目录下,所有的内容都遵循一个功能一个文件,每一个controller、service、module、view都是独立的文件。第三方脚本存放在另外的根文件夹中(`bower_components`、`scripts`、`lib`)。 ###Layout +###### [Style [Y151](#style-y151)] - 把定义应用程序总体布局的组件放到`layout`文件夹中,如导航、内容区等等。 *为什么?*:复用。 ###按功能划分文件夹结构 +###### [Style [Y152](#style-y152)] - 按照它们代表的功能来给创建的文件夹命名,当文件夹包含的文件超过7个(根据需要自行调整数量限制),就考虑新建文件夹。 @@ -1998,24 +2054,30 @@ ## 模块化 ###许多小的、独立的模块 +###### [Style [Y160](#style-y160)] - 创建只封装一个职责的小模块。 *为什么?*:模块化的应用程序很容易插入新的功能。 ###创建一个App Module +###### [Style [Y161](#style-y161)] - 创建一个应用程序的根模块,它的职责是把应用程序中所有的模块和功能都放到一起。 *为什么?*:AngularJS鼓励模块化和分离模式。创建根模块的作用是把其它模块都绑定到一起,这为增加或是删除一个模块提供了非常简单的方法。 + *为什么?*:应用程序模块变成了一个描述哪些模块有助于定义应用程序的清单。 + ###保持App Module的精简 +###### [Style [Y162](#style-y162)] - app module中只放聚合其它模块的逻辑,具体功能在它们自己的模块中实现。 *为什么?*:添加额外的代码(获取数据、展现视图、其它和聚合模块无关的代码)到app module中使app module变得很糟糕,也使得模块难以重用和关闭。 ###功能区域就是模块 +###### [Style [Y163](#style-y163)] - 创建代表功能区的模块,例如布局、可重用、共享服务、仪表盘和app的特殊功能(例如客户、管理、销售)。 @@ -2026,12 +2088,14 @@ *为什么?*:分离功能为模块可以更容易测试。 ###可重用的块就是模块 +###### [Style [Y164](#style-y164)] - 为通用service创建代表可重用的应用程序块的模块,例如异常处理、日志记录、诊断、安全性和本地数据储藏等模块。 *为什么?*:这些类型的功能在很多应用程序中都需要用到,所以把它们分离到自己的模块中,它们可以变成通用的应用程序,也能被跨应用地进行重用。 ###模块依赖 +###### [Style [Y165](#style-y165)] - 应用程序根模块依赖于应用程序特定的功能模块,功能模块没有直接的依赖关系,跨应用的模块取决于所有通用模块。 @@ -2053,6 +2117,8 @@ ## 启动逻辑 ### 配置 +###### [Style [Y170](#style-y170)] + - 必须在angular应用启动前进行配置才能把代码注入到[模块配置](https://docs.angularjs.org/guide/module#module-loading-dependencies),理想的一些case应该包括providers和constants。 *为什么?*:这使得在更少的地方进行配置变得容易。 @@ -2083,6 +2149,7 @@ ``` ### 运行代码块 +###### [Style [Y171](#style-y171)] - 任何在应用程序启动时需要运行的代码都应该在factory中声明,通过一个function暴露出来,然后注入到[运行代码块](https://docs.angularjs.org/guide/module#module-loading-dependencies)中。 @@ -2106,12 +2173,14 @@ ##Angular $包装服务 ###$document和$window +###### [Style [Y180](#style-y180)] - 用[`$document`](https://docs.angularjs.org/api/ng/service/$document)和[`$window`](https://docs.angularjs.org/api/ng/service/$window)代替`document`和`window`。 *为什么?*:使用内部包装服务将更容易测试,也避免了你自己去模拟document和window。 ###$timeout和$interval +###### [Style [Y181](#style-y181)] - 用[`$timeout`](https://docs.angularjs.org/api/ng/service/$timeout)和[`$interval`](https://docs.angularjs.org/api/ng/service/$interval)代替`setTimeout`和`setInterval` 。 @@ -2124,6 +2193,7 @@ 单元测试有助于保持代码的清晰,因此我加入一些关于单元测试的基础和获取更多信息的链接。 ###用故事来编写测试 +###### [Style [Y190](#style-y190)] - 给每一个故事都写一组测试,县创建一个空的测试,然后用你给这个故事写的代码来填充它。 @@ -2150,6 +2220,7 @@ ``` ###测试库 +###### [Style [Y191](#style-y191)] - 用[Jasmine](http://jasmine.github.io/)或者[Mocha](http://visionmedia.github.io/mocha/)进行单元测试。 @@ -2158,6 +2229,7 @@ 注意:使用Mocha时你可以考虑选择一个类似[Chai](http://chaijs.com)的提示库。 ###测试运行器 +###### [Style [Y192](#style-y192)] - [Karma](http://karma-runner.github.io)。 @@ -2170,6 +2242,7 @@ *为什么?*:Karma可以很好的和自动化任务工具如[Grunt](http://www.gruntjs.com)(带有[grunt-karma](https://github.com/karma-runner/grunt-karma))和[Gulp](http://www.gulpjs.com)(带有[gulp-karma](https://github.com/lazd/gulp-karma))合作。 ###Stubbing和Spying +###### [Style [Y193](#style-y193)] - 用Sinon。 @@ -2178,6 +2251,7 @@ *为什么?*:如果你想试试Jasmine和Mocha,用Sinon在它们中间来回切换是很方便的。 ###Headless Browser +###### [Style [Y194](#style-y194)] - 在服务器上使用[PhantomJS](http://phantomjs.org/)来运行你的测试。 @@ -2186,12 +2260,14 @@ 注意:你仍然需要在你的环境下测试所有浏览器,来满足用户的需求。 ###代码分析 +###### [Style [Y195](#style-y195)] -在你的测试上运行JSHint。 *为什么?*:测试也是代码,JSHint能够帮你识别代码中可能导致测试无法正常工作的的质量问题。 ###对测试降低全局JSHint规则 +###### [Style [Y196](#style-y196) - 对你的测试代码放松规则,这样可以允许使用`describe`和`expect`等类似通用的全局方法。 @@ -2209,6 +2285,7 @@ ## 动画 ###用法 +###### [Style [Y210](#style-y210)] - 在view和主要的视觉元素上使用细微的[AngularJS动画](https://docs.angularjs.org/guide/animations)进行过渡,包括[ngAnimate模块](https://docs.angularjs.org/api/ngAnimate)。三个关键点是细微、平滑、无缝。 @@ -2217,12 +2294,14 @@ *为什么?*:当视图过渡时,微小的动画可以提高感知性。 ###Sub Second +###### [Style [Y211](#style-y211)] - 使用短持续性的动画,我一般使用300ms,然后调整到合适的时间。 *为什么?*:长时间的动画容易造成用户认为程序性能太差的影响。 ###animate.css +###### [Style [Y212](#style-y212)] - 传统动画使用[animate.css](http://daneden.github.io/animate.css/)。 @@ -2240,6 +2319,7 @@ ## 注释 ###jsDoc +###### [Style [Y220](#style-y220)] - 如果你计划产出一个文档,那么就使用[`jsDoc`](http://usejsdoc.org/)的语法来记录函数名、描述、参数和返回值。使用`@namespace`和`@memberOf`来匹配应用程序结构。 @@ -2292,6 +2372,7 @@ ## JS Hint ###使用一个选项文件 +###### [Style [Y230](#style-y230)] - 用JS Hint来分析你的JavaScript代码,确保你自定义了JS Hint选项文件并且包含在源控制里。详细信息:[JS Hint文档](http://www.jshint.com/docs/)。 @@ -2368,6 +2449,7 @@ ## 常量 ###供应全局变量 +###### [Style [Y240](#style-y240)] - 为供应库中的全局变量创建一个AngularJS常量。 @@ -2396,6 +2478,7 @@ 使用文件模板和片段帮助保持一致性的风格,这里有针对一些web开发的编辑器和IDE的模板和(或)片段。 ###Sublime Text +###### [Style [Y250](#style-y250)] - AngularJS片段遵循这些风格指南。 @@ -2412,12 +2495,14 @@ ``` ###Visual Studio +###### [Style [Y251](#style-y251)] - 下载Visual Studio扩展文件[SideWaffle](http://www.sidewaffle.com) - 运行下载的vsix文件 - 重启Visual Studio ###WebStorm +###### [Style [Y252](#style-y252)] - 你可以把它们导入到WebStorm设置中: From 58e88f79855d4eefc9c081217a2e83173b093e9d Mon Sep 17 00:00:00 2001 From: Lucivaldo Costa Date: Wed, 26 Nov 2014 09:50:25 -0200 Subject: [PATCH 047/567] Translation for 'Minification and Annotation' Translation for 'Minification and Annotation'. --- i18n/PT-BR.md | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/i18n/PT-BR.md b/i18n/PT-BR.md index c13185eb..0f0a3736 100644 --- a/i18n/PT-BR.md +++ b/i18n/PT-BR.md @@ -1439,18 +1439,19 @@ ou *Retorne uma promessa de chamadas de dados* **[⬆ De volta ao topo ⬆](#tabela-de-conte%C3%BAdo)** ## Minification and Annotation +ou *Minificação e Anotação* ### ng-annotate - - Use [ng-annotate](//github.com/olov/ng-annotate) for [Gulp](http://gulpjs.com) or [Grunt](http://gruntjs.com) and comment functions that need automated dependency injection using `/** @ngInject */` + - Use [ng-annotate](//github.com/olov/ng-annotate) para [Gulp](http://gulpjs.com) ou [Grunt](http://gruntjs.com) e comente as funções que precisam de injeção de dependência automatizada usando `/** @ngInject */` - *Why?*: This safeguards your code from any dependencies that may not be using minification-safe practices. + *Por que?*: Isso protege seu código de qualquer dependência que pode não estar usando práticas seguras para minificação. - *Why?*: [`ng-min`](https://github.com/btford/ngmin) is deprecated + *Por que?*: [`ng-min`](https://github.com/btford/ngmin) está deprecated. - >I prefer Gulp as I feel it is easier to write, to read, and to debug. + > Eu prefiro Gulp pois sinto que é mais fácil de escrever, de ler, e de debugar. - The following code is not using minification safe dependencies. + O código a seguir não está usando dependências seguras para minificação. ```javascript angular @@ -1470,7 +1471,7 @@ ou *Retorne uma promessa de chamadas de dados* } ``` - When the above code is run through ng-annotate it will produce the following output with the `$inject` annotation and become minification-safe. + Quando o código acima é executado através de ng-annotate produzirá a seguinte saída com a anotação `$inject` e se tornará seguro para minificação. ```javascript angular @@ -1492,12 +1493,12 @@ ou *Retorne uma promessa de chamadas de dados* Avengers.$inject = ['storageService', 'avengerService']; ``` - Note: If `ng-annotate` detects injection has already been made (e.g. `@ngInject` was detected), it will not duplicate the `$inject` code. + Nota: Se `ng-annotate` detectar que a injeção já foi feita (por ex. `@ngInject` foi detectado), o código do `$inject` não será duplicado. - Note: When using a route resolver you can prefix the resolver's function with `/* @ngInject */` and it will produce properly annotated code, keeping any injected dependencies minification safe. + Nota: Quando usar um resolvedor de rotas você pode prefixar a função do resolvedor com `/* @ngInject */` o que produzirá código devidamente anotado, mantendo qualquer dependência injetada segura para minificação. ```javascript - // Using @ngInject annotations + // Usando anotação @ngInject function config($routeProvider) { $routeProvider .when('/avengers', { @@ -1513,7 +1514,7 @@ ou *Retorne uma promessa de chamadas de dados* } ``` - > Note: Starting from AngularJS 1.3 use the [`ngApp`](https://docs.angularjs.org/api/ng/directive/ngApp) directive's `ngStrictDi` parameter. When present the injector will be created in "strict-di" mode causing the application to fail to invoke functions which do not use explicit function annotation (these may not be minification safe). Debugging info will be logged to the console to help track down the offending code. + > Nota: Apartir do AngularJS 1.3 use o parâmetro `ngStrictDi` da diretiva [`ngApp`](https://docs.angularjs.org/api/ng/directive/ngApp). Quando presente, o injetor será criado no modo "strict-di" fazendo com que a aplicação falhe ao tentar invocar funções que não usem anotação explícita de função (elas podem não ser seguras para minificação). Informação de debug será logada no console para ajudar a rastrear o código ofensivo. `` ### Use Gulp or Grunt for ng-annotate From 3a99dc952f7afd7d577b9c647c585dd62acfc85e Mon Sep 17 00:00:00 2001 From: Aleksandar Bogatinov Date: Wed, 26 Nov 2014 14:23:31 +0100 Subject: [PATCH 048/567] Added the original English version is maintained first --- i18n/mk-MK.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/i18n/mk-MK.md b/i18n/mk-MK.md index 22389437..f64634c4 100644 --- a/i18n/mk-MK.md +++ b/i18n/mk-MK.md @@ -4,6 +4,8 @@ *Преведено од [Александар Богатинов](https://github.com/Bogatinov)* +>[Оригиналната англиска верзија](http://jpapa.me/ngstyles) е изворот, одржуван и ажуриран прво. + Доколку барате своеволен стил на кодирање за синтакса, конвенции и структурирање на AngularJS апликации, тогаш сте на правилното место. Овие стилови се базирани на моето искуство во развој на [AngularJS](//angularjs.org), презентации, [Pluralsight тренинг курсеви](http://pluralsight.com/training/Authors/Details/john-papa) и работа во тимови. From 0ff66b2f3ec79e8d8f37ac3a8886bebec729bb2a Mon Sep 17 00:00:00 2001 From: Aleksandar Bogatinov Date: Wed, 26 Nov 2014 14:25:01 +0100 Subject: [PATCH 049/567] Fixed macedonian translation --- i18n/mk-MK.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/i18n/mk-MK.md b/i18n/mk-MK.md index f64634c4..f642f3bf 100644 --- a/i18n/mk-MK.md +++ b/i18n/mk-MK.md @@ -4,7 +4,7 @@ *Преведено од [Александар Богатинов](https://github.com/Bogatinov)* ->[Оригиналната англиска верзија](http://jpapa.me/ngstyles) е изворот, одржуван и ажуриран прво. +>[Оригиналната англиска верзија](http://jpapa.me/ngstyles) е оригиналната, одржуванa и ажуриранa. Доколку барате своеволен стил на кодирање за синтакса, конвенции и структурирање на AngularJS апликации, тогаш сте на правилното место. Овие стилови се базирани на моето искуство во развој на [AngularJS](//angularjs.org), презентации, [Pluralsight тренинг курсеви](http://pluralsight.com/training/Authors/Details/john-papa) и работа во тимови. From cc59eaebaacf153db54a2ad9cda30d81dd0acf98 Mon Sep 17 00:00:00 2001 From: Aleksandar Bogatinov Date: Wed, 26 Nov 2014 14:50:13 +0100 Subject: [PATCH 050/567] Fixed macedonian translation --- i18n/mk-MK.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/i18n/mk-MK.md b/i18n/mk-MK.md index f642f3bf..72aaeb3a 100644 --- a/i18n/mk-MK.md +++ b/i18n/mk-MK.md @@ -4,7 +4,7 @@ *Преведено од [Александар Богатинов](https://github.com/Bogatinov)* ->[Оригиналната англиска верзија](http://jpapa.me/ngstyles) е оригиналната, одржуванa и ажуриранa. +>[Оригиналната англиска верзија](http://jpapa.me/ngstyles) е изворот на вистината, бидејќи е одржуванa и ажуриранa. Доколку барате своеволен стил на кодирање за синтакса, конвенции и структурирање на AngularJS апликации, тогаш сте на правилното место. Овие стилови се базирани на моето искуство во развој на [AngularJS](//angularjs.org), презентации, [Pluralsight тренинг курсеви](http://pluralsight.com/training/Authors/Details/john-papa) и работа во тимови. From 8dcd5d553b08a655c4f23fb79bfa94fb249de8ff Mon Sep 17 00:00:00 2001 From: natee Date: Fri, 28 Nov 2014 11:30:06 +0800 Subject: [PATCH 051/567] fix typo --- i18n/zh-CN.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/i18n/zh-CN.md b/i18n/zh-CN.md index c86bee7d..fd1f8b9e 100644 --- a/i18n/zh-CN.md +++ b/i18n/zh-CN.md @@ -54,7 +54,7 @@ ## 单一职责 ###规则一 -###### [Stile [Y001](#stile-y001)] +###### [style [Y001](#style-y001)] - 一个文件只定义一个组件。 @@ -108,7 +108,7 @@ ## IIFE ### JavaScript闭包 -###### [Stile [Y010](#stile-y010)] +###### [style [Y010](#style-y010)] - 把AngularJS组件包装到一个立即调用函数表达式中(IIFE)。 From b932594a15530ebfea4e79d54248ec6ff3e5aaa1 Mon Sep 17 00:00:00 2001 From: natee Date: Fri, 28 Nov 2014 11:32:27 +0800 Subject: [PATCH 052/567] fix typo --- i18n/zh-CN.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/i18n/zh-CN.md b/i18n/zh-CN.md index fd1f8b9e..65d20ee1 100644 --- a/i18n/zh-CN.md +++ b/i18n/zh-CN.md @@ -54,7 +54,7 @@ ## 单一职责 ###规则一 -###### [style [Y001](#style-y001)] +###### [Style [Y001](#style-y001)] - 一个文件只定义一个组件。 @@ -108,7 +108,7 @@ ## IIFE ### JavaScript闭包 -###### [style [Y010](#style-y010)] +###### [Style [Y010](#style-y010)] - 把AngularJS组件包装到一个立即调用函数表达式中(IIFE)。 From 5d8077f9551106c84a43b6bc68871d4530f88ba5 Mon Sep 17 00:00:00 2001 From: John Papa Date: Sun, 30 Nov 2014 11:04:16 -0500 Subject: [PATCH 053/567] updated modularity to reflect reusable modules across applications --- README.md | 6 ++++-- assets/modularity-1.png | Bin 142886 -> 302935 bytes 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 7e4f9eda..53433f42 100644 --- a/README.md +++ b/README.md @@ -2116,13 +2116,13 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see ### Module Dependencies ###### [Style [Y165](#style-y165)] - - The application root module depends on the app specific feature modules, the feature modules have no direct dependencies, the cross-application modules depend on all generic modules. + - The application root module depends on the app specific feature modules and any shared or reusable modules. ![Modularity and Dependencies](https://raw.githubusercontent.com/johnpapa/angularjs-styleguide/master/assets/modularity-1.png) *Why?*: The main app module contains a quickly identifiable manifest of the application's features. - *Why?*: Cross application features become easier to share. The features generally all rely on the same cross application modules, which are consolidated in a single module (`app.core` in the image). + *Why?*: Each feature area contains a manifest of what it depends on, so it can be pulled in as a dependency and still work. *Why?*: Intra-App features such as shared data services become easy to locate and share from within `app.core` (choose your favorite name for this module). @@ -2130,6 +2130,8 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see > My structures vary slightly between projects but they all follow these guidelines for structure and modularity. The implementation may vary depending on the features and the team. In other words, don't get hung up on an exact like-for-like structure but do justify your structure using consistency, maintainability, and efficiency in mind. + > In a small app, you can also consider putting all the shared dependencies in the app module where the feature modules have no direct dependencies. This makes it easier to maintain the smaller application, but makes it harder to reuse modules outside of this application. + **[Back to top](#table-of-contents)** ## Startup Logic diff --git a/assets/modularity-1.png b/assets/modularity-1.png index bb9043e0cec112cfbb8242b7735bf5198ab47e8f..4ba0af469e49a9bd78e99abcfcea0da9d7f25110 100644 GIT binary patch literal 302935 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

vx07R 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

3ugQWh%wr(;c^DLIL(+c;&vspmMoK9#v z<+$#&Ht-I;3@40gX;>~pnB{@tVbm#N1 zF(fJy37zM@pVRTA0`At7>PRHp!jhA|I>qz&oG7tl)zVr-N%X?*MZpC4Vm0KX-*zlA z<#cxVkP#f3Ba(G5ow(rqEL*{2)OXEZj7i~FY?<6ppUyK_xX7ruU=|t!vSrz$%W<$c zl;y8bT-Je*q8!ebEO>ddi|RT62qR+Xt>WLitln&Zu8UTwiTATkDV5FoO&*IWKNkq&(u>y}ooR@Xp68JpIDShcHjO-L84Q`j?F^he?D+FZ zrregCf9l1O;zzle|Fwb5C<~D>(Vk#WOs?AbIQFZ=CqXb31~B8E)c=8C*16SCdw zTlh@(6UTiC;DbF~U*K2*eP6uBw1fq4AV;=RYGqZow!CE_Pc z6C7!YE>Bi7IDuz+exc~A?gS>#bM!o0ix6;FB#VvENMGM+=7eC?q;VN+zraWsy9=?5U$pZb!Fr_S8_`r6_u#7u3|I&+E7T6#X*H2U)_*Ct$2-kXb{~5Dviiw{j2H zO;08HWiQ3U*=1Z_?g4{r?F!^AGsrpQWU)RlAGC31GQ&F0F<@ApA8;TLKEzS_=KmW> zNbTFN)B8Iwj<)QA-&BWg@JSMbfOPH@27{Wknc$N#YD!6v(N||pc=fU5GOjM7IwL?N z$2*410LWQ)K>EkvHxTh~QHp2j24fBZ#BzB48HR(6@{VpQrCKBwj)j@USF58yIp5dk zvSv>IQ3;D;r~OezB*xeQN9>z=b#e1fgZWUVXxGQgFOMV@aPd!`A#|`%Qw5N z4LpX&Mhf6JB*XtJ~}Bn~dnBtn5)^{skI6hgi4dk>Cg zg@HCEszky@OcDyqzW!lhQ(_AIGqc{+bMRm3K9bi>*{cl&EKYC{3i-8Ip{LDCJFeTN z9M~7UV#R)X@wOctV9Es$9q&r~&LdYc^cJrE^~zk;h+@*cwN0abnmJsrUohZbd+(4;AipNHS&n4x}q$7K1;}k($uVxHDN@OzP zB+%G|#QuuW0LKAD>4lAU2+j+`LjB|3z3};FOF>dOOX_|&?|zBLqR>{2neT_9R$tMP zx#?pBAiG66f4HSMR=tf1PYt=>&lcUddYFx;*&OY5$vkQ=e2X&c9`~@Y39iHuZj0MX z`ff?|IvNZ~1gjm$^AO6#&M2d#mc1q|q|6p$@=r`~6WS1FbG(#dmGP2>n+vRJ(sw?u zv*oCpiX5;g`1ZB*x+|C`8 zs*MK7nF_@^{su&ga-`xnnP;chGPBv_S40zlcco;D*4IM)up1OEX)q&)EKp3~g!w~J zpznST+J^~bWkRCza@u0}`*#1(fK;=%%E-4x+)k8Q!bGxss9POthc%H&fJ7~ABv9xZ zB0vye--Q6>WxW%NfgeN|FYqznDo#~(dpo{+`rO)~hUpU%`DQso2H@O+! zcz0A7zw<|UqM0oKtLPQgVBf%p-L*{Ss)Nu~Dg5;9Y!Y6o8-h6D5 z&{mcDOym0e1VMEP^A^DM7mzesr}bl|PDM~a=vT9h$2`e@v^P~gYR3O)Z>)+y8}hcf z#6R5^wxXB(x!oAj0oYV7SQM-Q*n5bK9o1TG4Uk=0E&%A(o%TLHkXd)u)ogsC^}37k z!cKl_$yxf^q~{OL;z|+{hXm|lPrM!!XvgpOv$~Q4FPdUjapOw9?zAX1%yt(H>J`8* z#Ho3wiq&&%5ggEF*yxx4;pdb(NZey&q#CGy9ZaQ^qv&|3V>J3(O5t#@B#U=xY4L<2 zR~3N3Es=CkPsyP%Xrqr-C$CwhHw#Wn_h&ohgTnp?XpE%)V@gI~^!VL_+XLjRk-nm5PK*ep1 zliyXS7yC&q&+1kro4cf5QZ!isd`K|<6rs>(ueZ2>FP8|a&Q!{+v}CY{{)N)HiFc}s z8L5$*Ld=p~jyeXtKg9M~X4T-xc7MZi@`xIIoe9CKF3dG4Fv+iLCI@lPH`NG5L9$Kl z&2SCtY73zY_HSPYq4(^DxJpf)YFI31tjB8-HXgG66zt$^Gb0PWzq%qT7AL#OVHfeJ z+CSlNvK<{%1)l;ODF7OtEdJX5>?WCuu|^4K;+xg#v`tOPwOEiwX}VE);rZ>`QE$xt zIee?sj!dOxR(eDL)Y&^U$aDSUIDOf+tNdh3Iz-@h6v~(HZew%n^eURyfAjc9FJzu+ zRgUy11T0isSr`e5{$VuuU>cf00KB1iD$OIS49NXOXT8(K%1tmQQbvD_Is)Lnj^}=d zViN>#?rLd$nvZ)EZ}4i)2iQUvJS#nKA zTl$Rr%I(0pT%2U-bnWk6is?V5rf^D4kEi3REEoWH3 z!)$<-?0HOo0`tZLLi7W9caJWYf(yhYb@ugiy7|PX?S!^{rQUM`UP0*3UcE_DC}$mt z1L?LzH6fP>j6&5yA#+iUn14DBGE@%5S_7ozlEOe&MC+fXBF0z&IJ5m)dp--RrT|1- zMU?hK0IopX764IRMk1EezkM`9*QweDdkBahn@`g=3eIin3NagS%rh(h8A890-{ha` zV1iW~%GB=nkz#gwP-Q>shgl<>c+9l;alD}ZLbah+=W#tFK>#3VgMCNs^z7t7{mU#Z z&0U-;KTa8;0Jb2faV80tL5<1%owM6Xu^G@nLLP~?w%c0oZypqX-*ZU)?FnOtgEd|x z5fmK}@%r69v?&{A*}UJ2#!;+mbkI%&H#8cH4SJU|ZvnmqwWbs(g1*xx(uviJxqOMo zF%vUoTXjfebo8R>piP4y-ShqWiclp`El~61|>q6 zFph<9a`(N5|F*RKNQ-fm0J6plyxK=aZ^nWWaRPAb5%9|ET}LX!HbchUcfYqp{GR=L znlMp0vJo`sfwu`kib$qwnjI~60f-R?zzs@BTK}LHmgk)59bKK^MG!;lwL`-?Gx~lI z5uAGVrSM@FHJzw0IjpF1wPHsws0Cn&X|gRNYo2(q;yie6bgl|1H2r#1kYjqCkW0d$ z`xtVR3gD+kV%ylokzAD(ZO;dXioGmWKxq}cCrQXdMyJhF|CTB!@DHCRx%?VQqZlUO zNSUG+<2tXArYb!LPGv5=6Nyjy;ali>brPiURLj@ZaU+<#9VGHl1VA7Ml&x*BX-zFM z)HDx@l(OgbXB_R>MS=MG+s{%Oo+4=GeyGask%D&|9CBXNFA?>e8Uky4ke?Ti0^76Q zpoj6w4*II#MMHjSb6in#2eMdqt3{Bl_yuQGaD4kRZpPU5LhSaseITk0yL}fjuclZp zCisDJ)TYa;C1}X_Sb{SBASx4y;#uElwov3V17sWpu>hE+2f-=Ry>U%H=USJG0&0)o zu44E=bnPg%6K7+Q;b5XWK$e@CB(z(Qqw@9d$#AX(-7u&Lvc7eAe;hp{E3xskm&Yd@0q$-$B z3L`&m00vlGgoJa|e*yV#h1FTc@5Pl74JHH?mU|DT8+R8{_Z=w?iWz5X*Tr-8_apgb z!9vLjXfsrQ;27F_+BXK_qWGC7Iu^h}fkxe^X=|vW(u7WlK#&@^%k(u3pX>*-$P7S- zk{J*eGDm$l{)JtV@xJX_@nijC1GPuUL(@ukQeN0}D9t2W@j43)tT4g%A3SZZsK1$J zPs6&qv9IQ8{6}PfNMVbVl!)^MuO1r-4w@Md9wQ>|`xj)eC_kaZx4+5_; z!$&m<{u%geqqDzh*a!>b$!-YS9jC8tLW_Ob#RZ;Hm%$v?77hbuDT|ezdF3+Ox@EhX zE#FhRUpQ&4Er>{oJZ$Yc8rRZ%P4|)7#3d;)tM|xfTU+F>!hN$$Ltl(dnq@ z`enCz2g6h)ofe==>hX_O(0 zq>dPM;K7bjhj?usi9=X^lhgwfwQ_rTyr>4Dor%?Yk$SChO;)2DTOsv0G(=@Oub9eu zXHM1C!*iKKDMNS5*${0=AF)z3H#oDqmiZQqd5bS*n$oaS?7J(ijn-;nnR|=h#UwgG zE+#{eGd?D4-{BZS7q|nCN~2ptQ+SB5&I=z3(t}S2o=LGXVo@CK1LvIR1`S4^PNxmN zhU~J}@5wMkPWo1RgdY4}HrOUG>XGF)vVME`Ar;S}xEsQr+V_hPAW>@@3BbKc3t88i zdv8CQ_aSlzZXO5Vo~{#3>mwGXcMrRI?N$q>)O}nd;GC{p`QosPSd9xycdcucE`QuM zYQJ3RH9!GWKsM1qB`&K=jqfJOoB4XV`2rjzKj9nS*o)Jv=PUx`)=L8nTk6I~+&Fd= z4vH@&nS#;=xqg!-PwKnITnrX9yuFfsDGQoeiRh`yDG|< zg@q@%w-ACADc_fCxuXxVA6QUmv><9C@>m9orfeoCFW-!s3hg$Hjs{&rFPASV zq}X93B79oI+6v&Qq5&##_hsnB{3))-dW}$btRcws1ZAg#lV=n*{aw&lQ z^A|b@CO=XmZN`R96&}FRJp8Rf%--cZX@)aL=WUFw#l_utcrb4W`o&%zdPZkcH zMj+@S^AY)PWyEmVAT}^AqkMOCTF9wsKPjNd8On6V zO&O~HkjeY`6xNMkVK{G7G~bi~VnPL2W%f651z@@7Y3h**1g7ie@W?B(W@>xgzOb0{bvE&%3~j4f}cQISOmFB$yX@SYI%VvwK2q}My+y{=*W}So3=w(JeP51 zbt3Gm6ej&M z+4+itmz(b&=dt9PC)z63(QZreltbW|`0F&^c{h|k)*G^l(;ZLYHru*|>^vl)jX2JV zuOTOO)7#jH0QUrvg6CmVmh`Ts>Ah?NS)r)fzal8wfaN=+jb;o0+`cqODk-|byzlZN zA5l-NU6(jpl*9?>7Bedt0N!+jomhxlQE$j9AjVD4h=IfupjaSmb3Xt-^H6m3Q{ zPbbH&6s8m5I}wwmg4&7X+w{HVeTgjc=voS>qeD5Po8SR5Cf!)B8(jzK>+}s0PT=9C z1zET7h^i0I>pvd^!F};!c_t<>>l_A`Rxch(cCIO{&Myc`vR`uNsF4OqBP_ufzj4bA z!X`}M%z4#^P_1zabu2;r?W?vacVd3mn(HX6dEmA+oxg1x8O4pSo>8U*0oK00#CK|+ zl`K7Qnk%BO1aCf4&z-4j8D*=jtCK6lSCZr}6?22am3O-z?2wlUQ-T9PDN}FjsSP>^ zvjXNpdMebREz?=%rWc5#hs-wyHYC05R_nQY?+3TLuoj&@J!lvb(1q6r|7g>n| zqR1&J065ovWT+;{7zw-<9wQGz2xms}{*TaSh~nD-f|45^dPMQBSCBd+-KduynG{Sr zBtBd1KJQ}{~QER3z0~-Swn_~ z@vO|JDi$=7EjX8+UC7_ksKkwnKr5M$2ruYTl^3M4+)8o%Kt6QKLk#NcyKh%LDfZKJ z)DX*cSHgfQ8)HM@mJCyt&QAKW0m8{?1t%VqGOH&;2YA~YI+1|>8N%QE`iE7{vhPOe zDwK6=8Ar^f{=V^z=CseV~;1B z*llL5k;N|R8#R6OVa3STp~Na8Tz`TgJjK{;V(3Ch&VegpvO-l%-eI1+p4~?6C@j7d z(TIogh>Rd)c1^dYTB2KdE#iM=@jvQQ@RLw&vygu*)i*WicOPL6Ge!!NBr*nwR$@Nf z)lxS&(@7AheW|4NJ=RAcs$bI1YQC6b8Ex)M-_Bmq=WEWnlZj88%KL6~;L)XE>+(7C z=K7RD$3+m6@3<_|0OjFTVE9eL<2@9aYj1Qjy#S-(uQ1cczd7%Vq!aU_lnXzcGjZe` z$&%iuy$C$iYe7hcY17YBlhoTI!nzRg%mn7!bu zcY1S;I?e@3nl38c=+;xQQ_?2ijVNFo(;Qh?iluKX(E&LL1yL z*&wFdgr_hzCQJ!+G^y#y%bv(}eB5`w)8vM`l@4M~*&bUU?hHl_6T#+!pe+ZNZP7%{ zThPaISL0J-;95?rFd}ogr!+zz$yB^I0g?Mqx0(7_AN9&poCF+Vj7BMY#B zB`by;pSWDvQ?~%JGbNTnRS#k+DYz7HY`}%v@&gGHnnD&!j}vixE2$J(*|YthSpX0* z)Z_b1MmRa0AXpZ;!k@p`k^Sv?j^qSlYB{Zct-S^42^UY70^LU2NAT$}BDnUcl*6sq|A|&_OTts zQm(w!!Z;U>eC@h|rMjcn(+Jzh%}*s-g#QS+An% zBeORmg`q5qCCcaAeJAPGG2c36Q_CuJ=mt_fF+m|K+8UM_@)s{8vmCKLX=A+Rmk-H< za@h5GCYGOYv63aibBrLOp)9m^0ZAxMr+@eHaPIo2kaX12rXmq&C(+8;@(MfVV|Nym z{U;pQ0-!I2Sw{jIMXofa5&HujsKQ^{W4z4^RW5K%l+cnf10-}bnHxqTQXzh^%4asm z81EannStTAc;u2&XchGgeeincDJEpmRJr^$LgyZ-DWz2t3sSLvT0>xz(cx2S6B>|= z6p&~y4f*x$?28c#LQSe5X>sp1Na#1c01%xMXv_s1Asa3r&*nQOAdxZZEKq~16l?q7 z77CTbG4jEJEHZqG)-O0X1 zCh|`WP8^)ua1G4x3b^a>UZG zwr;x@e9ov73;!zr&g-?!Lic8>xqglc=V@H|nReRxwpncnBQ5vKD!jA2T_Fu0N0Kty zCfms=$n61fs>R-5$m4w&6yp_Sp25q83h_wOhLlk1n@@2mVl*4FY`+8Ri4=Uw^6m<6 zU3L~@^AOI0OuQ-$r1xg`Hc)##`~shI41qh=M(8esAi9d@ykY2BAblbY_*_Eol z$lIR~Zrn0Z^?D^j{_W6=brRoAK`Hy#+*5ve$>FtA+!C6vmUkekb`P<22kp@}nsN#(zdQ;6QX*#km zh|8is$^xm|INZME47ZoH=}f-V*9kXiNZ7PRU>gu?B&V;#l`2PJ*Bj0UO& zzskr3MDeOvM7T5I$VDNkQ}k8!5m}EKUtvBMms#ITP)qlBWQ4zls(hdK-|0O3y~H5k z3Oa+7I0qis5}p`0iTy><1a%hDE5AUR*|(R$GJys7|x9CVVP3=3$YH z0WfJC-C8Af+wer=J!KmLaC4S+kTCgZ+@yQ;fQsMuaOaME=ss0$XZx*_(NiEPwFCqYA^Jx=)qH?oCN9AXzk3?q=;o@~A~0{F{?(2>hS zx*+?@0fbdR0TLtfk}vJA-2SDT9m+oPAghA4lut-Se1kBh-=I&Z&>6YznaCtSKQZt| z>=|c82T-7eC{}(;8Y|nUTq5t52pd0==GfhJ0v_HdUm5A;tdu*Z#9|Lk~Qz)0m8(^!Jp@k%ev4z;q1aDA`aUyN+wGq zGP;&G_@PV_;@K%FUMs`rf@R2+o3(zJjV|P@0<5M}TO=kfu9Io0l}2L|bX!Xuje^up zm6~MFZlv)I(sDk|>Ge(7O^tFr9yd$By#$|#)Fwmsc{*jH9`E!I)%+vT88-sV=`ZMm zUn~q^hn0p}t8QLm-6Vang+FFZ$O{#c=ttp>x+!#U{c(_o0qwY(3yf>V0od){0MQFi z7v>t?vVW>hqOyQNBPu7}Y!81%9Ysv_9l@8=!negK#kC(Q@9ca%HeJ^2r+Z4*iW@R( z7rtI_7qb{>X)@a{C%pc~Iv+96v@VdT&tX)Tz#-7uMb zzU|*Iz(-^vA}hk%E3F2{mT<{0p%-_WE?y!82VvQ5%4z&Dv9fG^iG7d^Y)>{34>(Nu z0(l%ihN>Of=)ztchV<{e^l#rIpv9gzhv4$_PS;*{r(4nR`#jC7yZHGZSr_a-%BFrB zZ0_90%#e)A0e<$Ki-i+tF)KCs72r?%0;2FQ-|k_ia$wrH9|rBCmgiLS22cAgq2C+_ z;S={EXNacGZ=if7(1aQeBG_j6)U@=szP+5Kynp{c0F6L$zmv9$i+n-i_;0q`xN&iUUJ&0_-?4dQ$+Cxlt9C0u)hwC1WBp!;>U=H0uK@=bg)bw8jSxs zFRfVuIx6!0u)&xkEUH4j#-MSTaUej*0VeQdNusRC_o^f44nnDq0HF9mU{;j=?xnxw zt+Nf-;>^3?!Nr&NxC-rfc+VG=DaYjMbAez26#D4!9-$qbBpF2Qmc~Vuc1vbZXy#%3 z)MQYv5^L(P4F7%xMu@#eys2awt?j-np*l;eL_8|We_Z!|tiavi@XV2KIRY3U7GmSizVeuX=XoE%8?A|+@e2;uZle4(Gb&9d_Z_n%Z$+scp4qKBQSkBx%4 z?iLL>t5SGU)zJfC{3)izkA+K{3){)Q01ZE3p=#rkI9Njvlu3>jByB6&RSiBlP31-84%E*4OqQi=EPAO zPg{#C-?a&xR?^0==pYv_U%+n);msh6WNm>GVjfy7iUK0?L z>-W|?8gx}CLAbB0m!~WRs;o^zbP%<*nRr5d)#m1igN}n-*|c{jeH#Vbn;gfpJZiuL zY>J*eJ1XOVLzPP1HW9M5sjA<)ljcxw40XM86Lw)Lg^w4a7+k+?^Dv{Gk?9zn5De4# zOP6dM_0tGJ+-~2TwR@-;dsXqrh5x>*knREx`7F8);9P2)u`mYRMv0>?u*)$|WGUvU z2BW;Vw2C9$7029a4s4amJ#n5NN}*DCZrssQV4vS`wOvd_K_S|RU%#-NwF>j^R1$Pl z@>}kCc=w8yCRPIAvA}%j_A?;by96_$E`E=Dd(pPbdJBxYL-+Dp_ zE-@lNIr9+!3#Wl000S+IIPVUy*bl%sNyYsU{qS3e7JyozG4aJ`v`zi@Dxi z1GOfP>B&F+&Z7OnYwOM*h^9d>6?RkV(S6q%t1y|;E=!5GKqW8-(7%dVle%*MzEMvS z3Ko9l<}Cma=AWX9C|aC&G|jgy9*6?u-$^$7)jL(ouC6nETQ2Gju=ok5CVU`#ft>$t>{K#pJke$5bx?#%~1(R<+q@={%^9AFd&9Hj!0LEzVt97ZK{FFemI{M{zcMgdDw_;eYA2ioQ;e9B1k zL(zBSq!}z5jfqkC#th@t0Zi;sNe-fBCgJCpKSyF4suFC_2K=&k)c%;vzJ@Hx0dbr0 zCx@nD%3Yr`_Y~$h&*4@CUOxr6F$3?I0}RM=Xtcp0oo*KQ>Rbf~;3U5lOjk-(0UQda z%b_yu8y}5ZK3yP;v*tYGh*6}!QTelhhi!v~x%M#Dq%pFW4n94OdS?dnc#SATcW=$Y zPjb+xh?Ml7=F4VhQBny?R1q!Pip}4fw;U0B`aly4@X-qNAihoqXA^*`7zSGo4X-S+ zhQhzOtupDo0nL8DD>i9zB7^g0I>Rub1JoMwxYRtlTxGykx<QO<(t5)A|3u6+-VQd^t1Th^f(%0`Uv$={+Alu}dz^3?70W_fE5;99{ z9yK(PdKqUr*$~6QDTlyPmkMq*=@V{^D;H_Lj}rYSN@!ggrW-_k^IwV@d@Gy<%b|azfVskIoZV4 z6PwLEfTX9H(H32Dn0AtGs1`$Zg z02mEUU47tU3&`*R4A(QA!RwD;-nB-a0VbuVkGU@J!T}d(VCdaxUjSgl(9GxtFq}39 zEQzi?$%(lkfclr8MI9KyQB3ARN$bu%9GU(vU!S+{-pry#tkcee?hdX$G77LCg~J1c zSVWkH4`@{I36#xQntlB!dvqPD$XA-<$Fu`=rla;b?cp2jUoyEA*dSqArjJ?fXW)DD z_=Nqh!yfI=qa4a;U#YNX=Q$84!E1QDSciHHx(x)%651rvh@2QqaK;Yq)*Lm3sJ}7AM%N?60GkdMg6jG~qf2;J0*OBr~IR4jAU( zL&Wz~0Gf)>YlM5RJbj6MEopgZD2?19>VIPF}44jb_E3wP&jUVJJ3a}*}k0U;NO_{hB<2S7_BS5+Cu z0sy2%EYqzd8b~c7qmjkyt33;>=UJQB+Bn#g&|D^dae+zVPV5<-8lW1* zLJ);~D?&*Rn^O!Vby;D47}mZpp$RNxA;P4Tm+Wzbh-o4c^wdkj_S`1pX;Pewc0wL| zu(hb5N-491NI$A; z?^Mu6sI!>Lm&e{ZK|3aX9HCR7hO{Qu(6-RR>pA7}g!2tHYH%3WE&($s0G0{R>Nutj zMHZ2aPD@xQbYjpOVZny}BQi|@{U0aX)bct`!x}}9Xci+ag3dlyj#*{XTY?68$}ItB zg>W1+j?>lz8w5hKlG|CmCC$6=Ab;J+av5l&(e9IH?9Htf*x)AF&~c&$S}j$-)s?gr zn?24kQ5bqg6xt3o#GbqxagJHjMl{M|3BKdd{an6)`9cmbji@6mr1CcJG;`=vd6r(s z$y%!0e~ysyTIK+0;PgZQ&y z>cnCQI`wh_zp{p-xwSkSBZH2{tBfRc8UT$d^V|*xSBF*csNWd-Qd1u0l;-@*sCQzy znr8gVW4vHDZ}_Q}0_8LY2ANk=XxmJT4O*p;w_Z+i3Q|jEobH)l47WHypTNPSm>n3K z42(pbb;RAjJsgj!=@a-n)T_ae_y9)5^L^n$s8;ZQ0o@#c!FuTd86EIK8X21Njy67l zc=x|Qb^wE3jxZ$+K&Was|FJ9+yZfQ@&T2^$KC7yuhxM0#u=)emTGurE8ic2++5K3iVHuAM$R zaR1p+U*?6oQ9aFW1K%WPq;l%Ffe>B77T#MS`F)@9u_LSFd=b(N?-+w`lBS9FQ~~1R zcXZg}Yv8%806uhBR+XP4z?$YJLOXnl4$fBCkB`?ruToy?x+~bWTBT?=Z{7p^Mw68T zi9t+S6YwwsB$}KuFX4PqD)a+HXXs8UcLP3dadz2;(E1!3L5r8Ya0U&IN%3185)|MW z+5qrQtMdrbiT<1L9?Of%9Eh}u?l+1blzt*i$kav4EWWi+>t9(Xyf1XhWV3etPQ;$S zGR=wm0A@RAo;YMuI~iaRW&mp(u8G$ZqoKLIvjtvjwt*M@s)~2F^5J||KkP}af}O(s z8#-UNs^n<23COc-H{ioBoF9efi=e4H0-bc2gwPDCA&_VdkZ68!#f3HX1aysYwl(&( zd9-n5l62+#nDgawnL|}6DKL$kwzIT(1_01>zsmN?7hSQaEaz<&jpl*Kj3wbeCIK17 zxkF{kykd2AjRU|@gB5j$xOC-#$<+t`;~oG;AEx5x(ez0&_L4jybHoM*FZtya_$tN* zrpx*C8e@_JIu4$$To^}ANK#Ln%63Z77}9exGs~j|QKOB{5vhKsYn^j-4xoqeK{!bJ z+@Uf*sqUV3QWFQnt9Ey8)z&$vV|KYVcd|d>n+WSY>gA@|;_HUFwF<8&9<0cC_Bc{* zRVTO>c@L>>(%MiIC$=cdplP;>=1B>&d8p)N`~mnIfE$mw6E%gSpri?y{sai27STK^ zVI?MLiw(3K$F0YD2sj^ zFhh&1R4RMWtdLsTC>ywo`hXpr%mm~-EC)c-#2K748tPi*$u$}wIs{ICoIPLcN@p(dTs>r?h9JZ2+KvHi_D`Z^gSCaiY&MAMyn8`T3mn zMPV#pDh8r#Y@BK=!Ib6b7YQXpXbcQ;niWR4b{ikGloO_5zz3P|Y_w{eTmh0SK#O%i z8i*Z3`$eWpVKghG+9|CAsX11vs1P!S6^d;LFeL&Vq)uCg0i1;nX?(|QK<6T+F|5~Y zAZR$MpAXBGAGWl9sSYuvzQ660H^Jk5DmxPIJ@q5EbP$%m2oe$BEvP&LduEhah5($}C z^|4_pgc**u{GrEM6N33n;4JH$3kN;yG?sb*D4oi%m}ke??95)@q=}?;PGh+N5Sd0} zMdRYA)6l&+oy9A(qlyF1GA1MynUDAY1|}p`qL8pYc)*1K3_d#`L)Un1tw$oV67P=Q zn)BY3$Mx6kK~c2I2Btci7ieEN2c7~l_`C&P2*eO@!An4fOkX~vNr3LP<*NNAdz70v z>fcV%5?%wS{8v9&wSV%xC0igIt@=LzHhc;_?srtt;jd=kod(#?s&XO<2wPySI{uj6 zHECI+OPm(J_bvw|tnp3Of=wrM_-);Fzkm6-@5+lZ>g=2Ey?28>lJej&%9x*Ubg*j) zQCZTAtg^Q(TCJ30?CD^m>Hy~~0^hZI0l!-SG6-}VZGRra8}aA{bzfgyvDYz)+d#`y z{sr9N-SqC$ey>B4_uhkV0Q{CYt9%Z~p<$Ini+U?;A0HldV27elw8c!hw-~HlCebaQtUKe1#5~`r*%Haw>kl$YEW9h#W=s?8Xk$ zZXRZhD#?>B69DZ^M1Kq2aC3~J1vS*kI^ znk%59%;C-5<{aZA3rHdU1oM9Q9yzy_R!5ooS1?~GFfNKRNr7MvRG^#!2Rd*6^nK?i zupiBp82qw;Q6=Y}4~=%o93}cghpv8`-3<@)M}y5z`i%B2nkCoYzel^^F>av$G297vEJCj}H8KnST$wFeOvdFPQAyCiPBxRsy z*4I(LT5|%mysvvF3J=oimaQRhA(b+LM?vQY5!?~#@YFk!(wTwm=!D>7Is-r;bCrzD zLEOpnu5y`|+VqyVZxOHJWq=w*s%Wz*tg}fBA_ykYT9DIJ30iU#Da{m3W^IgXD+mru zSfw@_mK+#4Z}^(vT5Q=2b1eQT1Zn|8@*8lV5DS@T6kD=uWz&86vX?t)BovYiTF+OVegN>4k_|SV36j*D&Bn z3Y9lmN33$fzYLhN4wE5=rnC^pooPTGKosh)XSETXc2bt^v;mMo=07bM78lZ&F(sb7 z$#-cT=!Ct_X@~4k2hju41|WMvkSOTNf|*o1dZ@F)+GU)5vO+Fuyp@ZJpAAET@I1&V zZw$H(Vp>rGd}=n(G#VhRmBuTk3ON`w(Lc?Cix!`1K%b!HK_5(^>KaLrk1n63Btk)x z*Z?L-j0gBJXQHvZv_^jxsJom}F}fJPO->J%IlWRSuL=58CPAanBUj{9k9_*H8S}i7 z#<(1aZnBZO80PM(PTg>73mB#Wp;N)rNE%xu7?}B4%){8!Wo9)tIqtN@s;n_BDy5PJ zhX6B@!=A%k7@-YLSLX1)vdTuDMe}MyvDWvgQYb7N&tc{a-nkiT3Lh;s?-p}qpW9EP zNvEHO%tERHE;>Fi6gsuKiWg$EFX}k<)bDyZ;6k4TVhFt8v&M*PsNY)N^-&;zf9dpV ze5@RM1V+SCIPdI49~l6+a9SAn#E?VJEv*Y*1B3eoV(bvmj#bnL{w9rm2|ZtZH)mgZ zY1BS(5n!mRf77Lw{q8sC?T>$&ad!O{ndVp0u3+8UUl6p9LJfQz%QF#OCgV=to8}^N=}fn6*QEl@7%Ow4}z+ z^2LXg_OvD@GxCepO;>4Xg+DR_ zRxio|VJ$CcK{$n7Pjh_WnceUHq`;yJJMP{RG@MrPpk)XthyHu2lpyx{n=xYca(ge{W&OCnLq)o2@%DMuukO!$vqgp=+(k;6* zfgIWtV!*75lrf#E&yf+!F{ry5?gj;@O6qc#9mp&X_t zS;eK-W=37Q7jxy~*^9OT957Si6xuo3WZep*)p6zWMHXdGp!XIzfj!6v()eJ*(6X$^ zE@2#(_OS^?06gSCR%mkp1X-pvf)wO{jMf4)5H1cTLViES01qB!(q^Z1Si{bN9kf-O zwKjbBgLV~?_qVgb&^Y;#2x9`JSlI%f@-Tu0>fGp}Loe;C(Y9hCO92} zG7cs^-ieBH!UkiIhcObJJvwN!;(1-iCRk2hANzrPvp_t;~(wgJ=bzzZ}loEeEUFaS|2_`l%Piv^2C zhQh8%c0jSI|0`T;Eb5UTQl5d*|Iicb z`oRBDmoKqq|94-$V}Ix8C+#y=h8*De&SKeq@5ih5I$>VRivFaHShQB zzY?AmSxwx)4wDx>1?^(^*U~{nUEl?Kw*zzLepkX`heO_7_6{n)#eV0CKukC8LE@@rgl|&ou z1Z`K&-u!pnehOdVF%fKmv0Pq`My`DNQEgU|&`n>7zw-L6bD8VgiG29ofk=QHesXLv ze_ZZ6?)UG|yMAT=r!UJ0*gEr4QlGiRK-}av@AG~_G|vKzlx3dTNgiaTF$@n1AM7Qs zzDJE~zdqe`@$(hGvG;k8hBY1D3A5`;UQ=j?qhZ$%?qe6tRK-ra{kznD2NL=h9_qXL zs6+1q%V7ml(E8^})5 z)7scoIaYKDJSNT<7HnEd*J9MY^iXOW8U96?YW(y26U8{}kHHvDo3DdBydQ~ef5zn`=Swph@F z3cIKaU5h8n28*+&PUr4d_0`7C&W4Ten$>Jq7Zd z!lcP>iWW`LPbUeEq49{|J;G;goC0gad@0OV2=Ggxv=rkjj5?qCN$RIf#%mM$gK#-o zyA0ehiI^eiK))#K?(Fx}>oHu=xQH;$rGl#(%2BI;i`1|`igwo6ZF-PaSLJ}!{mPgq zb9%9sRv5gni|V2XGJ}}xNP|O+htxHtCcDDiE}$AK=U1BFr<1%oN@ZCmIZei+w7sS$ znQMSG`c&}AcmCbH zC8A4ih{z#!#xawSy?Y2flnMlyo`eGO(@?-n@V)oYz+}&oYQ6l6?H1xsl6Pm7KiQ+l ze9AvLKIZMT%O8l|`%YoZ|7}-pTY}!s-^JgASWm{s$8Cxz5{eKfP+pPJ1ezxC8Fv|f zPV)bj!;~R|x_?o7y%?gdw6hNUKrwzv+x680{?)FB5BTWr+_O*aeSWL#4xiawHnX-< z;@;=BitUu)-Eqi$TMski_5?V%8csy6-GgQ^nXmh~ToCX!|HxEh1NcDX2%nsnz4XILC!}wVUx&PJ2C#gMISdQ_y`}peaq5e%Yo~F=vI9F|dA z-xC7#keQ{Q{Ix=Wg%h)(gBJ6soZ{fDQ(mm4=GX!pkX@`CG|Jvg&xwvnXgo+18khXc zyl?ybg^n;Z>Y~GwC$KsO6_N@7D06yULGau-K+WE(KPM|CIZ>nl&?qO{yDkB_<_53M zyGsUSk#PTzlgjqmO@+1?o?{fs?VeVG=uIwas509(brw>76O*zv(uHw|4*ui&(ck^1 zalUWHkNIM!QUb126961(s+2H6ahg2))K2Zty;1=#;A6$9#{%%knQb1XkdJOG$}y=x z!?>dUpu8iqufZx>QfO+eVcM~RW>$^y#E^gR+)(Yb3x? z^Djna#!zq6OvqDzsjmva+QF#OMwyAp9#y`7q%|dnqgfp0N?_2lr%~M zbbwUFeqD|+y;a>89M4!q53J7p4zAtz@BY4DK?mK#`sDToLTk=Ux=4NE4O^J9NDEU3 zUvipXEadDSn!I^Mx6`Tdp6t3Vbba({vgg8n6+GbDah~nmv+u3@UffmIaqijm$OC^p zsLb8hcYohqaM$l$A9vq%@b}I``#!tx#jdOl`~9%ry0X~w@qV7$b?>gPd$QiTu`ZS12mld?2zc+)RAyF|udeQ@_P$v|R}}5ch+NWWNur*mCq3y|OAqoK&RSX{t`TRN zDldUbx!oPe?3DZ@&e@JAjwUL3 zCXot{H0D;bB^auT;L5_J>~}ny#0@3?;dHN%*$se&bi7EH8qo7wox>4mJy)}X_}Q8hpp2} zp+ew^#h?;&ZVI2@oP1yb>e^cn9On0|5VCURsYjb9NqD?EeoW#P$xS6sIIn|90wUx$ z8V88z?e27n+A$}R1$fA_MQo)tiE8Qh3{z>apXe_zRK}_irIL>;Y}QRybh$!W@l5ht zO~6DE_>o16XA#y$aNMnJx>vj63ftUPZv#97`1i%kVd<2NB5*0uYzg11U(r)Ghd}8# z+GJyBz|F(tm3#2PFk&8d%lZ0y3)~+Igk$w!pmXQrulrNmJ1@n98+UHIJ3iA*Y8dS_ zmqU$7xme29)A*pTvYNRYvLTm^Xe@ysUmIa02|WsEAeV?GG&&YwD-;m%8yf7kYQh@b z7$qDK;+d`JV6+l)s|n^p2a!l75P6(p@-4r(yH8qL*AHXs#}Q1x)jGN{X66b(k;)dsEya%*r? zT{5o0ZneZ4m&=Xz9IE8(Ks%gU5hiDXCAS5=Tyi&i@YPM6iK-%DP3Mk;og}s-#!(3* zOs);pa`n**_XT9eU2EMPCIg3dV6wn8bQeodm=5OUv^ub9z#`bP8BRpFfM^2GLAr%M zKvLuz=iLKCTwO( zD_*#`;QA9|u-FY-sh^jaOU?YY3q)jDP)I)_>)h(T+qL-eM%6zCXd+j+V}pcYM$4xJ zXtIQ`uRSv0Bo}O6$2U$^tD^xKrazu23g)L^>F99}$4T=Vk;F zF)u<53~nk9VBC}I;WPCX*lvOSp4Z!t^nY!)z&d^4JbF!OgxMpETQu&I>ngpYixML} zIEiygT=f1uaktme|K%<4(YC;c|Ci^%jr)CvYf{TZO>xD0I*9e%P;0p*016_CC@kWd zL$Y_f@wBoiKYj-FgpFNaE7-M>Ny2T;TOJljl=#epqW95dDB8!;_?lxe^z^pda9WNpLbc_+U?KP*lgL=>^E8>Qehhi^! zy#z9oNkW-MmK?aDqP7i>xbDI9imhc^IW=Wg!GjP{tbmJY!zxD=R827;G=;9h&I+NW z5UAR6=n|K69j4A208<{YBFX)nL{u{l$fHSpD6c~EUAWsMi~vnSqf7sO|QjkbZfn$S>oD0?<>%b(E-DBfq<8 z+``;Me)|coZtl0hg{|DB`UdqPM+aC)$As{09GA+V){e`U1YG+&U~d2f#aslSgSb2R z%?J<#NJ%u*6MAnx01Ua7(%tAkrl=2c|0)2gF4`P)`$YtW2m5=iyCcps2C-0pi@-I> zy(5@QUQNxgPvTs+5@E;mtW)FxjL&mWO86a#8XE$@=xyei2=k)5sn)syFuHIhNq`cG zp(3}lO7KDehWnj|7tnnMcGGid6X4vun)m-p6(QHE1XL*6h+|&x=>QDrUm)PgpnnUv z(05+ib~u0O_uqiNL~j9afrrup61!d@@?90r{2-}+((_pl=Rm(?+xY0AY^ATXw}7|6 zVYPrpQa;^B3uxj}$Hc9fu&M1*jpkuLO6XUGQOvsm|L&6%QTG&+cp3)AN+#{%SSzAL z9`VtdD3o<|8s(%i6wM?D0HUx|67P$!imY%-1;wb|y@>GiTYPG=7_t7rUKb@~P2pat zyZq?aaJO)Y{38tPyYRVeZelXYU8ZOkIaJ5RR5%cA02QRkDNDrlO!O2^vmu&h(v){A zvk^1{+5nGw5gbi45Q#!FS*5#bdyqwtkFE#W2mn&^OlXs_q_q5&JD=@@_KU*4_qCf_4cY!7|%a<7UDHckpT@6s)eB zCT@oc=Gc>|DXm+5~DmoL2kdv2yD%WNe zALkSydlmLKoU1k64He!v9jWz(l+6RD-phjd9=0gxgz{$79r zawl3LYQ;R@QD-yZc$xglWkAe>MO46ZfFB!7^y<-8i6I)R>)yoVe`W$ugzKo-;YDcw z3rr$AThJ!KX6@Ka;Lj|=t4yb@v%3QjED1nVjzr-a^57?R+b$iGZcS{L76ItmxF29F z2;k7YP+gbeJ~eB?g{T8}hh{NQIDVNnXK`7QD}~&QN&s<7MBV5B42xpFMgapbj$#Wb zTc_>Ktp2wF@+czCuGbPIq6E06kbTlKNyci(quKg<0QV%)%PrH8NLp`u(z&ImZoB5Q ztzin2w`w_nCb4rGagpfgXv1Zu-kQX&Ap?aP6YGkfuX9IH-19l^2ZimGkZz+GRsG!n znrT-zT{(&F)^V>iCU6149?SSA7sWmT+|a)mLY^HhNyl1fX)cG=rA!l==MsWM?xcX#u)xBE!t3HSOt zEv<*KBCU%=R{&y&eW8~`JtHW*I=~`y9Vvqsj)r}&>*n+K7VsAE7C7VYOl~Low^!00MOBe-XO(8auG7#| zfR`p(yqriMwEQ6HQ$m0u*E4D0`2F%PpLAOva+`3J^SZbtaFfZg3co_65P=t>wyTYC zCSU><3arSdS(#o!e?Xx|T`GSB&DG3IulJb*09*lL z2rn|f4I-pazG(ZJBq{d#!6#JJVXQ0=v0|aUkx6-@wE(ijaD{1-z$p_}tzN`nYzW*C z$We!@!}5%Pir~7HSe0L70-x+#fD#4B4&2B&9y^fuVSmz5JkpYb8U_u?E4!wQd)`ZIC zDsB}Cz>TD1@#yCg-hlfwnoJeKZUr`im^ATdf)K||fFyBimo5rf$VH=AW;c}hO)A>P z9L$|X^loY*09G&_x?vAVd{e)3r5c_AaRhGTu#IW~>DKb-S-9(}y|6L>hniqKbiwM# z!#>Hvh{;H)lVha4(hTqs$9<;+J4@o6VhK4=aTmKN#}AqWSQL21s4n62LUyl@tXpS2 zAVy!zp6_Z0eCYtxt49N)4kiZoH;fB@f)(x~w1wYY0Jw(NjeD8Aob`D-3;>4MFBziE zB>PTTO7rL@C*TrN(P1>w13cB%OCG8;4SdLETG<2N%|M}Gu_-@-_O#0 zS>6KP0v|mKcyQxBUUN~~6Rg6w!rEw&n*pvO)A*o^`mKpkIFZ=5N)Di4R zEiTzCB7?KDDW?_S&LLeWy;UcKaqT8^6+fEx`Qi)Y|tx5+aZFRWH)76D?)(})! zqh2Mq6t33po#ZOCvBt`Nx@hMw;0jb2Ku4t!HyKG3Di+0;%GF)SkdppWkKf_nbc;}c_y2%9{`b@TTi)eF5kO)BU7qZVsQr;83AQ4fe5;$vO@`wVU>G4L%Gc` z8(d@_mvK-94cLH4(1}>G5pI`6EaF@~l1V_7B-dB%A&;5a8Qe=?Mc^7nO=)MqB--sd zyX(s&Um=<=TpA&dUdOPB0NTU>Ty!6m&uUoYF^RG({5D$ zHoO1V!k74PTEK%F_wl-Iu<9qbgD`yQ%JKqw6)DFw2&NXdTN!m1LDB?F)c6(jEUsK; zk|QvHRciGcTSw{G?SBPl-^shU6B{;zU;fhkLV5CqXdo-m3Q_5tCn&0j=0X~G8@XJp z;2NVSFyS;(%#J()lrz)Qme0&Pa3iHzYjC!!lmsLTtXPjT5nh;{XJwm-Agkw!fC2;F zB~5T=2(_7Ka@U9(Kr+sRn!!gEGno`+XK)S4qDfN4L{u&UYt$)=OV1jSWkPdQk)I~c zsrf~F|4iPkpr_E$SaI|I+gRaXGOIB|1|5wH7cQe$K*&qjBMnTh>m@eAl~{#c;=*-O zmn`g+9Ii-CIJR5~MH-ozMoWdL7ZT%?c&IcN1R^ZJaF8&UtP{nJN#H{oA;(~t64>ER z-{n4}h%eW!-mnQoHU(}hQCHb`fyfsHfQS(~*CO@K<31w8FU-xm?Ke0)4WmI3P6C`Q zaGRQ)o2IQfSP}|fN(f%q7G&pKspLK((bp8`$<1T)B9t2-Fl7o&nWg0v*D~f@iX_xp z!sR7{jzya5%$y%K2V%Ayn}rdyhK9`MwPeJmYn;N(u)85Q(;?mX~b~ z?TcDOc@=qt)^m^2hA@NO4C$_~BLB?Wxw9)aN}Ckz#T5$3Ah2f{Et?``Y-Yp7NiAY0 zK#?f~f13aWnh5#q?g#EoUBeu87b7Fh{gB5MB#4rvEC59i>ns3XOpF62@Vjc{eyC+& ztt5a{x)w|Pu9jdf6*mWos=(eU+^dK+ory>w;EC%Wlq6C#&r8yA$@8 ze>Y*XENlStR<1Q2D#J+|Nm1BZT4UDNg9{za$#&m@)%J^@kJ>l>aoRHE>ohp-BL91KD%V_niuz4`GAO!l*O+bzjj@=0?Q6sK zsV5V*N`L?QYm@fVSLbaSqq*UStCN587Vs9>%K{$U*vm2pzFh<8M(f1Qpot061{3os zLbEP07}vuroP69-v79fOeF3)+0SIyxxYtSGMG=;WR<)Oa;}s%PK!IzAs}Jl4Cg;+N z43hS2wX!6}11qU3S=Ci1=>OJ!9b00uon``;MtoDQ59%nlAHymDx&Vu?LsIGGpbl=P z&5Amc7cmRgWn5!IUEc1_*QSc3Np*oi!1OHCf5AeqLUtTdarDlw053xH43YmvoOX0RQQ0^p*+%O%>kokYS_!tQC93ppm|bD#a>0RKVG-@E@cgTfX5SlF*W3=H``b%HzGCYNC7DVCI*Jo{H4(+s{khZze zC3`EPJ}m6P?r{Zt_TB;yxdlA9albC0o1EZEkxC=NiFhcJR5Y7 zkwSXX8NfU!Zirj3BQb;68)(tQG@LqV(y_}!Tk}TuFUWV-W7y^Dz^ZJ(XDHX9Y;WbN zF4T3h;jZ%Mwhzh*u==eD(6;@z`G+RKs~fN%SVi7Uu4(EO!#0MWn@6}Wt{nh6+eS;9 zlUlVQ$a60{Y|riX|5~pAO2V3{6AjDTc6B&*b52cl!sE9}3nu;oom>jd;0_FIaPv7^ zXNMV6m8_D--kOXs82bYZ6AUCsp~H1YGNLPebSGv$Y5)&^|s(P0)Ww_@To8` zIueA_6@bA=%z+r1ygLSlXu&&bOH8+xH3<4 zmMpdes957dH~@q1t04=cJXj7}xCvmeK>)^Hsq)#d*D-#(w}7|6N7w?e^b~^J2_fTR zq36loPn5%BrwEhe?w*7_`%JqXA4%{8_X;LOm5 zH8J`$H?TXL_A7VoN!*LS^pyeYgUEOF!kk^dxM0_25XCMpP}~zcg_*iK1g@SU)asto zLfOM`zlBZkpWXrw+5#TjxL;R*j&TiU#l*y{&CoH5xsgR+5YoUyoq{f&$F36{*x8i* zAIDq6gIgV^eD^-a?QtD+xo2|K*gF28%Guev-TvOaE;@3nKD(W_dBjZvjh*N1{Clt5 zZh!lheYVcozOAy%?R&P)*!mV6QC{MxJoPqg5a!}e+h&Vx8FARozr!kCM=N1zz;G)LWl(9YOyB5Tg?i zqfG!t8N3ktBGA4l3wTye^Hk-gwNsPMeS<7?rbS&Fmwm3#qhFPfOSG1I4{!)T(4<& zkTugiTZ_63+6i?zv~pn2%&ml8KzjuS3z^&WUbSlv7jLGhD$#;;ECMCnzpoID<5<_8 zVb(gj=V(5+pe%LaG=6=maPIlI`fRLfb3bcBU9KC7GYM*$N@O5^@Kcq&xZ>ev&IGLX z&D+>HYvVra0$Jmq?4?76X~c0s#$4FhxQ@wv`)OfXUHh7F0@)OvCW@V}Q1=BjUv3rH zSjX0Ijg2^^&}&VSSzXEC2l;KjFsX-9P^-_z`k=rDC|5^OkT978O7cB-A6N#udqYiK zofg6Iv`hTa+Y_J|W7J{d6)dX-ek4T(1zLg8pLW2qqMYSCJbNH|AZ{=qew#)R{5G71 zxla)vQB2(^^H5Om2%bTj|By^L``NnKUy}vtoU+ljj7jJn@8o>*BOf`UK@)|`LnYG)Q5sV&qN<^!2% z2_LK37XwKt`dS`%bEY<&oJ7OvX-|cwhMY5NG}>2E8;mbzF$zNf_Vs>W7BoLt*%b-n zn<5l&w!LtK&t4OIrmbiQ!%7N1$G4_0*^@v{o~FlU){}Mtt5TaG%@NH9H?U$Z3|t1B z!%S6)2Unrs6oSULpd-`!%bB9Ibv-f6q)T0is!7fX;0|1J9;(z(Bfl@t%ZW z%09|5KLhrcSU-76w>>BQLtrTR(A@ruKIpMc4DgVUI|aC4h0AQL5a`oW5=22INC9Ka z6c8-d@FnH&KBPO^v%JIvW>4f=>hlp-;8dFI4$vA0I8K=93fS2&Ls017sGo$`Q6s<; z5@|M~Ia!LB_9O(d5oN#twDB_veWWa4teohj19rqpn7(!Yef8XJ!2>ZiyO5WbzXTW6 znNv`VYsfD&(3rwn7LT|Qqn_e4=jE~Z(IIt*8_opX8v9vx9sN?HzLDbt7$fjr+1jV&J_C9+|k?q&G7>7*u6JqhhlOd0MCtU$0}Yk=_+ zCXKGGptdt07XOEOW7Q~jW}saw)!281i)b{-+9ryq*nRE+!I{V{b$HFJFV*vlHYXMn zy9SX`3rn8W-#(5$OMznm&dtscIQ~7T9wGdp#l2B@?BBt;(FWXWPT*SUK9Dbb6@gQ4 zi+}jmsfvUoRtnsano}a%`BYP25~5o7wBRzo%t}eAp!Cj=Dp82WRuU^YOWvngC~-?m z1km9Msb5imL+%e5gHyvOC*bAtffb7V5&P^eek&0h-3N)fg8?o|{BHv?&Z8gyLoT-d zf_@-G1P|FnMWJqelo)>LPYu5uoCfN+b^#nZc}zA#y!`L*K7FB244j_m-v>6-#=37) zk1uMvg&jWIv%dQuO&=M^1iWkJAA{Gq^|(2f+$$}rZ8a7vQYXHTp&w0{Q zQ&8;$3Xrk1ZY9D?4n6OO3jC{>bqtzE7tZZd-FH4EO~2ojkg@p;X2-Xlo+I97bM@-$ zJiq_cAA>M~{Vj*mqFr107Ikwg>3z4#Z4)S}9Ll|VVY=q`gnIC3VWQDHDY>iq zs?faFpxC%7Yj_E%6{SO1EFIec0G}sE<>hqtUG09otN>l69y6*Zcq8u~@)KM(7=Ec2 zep)1sR{7Glw*da56!rXzeY5bBrXoLeI9^gaaM_Q|c>8H8?d|t8!ixAGsONjC9NXGy z-?nX`d$DjqKY_>q_n$UFW+RrN&5H3%>!J59pvj&#a|bUnyE|Nfw^__l?37oF|Vqo_=pe_7#j32AmZuvMBYY8sl2+X#u3vi%D+{XAt2@ zc4M3wP$Km`#(9hc6{{ESJP+S24{y4^HBALh9o7I#4{nj6!BaOOpahb2>>`>y4L!=^ z?62bvRd&LRIdN}-na|zlp?a#-3OH?pw9^D9!+N%@DH4pbUz}00VLG95!@%i6<_;;S z*Y5_4P!5?Kj`Cxv49VZG0_DEFu<^Tpj)jXyOYzAbWtNLzE{Ohnb)8+0E4*ptwrIm0 zXFm9ZWy?!_`xXrUx>E9z_Au9zx49(oLGdR#&m`XweBV-nvxVkjmI9f3MLqmg7A0)t zN0$qBF{~WyqZ#CZiz%(qwIT+S`~yPv7-nZmH#42nSxza}ooB}7eG;8F^i5G@1e;xB zSr3PO?)yVttbu-`@bePq<6a&Dj5K;rQdwEnX6bg`J3)%A)GK6der$KcmlnKmp3>eZ zHAsXxxskQ0W_($u16v<*n?kjVk-8#5=kiIIFe96oU$#D-YhG|R>#N(QxgOoi3O){V zTbWK8ElZ%!b&xcdSjR=?^FWZw6wZKUzOa4am2rgt$ThV|1vND3V=4Z)mAEys63fbD zX)0G&0^s($z%rSTBxJS!a0D~k#+F<>%_)t5Rb1k0dS{(+bXk-9rTYy^v{SbK^Dh%n zCJU$!EK&!17J|lUxUJvqb0_uf2)q^z4Pf$t=5rBG^UW~s#Ta8RhTD3|SgH!?4;=XK ztd!8DPY3_1)$6}%b-6x9a{7-SCaV|Wr9-timVd%VZCqLp(EEn>_bUiGm_O2^x!zf0 z8bOYB>s0NY2$DjHYnwBg;9dg^FTB@R!erBoe0qX$UkD~>0KLux2O#2H)14#8;} ztQW2zf%gbHnC_W6)s>wNiV4avWV`Eq@JRiS;lFEB=qJvO)o_t7GN?C{LlxxkZaIiy zDa6=|pC-;?lI@%MHWCMt{fmb|aQxeJyn3aj+jF%06h-J+bc?j=X=X_MizPwM06 zK7yq9q05V>s9#Pk-)27DNd>>VZ*GAV6*>(qe$KzUAG_fB-F=~}qVV}|Elb{_w*}1= zh2}&K(5)mQnCjJA&z(z`ZyXCB_aWx>9Jo1h8lqc!CYY91)Hmq(@b~2&_JLw@KU#3J ztEJL{@dy<-li%g@h6k6WF1Fte;jY4LQY_>4@#oBY9&MyAltaGf`WDZB4s<@UG)7&>V z;xugky_CMF$o-~c?mYYcpg6s*)x6eyx0m31sH%^`iBBB2n!ZYSSgnh|lYwY)ba8$^ z4&u(;$As2(@}hxrZQ)u`RdipI?GdnzN8(;R7FxEd$ zn`~>kxy}6l1j`WQ8Z^O~L=WelLXO}&R8IG4#;TMCjXA0n%@E>2zXGZt zKu^sEP$4AaD~}c9&0wt@qC&r7Lzq|&FE*NfP9BxpIa52(osbhfHsLr7$wPM}gW(t3 zGwNFNnO)C0Orr7W<#ovwb=QZTw|qAg^r;*qK6PlRt`6bqD~(`0fLD(0m_93KVm`8j zZ6~s;sP0+VF-kt?;cqZrmcEx#4TkbK&=EVbRu@2TD#<+)L8UaW_!6ROnA_;!Z?Un} zCT5B!0qARKwO3yeFrOCQw9fV7G*<)%xcwEJ#ccbf)^nqB<`SFMmg;2K284Gf0FJ%Q zxApvt{zLK)?7r%f{w=%m|GDjL$f)!j(7^)zA||weGxJu21O5SR}~ zNfCf+f^lQI=z!P@xABdWR!1_U>uyyA9$=aL?ZNzid}}8(s2PlyGyt-qui>ZkQPpox z7{(SZ^OhtyM}-MGPWnXtw1^tCHxu|HJ^Up-byaM1E;ybu;@^Q9VH*r*<;&>RdUXuT zE-4U5PUu>m09m|y{GfubU?DJCUwDMOPNxf+B7%k(qwFOjBk$(=5dyx?N}i@=>5z#b z+A}z#TdDVG*-*%i=w6L{n-yb!V8g98Lk~~UqVoiYFa?`A9#IUGz?zltt)7xhb=B2h zs4Cr7?s6!J-erY_s6=!vnUcI{j;n%VwtNF%{~1-+lUd5s_*S$gNoWM4T9v?9eSkcU zjzXO&y3o+Pgs*G7^!Nhn>i3|-r$BYORj_i^L zqUTYNbp?)MqiXXq8$U`#Y2e4%=Ut>^1&(U3rn3+3n@V7KC@wqF?OiOG_wr;+;)i(A zS%Ot;@Gu9Eis0^nL@4*KKc~gLiK3xhWu)jdcS=S7Q(ew>p0HTN*-qz}V5N3jr{2Ox+R#_}^fCu++UaDWb#q<>gcG zvewQ-qTe{dlM0fBW6A%+I|-bC;LIrxIA{#Ub`;i=Ov?Oj0!DSY6WT_;Hhg*c z7Vt2VInGOE{t-Tb$ ze=H{)vPqO#uV-aNWHeo1jawDo^nC+OZ(l#+eCnWpb1TrU?RLJyB42)9j#u%pfk!j+ zY`=A8JFDbMg;}P_Tm#vGMs~X57DS5``0}55BNF~aqn^7aW)q{K6!h_o-?(l+upw}Q ziC2gYuMVQt+tT}b^L{Sp4fI>N04}|9W%ZIqZ71s{>OCSKY1PQG$!X99SddTj{ z68`#O_5zns0^qC%V)d=og}fv(EG!EEN@{)(wX=vGTSxJ|B>$T4 zPe7~1NP0lt%W7XCg;Ba7Ech|L1;>*souex_xMVNCV^iP;+*7NdLOWO?O~UEVdVg`q zZm#JJx%uUV+e~GIkCwQ^t@VZ{v}SB~%a-|VTTkZDy~33se1ksv@-=z)5=&2LoCsxQ zZebO`@-~G2x?;iv^r|HW%8tF?h8KdCyiXi=mJ0pa(o4BmeC&G-Uc^!f;GlgkKzr9G zEcD8g9@){xg}Bt0(!#k-JX21f?%H;W? zTLNqg{qOi`f8*La-iSa8JZ4g2f01LVFXt*mD{p_n_}A?~Ue)!^9M~ zrwDux#l1mdJlXF0PkHQw7DFtxp(~(C{4GwIJny5HuY3-GUeH1|{^?3#pP~odYbc9% z$NN^|Qs(#t%oGkSfG>em?pd`2Uw@l^DdHuceg#Tq1^O(vskaV1!C(NonAk3ADo4uO zwseYmOB`$A@G+sQY?Bd#`%lwO*qmkX=3_H!GI{^#E9iJTw}Bi9jS0V$<%)=LEwZHj z4@~TW>zBw>g7K4z?u%f=(kF7zL_Tr>B=)AMvw)dHPX`>obTyUj7L`**M^48@dxd;c zlV$9Ks}@q7I#a~RFS-UwZjZId)h+d-chgTl>%b@D&x?gSCV13rUB5qFMf9H8(hFM~ z&=C*d^9fM3|1(qj8z-}XAUnEmN#}vZ@iS=<2FYe!1&Kb*`#BoU$2u=?7c7Py(ZuB; zPpr&_Dqt7Jxz_Gx?N*UG;v^}M&*^M#MjWL#avcwW6K!+h1mnI|hhSOC-ebiIo3iRtz78IK$>Xk#%lmoR}tC(GIqOtiXh{YvRr|Z~|+i zo_1?h|JGU0Mdm2(g?z|;r!DTkvAAprsjpmNuHyavMh7J`4|-qhTrZ(mY~iLf0c{NP zU6u{c6y;3|iJB&pKo{g3T+X#g>XP=$Ex^Y?tiyqc z4!Gp;*mDuGD3NpOo0)8aYEfaoMeVF(iVn--(*oyXA}e5`rR=FOtT*whTZWcen|@1S zr*T4>3`8b(K&X)-VQfV0s4Efa_l*6xzT?Nnl^whbMzZ3ia)(uh zYyoJL#W^!Y+@n8kddFu~jXU8Lim2dB+IG~)u%+C2knas5edzRzZ&potU7_O zgwQvO5qQ4TvySDs@~zukHzX_rflbR?@+_Sms8KL>V~m^1nVuQ0RGhE|Z4dN?0B8OM zJo$J1!mCzlcc5__{*|fkv`iK4RN|@t$$1)Uk_d}>c&)2 zu|LPVeGr3f1wV#HFIVGA*Cu@e1({1nm)-c6*cNk6cEj?PcJ1=iA*0HY`%D_?){k1+ zJgE<*xfe%pB4T^7W0R$uj7}OEH`hnC@UmMirBg^ISu)k%J~jYhp1Ktk-B@p){c`+^ zx%t$_Va1l!+d$soP+2-2O;Pm?+G;*lnf+Q1!sS)whjH?+sa-?v%w z=xrieR!!oCO%!wRVE~a@_Eu{uJX@x6z?SFN`z~l=;(s={-8PMN>+(n^2&X~npZNs% z`CY~dohOC~q0RJ^#I1tb#&2n!EB*n1e+#D4*miP3Qd!AtbpaQ< zk+u~Ns7Oa)Loa;4z|~4Dn9s;%(ZM083Z8LrNi8i635bC@jG`}JOjW_9Z5bY4d5O*&PVJ28VE(7%c9G5?-{1;AlLK6cKOEqx|NrzW<)_zHf4TDyc z#rnH%PK9(C)wJgqv#`0zfiHCm-dA5B;@gy5S;iGD8g zm*1={9_pkAl|!L)@YO$5$x>Tfj&W>Vi`V1+EUcEz6QztdXu&wLg(>lB)OrmCFol#{ zLeYK|S^%6T(sej;U4ravCiLI(CE3V_B+tJTN@uUndOf?u<7}&2{kxZbTYt7mgi8z! zid_SY5ggA%gqDp)N|vF>(G*e{P=SUN-5>#@;o{=@IBIt{%J6cah^CA7-A#3I(iiG? zpua`-VcN|k%Ryx`o6#_Q=HjsR-iYB~oZH+R?P;<>_=5@q)WMA|N#&|4U^Ta)3; z%MrjvJAdTuR5QKT-LFAx0)p|C=V;jh3)oUH^@PS0oyNX4H&)cWr`jC8RnuV@f;x+k z8#6h3>=YMj8(bEq)kA`>V1$YA?lNOhhAP*Ng+$`{-oBwS_j*&+)0L|`byEDk^@BR4 zx`MKZRu{g9V?l3wZ&U#ke8Mqh0?^f*Ej%JThl`jLUMN7*TIHe!1Ind0tY)8&iy!jf zF%kNAq;t_FnHQm2wd|8GV|Ca@%M^m4%Y!{zo#vZ%rd{);Sn~lBEV-E6J0vl*qDkA1&Hi@ z5N*Eb(oJt-BD%B|r*%G)lP8fVn|MS9f{H*@S{#0!Df)EI2(?BGKMRO%LbHm%?ORGN(HJM zzv9}ktFSGk?EOZEhLuc!wC~f4a3p~-w7oQfB!I-WVtOcUexKilob+i#}=WYnQ7F6>=mlsS#KUq9{@d9-uFpO7$b zJ)|-6$dAa?N+HB*aF01a!Poi?J%2ksnNCU4#7lZfh{&#i8^2qIu7kwdevIq`vC$XU zA95o$o7UZN^N^2co_qnCB^Tks*-f(hp2siF2@{aeYSDYbFDsaKAV#4gLyzjs7cH)U z&=WkAT}pwLdTWQj^Xjj+(-s$p?kT55jsBZwGoc=PrzqaLnEIgS_@$+EU*TVni* z%XG6#Yyqd0IqTg#v*kz>Zp&I(Z1CqbjWpd*9Eu(=3|+y1$XC{0k69vEy}{(56jQj3H= zXjVH&SWSV{U5qW}7TNbjWEQV?5iTHkpp$StXjVOOO3yY%3DSh+4N?F1$WdtLa@Fm# z_kX%<4@938CNw$nNI%Ke#Y!>nXn7I;MyA_iKFD%`{dy!sVdLrc-E@Aqy0i43ZzVmg zz2wTH-49{}_SDM!2#$4e=KYM(lEOZ|qjCO~!(r>33Ns#|?>SCJL1;zUtkiQM{yihc zQwI~}Y*-=K~RUA|IW2azVOd& zw9|{z-FW5iV$-aH;{7x;Y#b*X>boes-g<(4rc-^hTDyYg6Wa=BRm3l^nGX6bbp%x! z_v3HC0%3EO&YAE@-f&T!D9O%o+z5$Q{JMDIS?jNNjETEIUdgLQt`sxTQ->Z;c}Nj{ zPfq*c7lO+0!2x2N-`u4l@_f)X_=V+wGs+7~XzZ1q=OHRQ4hGP(qU+kJ^d5J}>($Mz zhK10oZ|oxDs=W`VnFVtVl$~i!ecQPNK}BoaEpsDxK}?`JU31j|JJ7`E$1A!x;Wtrt zebwB+PmJ9X0LydL7U`f2hU(EKjOBTAV1$5mIsp{2cRwOs%k`m(M+RdoGJ=aavbA@b zWM??X$q(j7(apmQd4f{b(uvSW9PM`4_BR0^f{1tGgDG(oz2hh{k`A?Ljrbjn0S(3cn543;=dQ&`u= zgXdWIRi&CuK)*2!(!tyn?8vmfH2ipukWcVOenEmws>R0YWbwaD^L=i}1|3ky*cAWP zE}j>1p)!+A2g|>P(Bp;o-W#~Z=?HAq*z~6Jl5@*h1l>*}twtMCVqKfWu9UBt532w{ z&M+@D_SCJb0)FgP@mZfH{^yRxyxVrNhu#Cc$*@noHa({vUEI zL^RRb_#AV%8uP*m2Ku!hZ~l^ofq`3;l}Jo{c1pRm4z8XR!3Ry8Np-0`?u$}Win>G< z%=<}S?^ssTmuYNwhdS%b2gKxXmcZSDsFerlCt#v2ze?~K`g$&yS5K{40~f2=w-{7{ z)~cKv0igKpZd2T?)~oj|y`r7y^AfuC#c-a-X~_*K3qbJ{W6k>K?|0g{<)If=zA$na zY-;J&UHcwKWq)cCDh=AYL6V){^$nkA)AV5@BGqeFn+O=<((C&q{4VY)nK0-M*A6AU zUq*2V02jm7xsxtek2Z35PJ`N^*LUu$>>5sVZG0M}!WMD8S6->UrROJ2Utb$)EF95M zhDPVGRR`5yFEH9^1LPD~g6-DIn@!E-B}Ud}=X8e`1Ymj<`qQqqSCa!oB8t8K zCGuVu{TN~P^bJK7s7>+DnuXAo=t%|6>jI6=WwtDxtRjw)M*>m!sc7k72p@HyO=X0C zD#}6TcJ2^tgQ?vnn>Q4~R?pLAA&A!U(L!kP5bd!ocWPBd=p=8!NJiQuSrhV#MAbFy z<6YRGzGceHmMnG&D(Thm{n6x8Pdus1=`;8FnDBdlfvCod27`4SupZH;M#c$KY+lzC zUN)N+$jB??=(qu;y)Cv#U+5dh9G{dnnUdk=%zu`)+oK=ywR_VVDx*KLCqaXsa_6vP zOMs`P=Cu6!^2c6Am#0wddXS#~*=15LN&WWgqR_eUnmLKZUbbkc_uaJxqx^8kXbN46 zI1+dpG}TPuH;9voPv-^C$9vctRM?P83R1pUGlWW(Un6|43A8(WgO^CLqOTR$Y%PxL z5`=YU3qaU6nfJ7YY2|{w@~20Y;GI^7;HzHh+g%CY#q%`ETBb$HEL*y}Jqvpw-y&;U z4U+5D%P6ugae8PZBwTO#j5gmb2CQaveaP{~6iw>-7J=eAF3F(|ISKIwbc>McaT~h) zvp7V~JQy|yr(cGG9|V|*EgkABgcM9A5;(T8K?pPDCpn~eh|TSmgfR|tEksW7`cK#Y z4;6~Xs1#()%lE@PRA~Q&kqwGIX-LruF9Mf?0SGP#qs%8ub!@qdl9ZBcU^PVG@VhdW zb?8UP3jUjkn{SukM;nTbL$%pfoZoWR!=jdek#la2VI5DJM@6n0Nx8EYC+f`*k^DG+jUI}FeN94h5};3=>Yp>I>EKVF4RIlyfra@;8HgHC z395;%NLQckG9BPLQ3*aFoY8^&&gg*8p$!c{ZA{4-liB+P_d7J5-aB70=T=fPrVxtZF!;gT9%(=Xz5BnH4eo1LNwjQ;b4uR|KW3@w2$Qd zoSR6{!7bK>O%X+|Hs-#S(@4_8XL39vNOuBJXY*sq8GOtH{MB>`Tom9Wfa2SL3}$}x zl9lc0FyseXtJMGLfp>g@@8sF$ya-x=Ph*9QaLR9RM&6!-*9(oZf52#T88>ajCN+*! z$IWKh9v7%2h7)r)13A1I&q~TXZ@>>sXbmdOe!mKC*}?QzAIp$h0Gg+xm80~Ed_Xug z5Oh-R&~+gqcM=AOZXO(AMR~z|RZ(0nV(%PwM+JnW-2TtNyaf@y2Jz5@Kgb3R^u3xQ z)^XGPXbZE6qF&zvgvqSipi}#weZesxwyWh}jFX!@W{QlYOjP%}pnvGCCtwGeZgUMVRnS3_TxEL^5_0pZ}ii8JCCtzcf z+YSA?83A~W6MRQ-LC>po$*S+;MN#3P6Nuttun8cxs}8~CbX4kCUTv9pGO2($tgX0M z=8on032H(2JO!&WVND1~sA^PCt+IQ;$to1*ieuSX+P5Cvu4YW2J|uT~1H?4EU35HG zL?w?e#o2p5B#K7wrl?FXtsTl`hjyb0NQH;5X=DtCR7SxrW8%^!Uiuq84-ZPx2VJEWdckQh!d7J(ilhlD z3qJ@&{)?>MGUqS z*WsM=)kXdNwH~x~JnJp?j?+~qRu3ZgLbwWdKdE4ZT~yyLslzhW<)+l)wFX^K?a+-Q zgrk_zbi@V3XB_$1 zFM6cqT6}0yJ%Rq`BTZCEwC9+^KX86u77?`kfC(y_Z@M-R^wMb(L}YqQ)+_<{u4Q1r zP!JA2!kKw*^$T?=Q`ILtyhwo|xRPAVFx=w|(%P?-+OaaVJIOuqDsP}6Miy$d$_&3% z!nX}LieONdt+EmY^Ep3~i0}Ensrh?^m9M|8cEjfcc9k5k=l`;P4$2J4_ukdw$e*>g zMbSAc0z+ECEkvr7(z5!FPDc&JyiwANC`Dmx){0hpC>A``CGf46d-v^C^z0!1zZTE` zWXNrCW=@WlC_B%lR4M!jNOhd z8h9TGCHM1iu3bYRE5jPLb%lZ&|Lp5To1|rsUZ_~J*Z}uJ@J79EL7ovgX$m5Nw_R4G zu*e9XAff?N<->1cqetJrQZUM87-t(HyprGQL;o)7Lvg9=t2^{(Vx+#&cgJY+X~`=Q z=>~|Y%n(^9oh#H(&K8m);dDo5pzVLto?WWtCOJ^`5EMZwz!u+BZWJ!}Ou!61*b9n{ z!6lSe0h2YG3m}s?&rSsQUIW+3Ma67^9Q6VZ^{R3vsm7l+~*nx znuz-M!OZ(=Kb_sra3LEj7%Le2%7I*^mpTOAivgzX4D@fY)ShU12ATFY-E+BK~{HX7@lK?j>%~|D$6(&;;#HtN0?WTDeMW^UB~?p zPIb6dx8B&GwcZoa4zq?y36q8=C7i4r_zT>z7zoY?x$n%Kt`8bE1I6g~X7Ga-0`#Z( z@;vu0&AW^WxF=YUY3RCAY7th(!{#3M>#QVbkr=k9PE})ixFr}zDU?d#5|DUc1WME&0WJ1>#6Vfim zIPdX>cY}mqX1&X@lcCw5^|6-G2gctm)KqBBnItJg_{$FWi|xO&W=@iTtG#zdo;z#d z$yY~xhwY5@x`3W@hvDzx2Wc3M?@}A$VZ>G~+kRFnIpPu=p&k7!)y!+5<8&SDV+X{f zq91Wtwu2T8<2iykfF_?m+O-2zgPo;o86_}Gi+b6k&4|xsz5@JQi8u}Nm@An-8krgw zMA|ZC44bs^0t_ev855l=9|5vA%u7KE?%F@yc}0dES2|Ko;#4-1A9lYV%Ss||biZxs z!EvD|mDYpRuKr>)E6u)8aT^eri8oKB;E7hrJS;3L1cf^3<>04*Nq{rI{gqz6c#F2m z6yp-0b>tY|i9YN9s;xz>YFTBf>8RZX`>j7rV!%~i5}cl9un;wQLqG9qEyVk+9TAgg3`BJW&C9<*gW6b8yMC3Sc(J1zGh13ZQa1BXwa1R1)aLdSv9er;|JoDn`B;q ztZU<Iy4+@q9;#q3&}7DQLXK#F@pF+_U2p6eKc&;1CC{jZDMM`oME|c zn6S_dw~z%|l}Y;C^UTUvCNMy%&Q(`r0aU=ZH@(Vq{1hAWVz^)4z`m(?Bg?hj@&;KH zDh0|B6ms42>ptp3ElisLbnz$l;eI2?%gHL!tUV7f2qN2bA)f#72>;;{>Y?%aMYi(d zSymAkW#Fg7UDPB`X5ggXTt+e;fcH2F&;wc3=&|cG4uSElpWe?~v`sK)nMjPiGI+9y zuor8Fq6W~~XN>PGfn&5Vfwloln)rJS0V zlfp&Ns(2&B;0eWuMVa|Je{mVH2yB~eo`jV)uW@;sjH;aQn~JJ^xBtl3J%r%*=K{i3X-;x^q~BNb5XhNWd_D7Dxqdd!>U?hg&x_`SOQFB zNfhhASp~4*bdF)K3=YIqhScwK`$bEJl@Nn(U^Dk2axC7T$rDUak2Bo<(b3>!uYcwz z-Md11ztqgkFC<{frswD?x*QEHhVmIS%amr8)SS{b?}_;<^#A|U`5OaFTTIDs1mMh~>=c_iiy(#P zobA!7?~D60coEA%$0>k@i0wGxB;N&pel=joDb=MFs3ljW75Dai_d$!95Cio0;`rtA z05H)OU>UmivX1V3U!|RyW&|BB~l(`SLgntw)a#gR~d*_AvzH6RZu7J zQ6}`dGAbo2#bfJ4W^v5IxT->r2COQbg?*G8ds zzg)^%_>Ro@rLAP-5QZSvqw%-jwR=2f4v&!_(?EM4iryWhJOmRy2GeIWZMb6l<>ke; zwq-a2qqU5;E*6q$%HqGT#y^(i#!)LkXc<|SxFE414DLK8lv5Pd;H4V64zMn68bVcnkh`x9GvY7j=dKHWS<~E zrR&!cdax8i+Z2*Fz=8rv^g4|q&E;x5>PoL;rte;;WXI>J;A)QA=U&**a}Z}Wf@wd$ z$TU=3-7!YE1IO2a8wm?t@+BwM6xw`DVD zfYxdsSF$17+S)JbyM;ltLysS!3q& zk~lL_3*O^hr}lS$j=c~Gf&ciQTEqOPm(gUhRJxUwM@jG3i6Abn-ev$fiQ>|FuM&q2 z+FVV94z>zrA?|9 zNwvJ*H?q3i%vbH@uG5G(DQw{HBvg!)cfB2Pu8|_xMC&5-7Y)a?XsOB~ zfvd3>cA9o>WjG183Dh0+H-r%-HB$a#dvxGcb*0mXVev0kB5`bNW9I|awULgbbZvz(U3<*v)Y>KQb9ZPtMWVsF)Mc%HJidb|RA6zD=dz&vTzOqg zq@=*=(k6GB3+;`-IIyX2kcGr`^R$BA>^K80hNCsG`Bn~NH_SXIdl*ODDVDU+D$ro6 zi3!GKwo{AhSE7Arr_AGbCI6=vdLR;7BSK|+$~X2Ahfcom_k1<=l~)J8H?h4Y^>i8~ z(S^oKi%-NxqbQ4)0+B0pFNxUBcijGJ&3VmQn?y}Xv;Yu4rwsArww#`3#WqCzpc>mU zvI(k`;ixR*FzR{cr@4GCbOXIlOI_6T2wPD^9H;6%&3D-`CwkTaxu*2Z7)zlE!1-E| zI89S@UB&?wzJJSr-lzAM-2Ntg@0UG-7OA+wPP0ahsY6+Fg*K=5b%vgG(*_>xt5Ib! zZ#V0j7rMgP919zk?|m#0n{o1QY+De2=KqZp$X)6lug8jNh+z0V;jw1$e%k29cI!tt zB#JdV#Z0}IpjX-4QCW>zu=8`)Mh9C){aQ-Vqx)c0 zi=@k)TL_aZH-Ba`$(zT<7MZ{)V>@xiLKq*;*sw3nydJ#+u0y4kgFl7{h54xYo{H)c-q6?x1DnCRFxL^|STy&w4 zh@W>7nNPgQZf~vrZGN0p5#Tye6g;(CtdU?5mYlWP)`^X)sjZ(N6v>z9>oxCuoTWRp zit5J;j4}%ANwtM|GatBgJG+L~wa>aj-LmX6Lcq*=1)%U`Gu1%?|CV=t!D>lXGGXfZz z>~FgF`e{V1Q;`pOe?z0{~4Ucuazgv-Sf>}BFVqLfGUAAq# zi~zdNja~P~ZQyQ@Gv%`g$(&m04y?!aqzqdJD*6`+LKAou*iUNF@Grp_sha&-5bH z^IwlynAgpqm^q-Qc18VF|39YQ!LQP=Ya6a6+jf&}V`{?GWZSlFO}6ctjGb-U*5n#=0lF_+0SD;Hp~A;JHEib0 z5U`Utj0hXO;PCtxjO&N@GR~l$w>&()o&1%#7isKz*+HchD6mbHYc;C*8k$3Opzo$K zlfGV4-Un<~d=X>FxT<-q?8&Gy0=?V4)^ZKRela){{4Z5VQW>m016~}^@E;i&&|TUH z@GwH+JP4@tWwUmaricQs!-Lisqmdr$`(euhvT1PurvG zm{FXjzs%Dbo9*XI)V_Bh8qc+bb}~*N{qTBhM*-1#do!V2*4|d1Vbi~5E(UiXcOSwS zg9|Hrvbgn}D-Bhpo9qj6r%*;$4&ZwD+4dTsLdowy8r98TQ5|>-#CVDv#28W*#_F`S z8ko;8Yeg@?x^s0&g4dZ4ef&I?xwvOoaf9%QF!=PK&>YKW!KJS5EMB^pJB^OL>r{xM)4QjB3Oq9msl4yhc*(vO*Cb!=fJPO zF*YloJ998zKkqCO@_+3QSywvz%kQsgv8wm^Uj>ybJ#V2g^nvQ(#WTCBx+IPl^FDw` z0kyd)8rB46_cWVgWtz02>KDpC^)=JM>fJuOYPukPITDfnH1OJI+R?Cfp_*3xhdvAP>wM-@D02JV;o+J z_{2)VC!(&S#<>vJHQ?I<$1gbP)#|?;Yo*#WO8WNHa(PYNAg(i|FLy^_T~D{}K%g@> zgFYfOySs9j@XF^b>i_bM5`B%nW~Q4GT=}zc)lRq&GpZb0f&8L_-&l z-jtT-2%v}8*W0bknSVlGyq9ehbK6J@cWW>NH0(Mfbu`cLjE$v8DuO7PlE@$35=@bL zY0*oq?NmvhW10&5sHKxBHlg)n`$}lvREKF)yv)0dTfaB;BBS9_%&AtEPFb`9xROwq zDEa)M4PQNPY0xX=D%d{F`^h%tjh~6Qu}|aEi$8~_nRm~kI~s<`?Nq08@H#7qU1KW< z4ILv{(Lq;M6)+*N5`i}on?7hJ%*!bZ`@Ipa+J+aM*?Nrt_#X0zEy;+^l@Q#rD3uXh z4Sd$pdy5Z*~<$>_9vta}( z6c2F$89^9zL$2P2OHOjLLWCHXT0}i_pCJbJ|6B}*EdkCrYZzmnGv$*4JAtGwK}I?} zUp2s>bF#p~q}2xeN*zbpi2^n7nNVOLP6FvgcBd1^g@0iNptX!;t|}Vr`cbf$jKpp{ zH{KSHU$wY8J&`h;$f+Jbf1B>eGG6KsTQ;FANk#TD^uy+T^yGI3RdwAQG26gNjQLhg zZgC9e{U3<&8JG%ZWow&5wvp~NqFl_m} zc7{A2ZsCiK5j!hn#1|WZTZ=3~*Y+VVzQQ`I$_#_rwZX>*-S*6SiNTGm*+2M!wq8$s z3|qV|bGV>Iilc3KQnIt5)zL!TcJgnJsv}0T3idg0Uf7KF1hYI6_AGkFuNqDa3kF_W z@x5KG%yt8?RSy&zJAuvGN=Y_nX?xk2$O> zw=@7z>Ppx@25n)t;tIB*WgzTErw;I4{c@ySDL#a~uikW5T>p657317o6FWf{;id#* z*^JfO@T#_rgBD#@oZOeHme?DYUvb#qP+UG{-v+8OGk%{{{HASD<{fp4xB2s3y6}4> z`M03&)6CSJFa|<9&Nr|DkhJI_42j+0gHaE;pGg-F7jJ^z{tpaU&R|@ezA^-S5NgPu z9CY7y9RLi|Ll4u#fA*^4?g#zhLNny(KD5k&-mlr;0GH-fW0WRM`n^u1lg2GUN1Vh3 zu*`aQ|FUZ6ez){GLI;$}FLUW&kDgD!WURr_TzpkgQJ2Pt30ns6CSvp+Ei1!ix$cLW z(6d|6`-c5m{lkoQ#QC9@E}6YC+@tOT<*rO`S^zV+K7@KgKoj9Rmli;s@RUIV0Sr~( zuhb_K;;f5JDLDiu>c=0xZp&SpkP3bqK%pj*RIlbM5$-zw%sja7 z5j1(&UW%@djt!kIsS7Vrij$2!W|+rjZCKj4^7ls0HyIut^D0CnlfCuW^#K$hML`Q$ ze|3&LzOPW#6YHfgltoDfQO$}Cw{*I`>@mCyt3zL~qX3eA#3G?gtCxolSNn2!o=_bl zfNrmbFG&13q_GA5?8fIox0`(NA@10?=-An^XVuu=Hr~9c;UT6ci#mWKpMkagWs2QV z-EtrO_PB;ekVT1+C!;8hL{n5CwJLPK_RahCGUR?Qr;x#m+(ox!s|EM`Yr$#;L8fMmqUg?tCqh1yD(vH&yyd;^NmoCEh`E~Vjhy^W>7g8)Yf6Vj7X!LGHE5= zZz_7G%Ojm58%GIO|6@Hv@o3UM~n9bOi|E z``CvP27GEs^r&ND20XWTsg10RhvhB`-RAkiZO)-ze+Ef;d9~mYa(9~MAESIuusHw> zoa_AZh(>hLRCEwF?=hG0WTuW+*Yd(6+6~%%G+4$bh_hzeQMTqvzZ%<-!Hrr6hx*f6 z+Y3B=@%{kh74?a9YBBLPr~%`3j!PU7V#cl_{~eufNFTUI^j1$eDL@5}k<5HKm)Z^S z_1~Q8XqlP#L3V8UDAYZ|oRDMzIqWup;#~V~KGV-+e(2SlotDZWz89^F3IB#D7f^h` zK!hS%5A?3&j7Wd?9qL2ttj+@ zNUR#|9>0-?JnP8KU&a^@HGnaVZ1*ET&)|lZe&s6y%?eg8w|4&I|B)4-vNN$-Ch-`} z5FoyOdlWT80}*F7(&+Y@!<#0~JWtrngx2{0b)$zi*U3E@b9^EoJH(a&Ka-o?A|hm; z0OmtxjT4@G4lWBKky<6~jp{~-Z`9}2_+tOukVY91bH*7at`DzTGoIr6&ve zjObGMvkV#kD?{!Vi*~Gafa?^x!;BdL=V`x(&QT6m3=?jVs594gdkc4i*H0V-0Wozf zrWKt!CMw$Pe%WAszJVR{LbA1v-kX=Q73!1#C7gHP4qsltQW6t&TrCLQH4!U z8I*kukQm_8pj2J2z+eaEeIy~SsET4nHs`xstbn~^G40uIW2n`|1N@(l7eMDLu$2KT zHYmXNDF!~wv_{{21sZ8t5+%_@Y! zG5`$**>zRl|0>@1%wlk3%{{ewq(;JvcYgc$0#anmZobD2`O|)2t4OfAWmR@l$Rqn} zoTuV&gqpM{JeVTxl6q*S`bKHn;aoQW<=_vF1aM1T9k>W%nUzk4IS?94Lu3c3SHtx( zt$)!ng2J^?6nDQm^Eg)b_I@wUFRa?^AYhc|?^XL& z>)*DqzMl1?dc%f2#49^gxd^;SKbMLUHGN0Wds`12%mPf|lt_A2|4p9tTu6#aSoLza z!_aSqPx#Bz@yCPw5BWG-#ML>N7oeS}*V(m)$3cps_ay*|Us&0(S5h#bpUsg8{zt_r z_pJ?D+1MC26|mo%9Xb0qG0owrXDtrAb-{%`U@59{IYD^i>#!hyN|I>;i0kv^H z+h14qIC-DaneLYuG90735^8?n#b7$);jZ8stO6_U%~I(#{L_s;^LkVd(ypN{pp7ky^C!U^cw%_kZjuGu-ydNzP4%5Lq&J8+{ zc4==dTj_2?DYLR@S1kqXcRZqc9@uT{e#AHnHe0sRC>`J(d&X0|idAeDqg!lx+8WIb z^HVE>X7_Mk@fEEHvW&2=!2WbpV%^j+QZzoq%5Gfg<+dc@+y;=CSvIV7J)K3r4XHod z{&L866VUqJ|D(HWy@H8dC)Vv}82=ZmXy!F^GTPgE1(aGfOsX94QHN890>UwHp*d6g z1!!H)tiB{Ns1c~(Z%U)m`O~JHPNEe}Hc(^=J|q|6Re+|ojsq(oeJ8*CaF@W{`T8G4 zO*uX=s_xem-R2f*3mH6t+?&hCs~%hc?fm+05?PPZO?US)qSY;%shA13=Pu2cF?k7F zkIqB3PN_?rvF|k3B{0azAA1NnZXwqx?}M1PgEGNx%p?*Oh_z#*=phY06>29*w|h@R zX}u&-kUkCvai*orB-9VQTN@~CbL>~*44th?vy_>5BTp0o$I$trG%xzlw^jc}a8DS$>} zO8VsFKrzPgh148>0T%2rHS`GkBpdAw>;+5UVhXFzHe$#;P%JjgvDYx>h73sub}1GnXKHaGzMY3T8+J-p>hfQQBId z%a_HvROL#ig!}j2D&ziM3XMf#lbB%a=3YyW>>i2!@BQsE7e`f^)eKQw*oB@x=#6uG zd1n0X2vTzZ_2;$ESi( zCUhIc94HL^?{g&?V6bN$p12CtCUnvz0jdbDET#L$|F?1YSL=5%5_*yFBO$(D8;r)| ziJ$7_SP$V#DfD@$wuZA8uS`C8i3EY|;Z30>c*^?6ULmS?>lB9`(_xdMicMXH-6TTt@Ja@Dp(MHy z>mk>x5A$aNX$q(xb~eJ?rK0ZL#b$qaj5dgIFNX4gA!i`x-pE2P(??r-!dq;PM=L3| zMjBBr!(Zsd7VG%o{+7AFuxZmF<=1|ZT!NMrK7c9~U49Urx7GJ59N0(g&-E~0_WOVj z0S@p^40Pd@i!2eXl2lT&^*+otYK(X62#5hAS52wt>+BaL#tLB$0SljDDwZ3q4mZVr4o zxc`6ceBg#GgceABRkN1v(m08HuiKFKE*ar!?h70ySAh-fZK4K5FDh4E_r(t~@ZDZ| zQPt(?4jm>}k8l+p11kaBh2q$^>tN`px;qkUxb?001izyNU$;Y%$>-e%9tYH`=)U}z z$^H{Gi>5E({1;JqS1poP_O5G6^Qb{o;L4czMof)eru9E&~INka~cP4N~ zld1x^TsV^-ocV`VZ#zD(z`t@7K`b2TO@c2Q7may9z?WdMEE4^uG`;Mm2f05ssScQ) z35#ZN75%~D#B>gREVWSmVM-ozBqanK6@f$QT7%#(Lp|cRRpySq7j1sM zp$R=%ciGdMr^xw$J4^o@xB5UuJWQaIQW`2NZ)W2}V|w^#0+b`XWg8*6J{F7K z@U5X`kz_`*iPA{^o6GaHZ}oDh`smlev8??|W~5z7RhL z&0{Wi@bDO6rXr17JA-*>XbjLG#v4fUutSS(&6+uG-F{oAY0U;I-%2bjlhcznrKZ1g z;;FFfZT{EW0K2n8mdBbgSLC9uM5eq*yymDx+OF?Sf68aT&en>GPTXFB1g?~=ovYyU zXN3h)eg1Wi-^~#Z0jwrFuZ>-x-h>c}fXp5i^PP{=^qj1(?vI&)ZxL=caaE4w2Ec+c zH~!_bt{hn|KPU9tGTJODV>SN}w)&Lv6Sm;Yw*r4wdPdJnee2;-M~F-kt@ecxvb$)XRD_C7;! z>l&KF;CD6jX@_k4puscrr*q`iLSLNSuI54j2XyFtt|G%C&hnF?bxn!LZe})fe%H)p ztWC!`g$)qW4L?8H;Va!jTpE!*)>cm#AKSUyLVFhV{B^ce+z3yl-@MU5_hsQ16M0wl zkdOrx zurR0_iY0`iwXbQce{KN8k7Sladrx84y-{!O@V9$jUhV6jUD!2?g>PJJ2U1y2n=%kC zLXaQXZmrte(9RjH%%eAN9n$t(UAF!yRcF9%3&nwL28V7VM!A5~)&&?<3?=3WWN`{m zYD(GLTyT3=LplOG&qXS?Wc8^A=+$y%wThxx-wxK1+BJEfk6-@tLaG_T_b@9%{0(3@;bSA`yaC$8D?*#xic8qeWV{iwq9Y>i|HNEE`c`eDY>ktQX zph{@K=N$}D?Vgr{CE@V{xhXcKu#uwA&#bVv%5o=(keF2I)EKS(*O-varQ|!T3IdjO zI7lDK_-5mfx0lSmn*B+ND{C!~B39`MJJqq0Lc^d(?T{u~cu@aMdCRH5Bfo@N#z`J$ z5YONsdmXmxDXJ2qUfv&Zs5G^W0I2Sn*r+B_d+By-u+Bpf|GPG~V&xA4`huRq`K$OF zj7S>D?pi)vQZbv>CvOF~7R|BB0Fj+%c9)95Mx;{_WZwIY@@o&>54zTpH`S@mpyAq&vG@1znf2>c zLR+0vS0`tr7xNeNM~|U31bSjdS$}gsU?i+)9EzYMAec#Dg!)31FGdV|oBdPdm*+3p z7Ig`;Re*kIBZbL>z@jaR@Tw&WNo*@>iq<(lFAluq5-4|^PC8sPM0Xx#8v*S1h;!&y z#%6dHilNDGc!eBoDvyLHNz(Pv+YMGg6EEI69K8f*&8&=CjfioTj_FE0;^T1~*~Kdx z-*tss4Dsbw$J<#_u=243Vnw27=xvn%OzA?1Tbj#va@$K@SvB|7sBOq+uJpVv$NPSyHFC9y@M*+kJi$Wa zS2a@GJ!~%6_1O&jy{!i&IEL4dkzTYOz<>M1hk&7e<@KcT5sXx;9?->R3qdWuU(vw^Jx6x^}z zX429N#a3-I7cMay_y)solP2;@(%UvLnts6~OOzrJ~A&Ed!`yL-PE>&+5yiLQ0BNVuu*5v5e}bJW z$_C?b@NH2HxLko*osUg6TLwcy)a3i{*B+iZ!A2>{^95)>d~q1sz=;~`l)#d_5-VQK zh*k#!5(mn6H}814xvpj)cueosV;C(o0yr&v!IZ^JYI$FVdA)BQ$#=tMGl*^>QzOGW zb&Heq_`768aB5pR=l`~SUWJ>P|0q6fQ@zcpLukH(XhAdq&+-O4k#SC@^pzpA+i!wT z-Qq@`e`0>z_!2)?@uwN_YihRoB4oH>9h9C7-9_juFp8wP$})Lq>8P*7Dr-+z|7x{P zw91wtrFoPa;fF`mac}TkQ)Kx-W>xII3fL8fG0n%+An8b>IB-$NS^Xw zWmfyjc+nQcyCK=W`lvAb9KH{-Tz;h$Rng+tsw$%hK(5~p2Dw4y|L`GLhZp6+tk-1_QuyKX5M&13UFgFW3ZOSa@WE0>RzUA zY?}2Fc7xsz!&TJVgN5ng$%2D6N-Epx_6 zwm6>QaJ=m^C$OV93?FCi=YXDG_Qm&Pm+9emSy?+%+H3(ZZ_0M!8;fLR8~&*_n%? z*!yt7^JS}%0$YUaY5#y|d3zqr9a0AYHCaBIVI79V*99iZt}@Sd@8fmK+!t{#ClHVdHN!(#nJX=^5BPP-O06F1NTuo;r% zzW^hZRQI3cyTR3fV9`wfxsGX^Ikmht@X(?i;i{8Om`l9NK}DbNuG+3&Bdr0OOSb-N zT|@2KN6KpR+Jf>XkuiQ=<>f0MylP-PMt|VmBkY2`yB!fRC1F|tnr$nG0l)(f2*#~o z5L7&M&(*r@uHAH#D4TN8rXP!Y_KRqUfILu6e96HMOz66+(`2(5tv#jeUXj^L5tfK< z^N^OSG5}U40GIuQ`MH>wh_>)^_9Su|t2i$*HV|S9oXPoQ)6l8?$H-zS_R`Ii1m##3 z^HjZr&dldx8AcPX*X=4Sb{RV{U{oCI@yUJ199)Tiq@`Gvv$%)Kbd34MDvTyQE6Mzm zTX8uFtnm7laXpAD>X%~fdx{J%zrW!mo6bZfn227Fd$D*Ax;_L+^8PHuFKn{FB*N>Z83J`Iw|))G2*(J2W9>e^cM4)?iXjb+u-CJ{An$=;{-KZz1Ui= zSwn*$&OEJ{@yBmQK}cCrRh+vQ(n*S3kP1G>jXW1#9lOTTmN9kA2&4W z;FJ#HKD&KP9p0p)g-uo`C@P0|HwR@$K%AZ|(62V8p2o)3h|P+?r&aH|sa&tZk=V-! zO@`&cAcQ+!eyRszDQz!GgPZ^ux-3>?&f?JaKG5cpRi1al3@HDnOEYA=q2TaGLrh$; z4YtyZz#E~+m`2#{-*Dl)x;v&3UTW)J2rdnAelSco_VCZPb$B{Tq!#R^$Y+W?%XqFc zfbH&ZBdEde-7)#i`9+x(P-u(GYnP0JU0+3L+u2`EYxkk+7 zk`)qOa@Rw_Sbnd~YGL1eId2qjMOX{+{UDLwxa)z}#?ixvcRe{phQO|S>TA!H#j=IW zaqywDzoU(|TsC#IkxCKKuFHtJ11<2nNV-{p7X|%m^GRvOr@f4k_Z>d zPk6XY*Tv$@e!)L|rR(_l&kgzUCS0m(5vDX_gwx@s+RlpfA7rAO^;ILg^{W zcLs*EDpSz?TkvBNkN*aq5DRxBNJeLGtSeDy*SDX2rzp+@u7kEgQR&48XbrbU#l*0> z^PcA!)mVWgTH(mmfh>YHaZr-jPp>Yz^66NQ&dzN9I1nz?(PvsZAiCV<6a0R49~&+Z zY@9cF@9IZo`|%{)b-c_q% zx)vQl*JK$wMznU57spqE5qYQ?O!B!9rS*HMjZsK$04rcHng{Kk$wxx32Tyu|Q(N`A zL}uZJhsZ0;YhStd(2JEf^>q~molpdv+{=6~`>?g8acuZTn80%((4w8%zS3QYK;PQg zO#@qT)P5xh_%Yc-WYxM2JXrNS7Y#EFb`o5Ly+jlUaNss9sm$y7Q=1}qWOBd;_7pm~ zW?m!W4qvskEabKd_r*fP_lIh>1XN5<*T8<&%>kW?v7NycQ%KMof4lAr?*P*46V~bC{=J>oFfv>+s;oDD)H;${Z7 z)(C+#T6{suz~xZUqH5AUYV?SHWn?jprKV03Sy$)JwJD4f(+O^bm;>HdzCbs1c?@6k zkiTPXl*u{~@@>&v)S;-oX*Y9g5ZBX}14M3|l?on)D; zVS?d_q`u`{o}sLt9yoJxjc}Hn7pV1N&v2B{bqdR-{$KWskpUdddHP_9g*$7ZaAy73 z)5PY&2`VBwQ) zy-3y4<+^(>wAYIT%5>slw&25L9PkUQDg8eC8cijU#Zqm5TJH$$KX#L+#9P<35n~#O z6N+x5PQ~7G_7J|joBndz)0FalQY$Dvp2iUGpolgroo%;K{);!E zwHFkOc)s3HDADx|G=j^|M{N+}vdqx4bDPaZIGV6Ky&J~xw-umEZ12N&x0#ScLn95dFjKi;iVg}9R{j!RT`^lr(IbA7qkGV!v;5ZD)5D=Gl(Yzqm-Q&(^K z+4i-eUt<(OkMk7>Py+NO>nj@!{ODIidG#rwEPjZUhqU&tdqUNQI>faJ1!7s0f`d}q zzW#B(FO_1=W!x4~NqGD)V~Z>mU1$AP$e;}i^X}75bJG6lO`a7l%UkX(W z>GJS&n+~qZY;w2o?h6`|6tIk>_=Ay5is$Z&@H(CW3PZkJ!2;OW=ZsLi8i6@T+_jwG z&olp(4tKGW1GLwctK9Hvw6Sah%57ft_(WlIj>cw?R&j_e>s$2l0QHtieMhtEv!2L= zzy{%u=lG$U$JT4T`E8Qv`oMVKP`XwE5pWCJNB;K=HKm4u7@#NJh~L!)O~=%74n?RQ?Am` z+9@)=8)p+Sd2RLfH3#i8CArm^?!NOliGo2ZshLM|1nG3YKj7bHe4Q~+I7q$oi;6}r zg?J#ZBypyDO*>I!-4eaiC>*5BJ{{)T1}wTH$)%%Za&1Nxz514n4ZT>tfF z9Pkvy+95F=&_;{I?Go}6O! zMg*OyKx6v*Z6}75wQew=aP~78V&R0F1FzmUc=_cREHb+}T0(&5{(fn`$CY1-Ya`d@ z!Y42N9mh+Pi~!41e~0Z;`AS3y2mUggJhv4Jdcp=(cEc8+#9(KakI;t3sn2Z9->Kn(<)wAVxfp)~q4-4+w}Fh{D~c^(MyYgOBXxe!ngEy@?1Ida1p+ zGk8Uk{dPOmvYs^R8L+y%FFO2B767KSBymNm_e)b0u(0HOgkJ%nXyEyOn)|LoK<-LM zNM4MUdD*zzkB%c~@`H|w1z)n@yx#`0&v(SAVSY@kTgwY<9?dt~&MT$cIoi6!#6?%RZM5(QIR333zYwtJh^rMj`+` zACTnDmNDz>S>L+?xMT_0r#jyUKK)%4U*E7=_tted9iZbr_w%+@o!wBK?clT&2n|O> z?+CM6_mG=CwzaS`6-ypVkR77OHeLdWHL|pbdHLv0U2VMR{h_Y#bFomiNMka zTw8jxfsgxso-qGcTHmFj+*NC>#%`0juc_`x+iuLg)yhJ&Jz-dg=!h*Z?ZmbpLo)3#4m)zfiRj}*_%rdt4%ip>}O7X$AZ>xPff8oOE${ftwu#uq&i3@&Uf zK*fI0+ogI>J%Wz$y{n$oeG2tc-e+IrO6h=f4qOKQC0bw)XF~PnP6)(Z_y&#asDU=` z7o*)FC8qChIsSx=9kGSMwgc9mPe7L7?e=~_UO<3G5ae$N7Ir>84NHs=PpcVW-!-Jn zW@7+8wO8Z5_qXZ|RHE6zqv;SJ>BxX|bCB3o?qVdk7(C~-V$tsuVre5haam?p- zx4;r1AN`v-Cw~gnL(~h;auNexv~_xG3v|!yau5;U=q}H&E;E9|pleyTt;>k5Pa&)u z5O0ZwI)adJ=lxj@>m))Nq%@qT31KmLVX-lH3LFyKGt6$*ITD%V<{L4lXOo zk18^<@8mUP4B!TO2ncivpNSLz=!eG2Y6`}PTgx`;v%(1+PP66KX8eWBu5zX|^g^)t z(x33&4W|9xj4FXph-Y?j>w6Si%^kMzO0y6;xT=-(p8Op59(R~G(Q|e&^LezX+)-JU znRSF{k;^7ZFf7X6z~=#i61zLtpJ_SX$FDYHN7wtb6f%KQnwyN~H;{M(9p+doDrv8# z6Pnm8rfNaBzzddocFaGPiqSFF=XA%9B>&N)nVmKX?S=ZiZ>X`HMcegaAKK&_(RV(hi2SKLpZ6~GdzZsv?}&=}0e2If+%PAbR4o}b zx}le<-<6|Z02tF3m$0c02y8Xd?iz%`={oXGKwt7vJj~2-^3gIow0f z2#vOZmyb8a?dh7XK%TmQkHwZi()jHY96uynDd^cPZP!N>qzeNar2zpr)DNb3uYt>=Q}DS zxLuIHO z{5~paj|=FhDn+5w_=b94{+$UL@Q?8>D5@##G&=*={&W|}#BgmOE8>%2v4QQ#mT=Gw z6Uc&VobkKerCF$v-mXZ@#fx3Kk;p3>&hx*ZMyhp47N$~Tr@ZyZ1R0AR4}m)wpM$C!L)WN zF)fK(a$lJPIE5Y51~-k46lC{6+}XY@#^n(v$@KLUH2@5lMe|R5)nDqt9w^1x4`6GO z$+~~2B6}lXE8GWee--GV`BN%#j7tY~v!-Gh`-6)vb9B%@dU*`$SOcZ8;oD$YxW`wr zLhku1U+4*??3=7)BUap+fJ^S`j*zM(lP0)^E0 zyET|L5=G*M143C3H!{0)eFLd$>Q*C_t>9218bk?5^{+?sO%l-;dtV3-5h2h`l1Eq$ z`*gTGFl@w%ql-jy)G59mop$Yf|$V&Y*Md{;jSZ>U== z{Z?!!?TQWg*AmiI3HgqYR3fmPng zZECo1hC{91=GduNRt))evZ7|utMTT9z`wdZ?VH|k`0+)?@xk(|OYQvu?E>ejl|E2* z6$jTl_Wd}e5Vv9RIIqKErYoUoNZ_DghJPW7;Ht$x?EkzoEXw?QpA0Cc2$vGqs+@Bu z@$f>~vaET-W%|GRPv{~L;Y+%9CcmT8_6Vz+MlHdbQIBA52JCsW zSx+vh9=6h})NlROFR3DiH9s>J(TO0gbuN@=*T_PBrkU{9zUOs}CBs6=?H5OX2W%Q1 zp+z&X5@bu?-Q3cWjhI8;1#xsfAg94xpE3*KmDtW>!{%A5tQ!6O>vX&p8l(z}WQ3^0 z|CRpjRN*Xi_4TuAYX-J{zdgMC`5#w6pu9AMQ0vW)AASTtI?Tcn3M(-OIz$)f>cr`_ zIDe;UJulOovxWRzZRm-%M;S#7cZU~{EVnzfEr$XjUIe~k+2&^3qME7wTACiXsMySs3 zyE_W>oOeni?tL@Yj}$}>A_g8#+1U4AX;t+jcp!g#4iWR?e%_W~P0Wp*}~*t8gw+ms^A%x6?Q_$a;u>tb1tF_}i1j zx^JZ`!1%;(5-lyQAx#W?JoIVUhVF6gB4{#<`&+AMqGW8TAWazhvJxqW&d`s!A>;;e z{W&75jxhcE*M0|h1qs)A*s%rGS4t52TQzyQRU z1v~Kn1|V9!wf&`JUTiv&5f|yb4??+}9ve9GyNIFX|IwTbOUBR02tJPubJ6|sLMmiC zkVIt!e5(eneUf%L3%ml}($T-#T3y6j&FtU7nG(KdTjw_tp-@4Nc&Me0y|W4aX#WGj zZ)D|Y{j}+G;D_{Ir2GG7f83iOXBn9v%0bEQ!X_6<+3ueV$=4G90b7iIk=7sS*T|t9 z$w`zQJc)q%o1hZu^{x??;cFDsRMha!Mxq0~u(Qk@FL7%Kx}bPNw?wUqLSlYJ!PkbvE%X1b+Zyj?W4=ZK|mm9)ol*c zNVlOGEN=>bSszJ9KyZwrfFoWebXYNI6&}a@~n^ah%TyXQ18m(Q9 ze9(EZ8mQZfkT%sGMR!W9gpk{%3?$pxMmGFS@kY*^<$Ogk0DEfC(f$?Y=%R2-&p8d|4LW_hp z5C)dbJY?UE=^b2Dpzy13wgNbh$1RzTpNHjcJ z4dbJoa`^ogQn>-4D1$a@(e-BbVKnp0%utdam~~qNfipkcc{EPbC%? zab=brD)-td$@(NP#~F4%)q|FQnH-b)_}f35G8*EUt7-a+E3 z2I1^Ho@asnMs;}(V2Gv(zwDaAxnmVqVg%s5;BZcc19AgHwevW4$x(w=ickvYEy}@- zX5lkfNMWFMQSArXe@t3$bA#JmoS_)2G&;*mt3nBZ4QLR&Sq%I_`j*|MRIQPz`_>R2 z5X0%uXhuOq?_er5N8LBrQN{W9^ST`*Ke>Q&k9dh}kMEy~*4aG%!FxXVq zc~0_nk|th`E2(DJ7p#(FSI%9&k#balJ;z9I*~((r*)U$H>86VtzSiwcjefsSDupp4 zMJJeRR&rHBn06;DiYx6d;1>@Ww{P)15NN`bVH}7|;H@#_Y-05r)}d)1cL~D-bV2ZI zJv5_%3?ErHiBMjyMmFAujbtBAF>)pHVCy<|&R8&C5i9@uCgVLJ4tb?CWN&G~w>vKY z#IFGld~i_+#GiPIbS7XBS%E9TD_|ld*>ajIB2hs8O*=^#OA=DKgE>zK9k&M9>`HB< z)yppr>uEi&92NH3gsqBN=}mW6-4@i-(Q{PJ!vS3hS0?9vy8kH~4w5opLmh!JQDD!C z6nK;-91+=Fw;^s>kq;X<3h&K+SY;bb^JH6n`Xvm~BIb)DDi~i~TQ_5MSLfFCK$%k?nR>I> z{fOSkwzc`}>CTJDLZPsv9!*zIu%kG$c1%f6FL37!c(}4`N4aT`dGD9S}XxTVS z$Nl45!Iy{&Ajd=4U;sc^K2N#AuOp%PYPL#=b}Zo>h-%!=i&+9f#Ry-Yll5`FmN-)> zU+5%1@`4FpGsDr+0>q!6CsJ~8R}}(%FH53##xf;ZVb?DzV zVDl={2$c1qqF2MRFVtXgurlqZga6sRA8V~|FoiT7a(jWIpH>So+Q8wh&)((khn zI){s5=Tv`?SjPK$&lB+yc(@c2^dMy$8M(Q|wjr=w9;&Uz0n)|Bt@Z?VG|IlAKAx`D z*h)TY+nM~##`C;ure0t7b;vMf{XBve$YkNL2fOa3H-FE$>HbmP*5N(+w-|5JL;@wl zWA?aPnPQZ7aS@`V>P>LoM2~Y72IhHgPJTmg6I?(qbzEAHoRm<#LO#HzxR}a5zqfsd zwwfm0e?2l*VvAe4k-3kR(jO zV$dwGT4R!vkHeut$>!?G{c`8PMHv+jFBk{5B-_Dwi5%4|8TzMNAigaxJ*u@{5Q1Q) zq=oKu^Jp`Ujlk?Kc$eVYSJBJfDb9T-ad=F0{M-s5Cv|JtQ*QX z14;s{ySXp*Yqwuv!JIu1miwP*8+x-!)aVmct)R9w`V0 z?3Gw_A$Rl}(>1*D^f=**r9|EZYefIP+v9HI_iY9pB8e0D5jywpQ2G}=G|Ruj|ML8V zd}m3?6z3y4QeORzVtoL&#`1QP48$X|3hwuQ!gV?TF zL|ReeS0LNaDLx@wm^8Ox5ZQ4d+05%bz|`Ha@8!EaY-C_@!HzFX0tZVw1hgy!*cR3&@!!)30S<*uBMIO6Gu2*Oq2CAEJ~t&D zbltS#2Ag8;DMFvC2^?zT+d8DJ43CubrAQ8mJ)gRE0n6QlAvCEjUOq=VDKjN0MCpxo zM2m5~PyG7Fg4dvOYuz>OEoObJ|6#Fp9Fg~vk`k7+79$Qm8gQ!PF{GQ<=E||EnQ;J} zbHB+=mE-NPZS2UFG4+x1s~KQ|JpPHvy7x`%1(xaGX;pjJ zOTeY-8pjQ;uIyNa-(I#lQz~Fhwir_yXYZ_!`#Bzs9=}8qF)#%Y6cSn}&91-w!fQ&c zN7@VwY}oO07)K%;xB^KKDM>9JlKDiL3+g8uYpu0kk*c3>>`ko z^t>5M6Z2G|%IS?-V=X`YK9jo6Ot-imB=0luFFVYdpVKNm{YuE4+n_ce+zDytU&i+6 z7dy(L8or9qeitnFaPf!c4d|O%gEWJ~0Lm1*c#Q%eqHjcT zo%2K-^>@ce>LJ(7pm7mj(CBseFP=iwpOSvGLkbAR-G$aN$8WEVG@nx4q`glspj*%+ zuE+$GQn!iekR^qGX!rh-I2aG|b&lf|Ie9^G-Jn!c&4t33pIzU5?|DysU)b|CWGfR5 zy2cSe!J7a15x_xaWnb{3kl@_5behU_)|pD-a{`1<%b8sdfAiQ#C%S9$?{>&LkMj;z zyW>&Nwv!FPi3R`2A(-8-EbbaPd0E+7z7P7kmm=f*?Fe0_p87l-6L?LXbOg66LQ0{&zKqtCPdK%4Cj}qgU-X-Wk5QgYRdFd{v-#mVXoaOa`ljXz0v)LZxX1h0jAoY4W@E+ zW7m$e8|xObZN8{2hb>#XKYnl=*LADyRz*S!3o%i83HMx72!4!y}8u0ul_7|7;ck0+xdi3|) z(xU3Xtgq+n>|hm_u4_;O=ngN~;bixF+j)=HwjhIHi_c+BN3LS_^gd3S9sS3| zA%zhMWc{#@X_Xeeup};-IEYv?_Y@<~Hi~+C&MKp@zOIUbA=?VVg_>>+$7+NK z+&swdGj1YKrf&W__lI;xzWadK8B!HH3al5dy$rHscz)tsV|N&shkk3NK`N)m;h5Y% z3GA&VdIfZv2G1Xe^k8w_&yOj&JPP9hUGSL zCcfJ!Md2V)*?BOR1OIZHsE`gWL4E;;K8hA|Q|d`A;mn6_)P0xlAqic8!9QK(%q_UM zBN2?vSFul>bm1h`!})I%B9sWuv}m)fc6cV(OISG5pX8(=3P&nzZ1Cr7P)rk{Ihgm) z8<+kn6ulS6pUoPKX|}c)j^Mi~lDF&zoBL*hOk3{+Hz-AF+4v;*s{Lg*z%wbk5R3*V z(|LI;!d508?2K$L7^89+T<;?eVW@82s;medNE;L2Z>ltmW7NpSyF7Pn`;tt(O2&=Q z=DV%+>7b|e4GcWDr`QjU|4NPsnLxe#Xos6I=SG=r4x7xHd9uy*RWeT1Q@xu!I5IWTIeTnVLI|aFq3QycESNS44hGa+)4cWiz(cBs zb+ZmG;dF3&!Wa$0?8c3>rTALRJKuELO23)cvqYLXDvomNhxE1i=GZ>!mLYAzSMnf9 zfnlqgi#Buqhc3{h`uHS|A9Xz1SD;isR!W=P@|pa4X0SOjX~yxsCOPzzli6A7=UN$S zxr!9(TRjv-RwD7vK2RSu(yrT9^{sE}i0d^Cp7=W(4R5w*&bHUP7&c3JTB{#A&Nhp$ z!UTbv+x2TFvrmd;qz23Uadn$Kvu@2-A;JUG6*y)vu09U0&2{2N^!}`CQ8L zB&zU0$q`N7j#)juj!;iON_e{S2H)Kb5l0U1*(p05jOk8*^@?+emCb|7t9G$hm5O6} zHmCLNNPjzo3Lsp6=$(wQIWb!GNn^ndNo!#nfRkT27K9+I9l#enc}hW%BzR*A#;9X0 zupcLaakL%Jv}Y@NPcNi={qbD*$I^}qan&aO5kllUe)~O)U=--mv3^Kf%Jz7V zQuDgoh?`wMEmnu#>K^mV%eZMN#0;;AKg0V+RW$&AlYDV@Uo zAT+>J)-zeHBk&SWtA1dJniU>$iUG^ko8LrCj0OK15goZ^1cM3Vqvm%8c{e#Ch$=OW zc0EY-6!gU^YIY_Gl1H5p)o!i@{iEuFQx>rr(s7Q&EW!YOFjT*|0%+J*N<(GcEKK7# zs7+`!IoLdfMKZeq+YdI#ZxEivR<-Ubm$PX5mYGJ*tE)JlH4I$Ww0#_&hg+7qvy>y7 z4IPp7-@We~AODe* zsaD==6lTh`6}ajSb#r}!^JU(QztHD|q51I_aUVkh4LX>uj@Ycm;P+$vF#xD9m~fD~ z84ltM8{G#*8rl125r;dd!c4l8#kvi!=z&9%!1r)a1!1wY`K9C5B&ma%qOIkAyw-() zHB&kMI1gzQqw<9dlxo`?Ok-CiCqPfzqLCV;{ zM0nd?SQ6*DOU-j;Fm?nJ_Hti6RJ_}|Ox;m2hdyYNqoDd9yUVzypJxkw(G-?A5z}ZXH6a4wH_TX^z zbT%o5>FleU4!_ zN+N!J-)S$>Ai;{67WUn_jM5P67Rs!Ra~-oM#HK%?2$aEfzERnHbKJ-fqN`wQqU55Z z!lQ*eu3xj5`wn!DaWN4yM`?nz7{dIBof@t^l41Z?#ST~?<&&NbL`K(8H&l;Qt3mvq zVm%X)7-$M>>IRwYvyUoFLb64pnds+rxHbK>nf=R?eMo3tU19yML!FwHwv}csd;P0U z^CII>Mdz>px&D4i&Zmr-R1lGaAEwuuOWJP!E^OLpCxxMPj9&EUf=o^Oqh2y^UW)FKGlLSE%1(pH@DW|WGwa~-Gk*13HhT( z{_5EkThxLbjfjOiXyuNDWh~}4p4!nawU|E`J&-Mgh-N@|H#RtZUyRlf}hB=>r=}R)eBgJ-ro#yv?#O5#R>(D&e!a zL)5QuH=TULE1%u&1wK_Mrz}dA5%}G+u3SRMl9kTIlT9f7nl%n}IN_b-$f;-ts0P{I z-xW=6`ki|efD`YpSTKf*a@uzG?}t#+^O=~-RlVB3TA*}5)U{?32(6TJI*d5XapIxu5=-+1g?A1?;4vkd_~yXd8Incflo~3vu*@f`m937c*UD?Wa}e?$Da*3Gy#! zP2{jDPHWJAurm91z`J>l_<~cmm&YJn<`did{G1?yoR`F;sZ56}o?Z)`gri2Atv>ym zELvD+STO>)XU@c<39zW74B8zW`5o`kXH>R=$sUp^SZ_uh8&KiAwe@5N((?Gs4Y_rZ z!nAS$_~W*wwyQ}vU97|1f-+d9dqd+lp!}ED5l4{tfG+%g7(1D?#q!CVd;|Fd$WEhV z5OFxvd)b>m1+7EjO*REfhd6&GQI6m+nK^Lut%akaZ8Ey1(}1SK7Y`jJX!3WQX0MnSnKIkPgh2fm&6G+|)}8-i ziz3>90NPRxbP+~+UyQK?he%vZOkkA)McgR()6X+Ntx`*P%&;Ze#3fBk3M=C9;#@H&u-$$SFH^J(NcX$F!q-Oj+f2CL*>Xf)jER+|h%x=Ub8wK>h>HHTfBo6Py9rEK|Y@fb@0Zc+;dHWR9#&|SH84u7()y(6(9gKucK)_}Q+d?l1 z#NiLu+qpiQG|}hqRXisUavlOSeINhet&I_11`c0*ANy+q?Rp*=pN|497Oj(53Q5Ek znHnO)MPEpgv+5@0Cbu;=?T?GQ8rUvm80ZY-5QTfCz2EJi)T&VD^UjI^H@GXJS1s?V zoPJ2>gB75AQ#)J8W6Wt2PH1wI=0hHS|AQ)fuCnK8Q%g6%n%Lm%iDRzxLC3I8V`pW4 zzMAk?>zvJ(;}d{AoVX?Gvfl4ZaQ(d>(H$~aNVIdk?_*aaI?z4-z>AG{WQHKX2$SNZ zkSgqY;dArmz7AzWJ?iyzE1H>E46Uk$BRyLF(Vgsd+_Wbf*2TG!NtM~v=Qnj_#a>km zC+F)MuR%Q>O->{XKaFEiHhjI`%i|HvVH)65!DJYTK%hTJRtJZd+1q&7!1q?0ZwS#K z8%sA-(~tk_!REil5`1D{)DN2!Bg#uipU$DVo-y(Kl1HU(aelw1}TG7&kw|t@5j6t`y(pDuFv_arU1FK1=SYzsdMcMqmbu0vv!RVFO|T8GZdk(-o>9%L z6H&`@zYz-LV8IpjY#!&`LQTZ3%RE}zb*M;0Anr^QUG*%gNeE&+`@`-f)7l-OibSlq zuJ)mx#I{)9H@7xGM}J6$*<%_B7lI{831r>}q4bmDz_X@ryrlKKwtq_R#E$p0G8o^O z!r7M8XBo!oHdz}<35;tE;!J@aXHD$~HilqdWHBxm*aSGy$y;L9$H5%GvtpT*$XeM1 zU>L4RqZAt+&0;Qj8r2w59sW#qT8DD-jbMqc=mFIZrUB9hc`{YsV4kuBa|Hy{k>Uq) z>Ef|iXM+}?g>cer6{x~hGd+G-4JyYwE6{E8jlUf5V|X%_6mv>NsbQx{K;r@a#Iz@> zBoKazyF?H}=0V5kiXk7~)Yuf{&8a%}q-MOq^~=;s_aUJpEr4c}|BiFEt4$~s4`&Yr z&B#DUz2sV;66{qoRjM!A3j+x_1|)-QYdP|D5gh7|-fB5POFn>DgM(<(ngU02WxXo% zZhG(EDeyquhM7>$vOrNxa^U!|>kV`3OitzAa6z%G>e9iUC^DC$>RzZ_b`b;CcQ>zH zKWQJa-iv__`yZHrLt!*sST0mD{=) zQ?Kegh!>h@3njU7*P3M9{JbM-FH247`5LW${o`QR${!tUU-Z9aHeBSO79|oj?bS25 zXEg2yXUrX{9lcXqD>nnhKxi?Qt*&z9;2>sg_f4vac7stdBNL}=qH}rBL7dGEC!$N6 za4wqxM#WjNmRgh6IJ@G8ZVqE*>J+sr$HZLw&_K_;JT9&BXPh%kJ?IB-cuE-YI}i#Q zgm?^NS~|~@Hfs4$`j=|Oy91cnNF(OkjTM_6J5zI$A@jtBTy_%W$QT#aeF?0J`?Q_w z<@71fDoR)v3SW^@(BO{ha(HAY_aZZ4(17Wq(nJb!vGb72xRDA?D3Yu0Z?Ce{*)ah@ z7##3^=Jjl&WbonydFJL25&Fj0Xg&svpB}hHeyl1~i2|v;r zz$Of#tZ?FU<6b#gul7fTDSI(NVlV&-z$OoanZslP33-|TVSXAm&+P~Sl3hG-;r^k3 z#yh-gGC!sR@epZG$r4FL6|o#*aY;BuY6%ix>TBY3wi*2Cxo2u@V8!ssvLQJ)~5ouSs25Gr?GxiIk?)dxcZz`y;at5Xit zaQEt>r%z9l84=+ykC*1#aB@ld&NLX3;H#}SQ5N;*?N_jkufVtIa*R6_s)>9PDY(8R z=Cy;o9zT>P?ZRJhGS+8Y#E>wRx`CnrSMG72F_#&4?-0KyH3U#nm7Ff7jGqfvLcO>ABPEL5b#VH6kSFLx%b*+rI^Fu%7VI zSVf76>{c!+SR`n6U~aJ^KtOW_HVIuW`LO9veha2)Cux(v!M>SZq)J-ASe-5`BUr#0wUtcvahrR!) zQZ1*_*OB2AZ*Lu5Goc=LA>ZG8OA+DQ2N@HDTeid?Ppyrve$mEGR}A z;+Coi;b+5Je^4^IhGbTox=vA2lHY~#t2o(0Sr|OyL{DgD26ao-9%C;CiQ!t-4Q$Q+ot@e214AC+|WtuMT z3JHJ-X$QWA*aq0KdzaXwKxy~C6Fn( z*)QzDDRn$FX14$-UqlhYa=oegZjr2F|m-Od~nt(%#AR6Q?vWa7=Tq5u3OqMPbWN6 zH;dHG__JSbs*Sn4A=@g6t3)qDLjc6gM{^hH_ReFMo)Cn;CxqUNah4|@J&*%n#y99v z414_3IMH>MIHy@cSa_vgq1*dkt=dJA5nlirtsugTJC<@SI~YdCwufL)jcDjyVxD4 zXF%jAbSVSNEru;2moA2nGruOZ{SVy{zWqNNC83(qh)|iQ;~1vOU|e<07CNR)4fgqD zC$>LIEq`yYHzqsxlmuPX9`kN>E+HpRhe#5W>DxyV`+G>uqee-}P?XMh0dYY};BmR> zn_hQu9|e+2CEzm*+tLCSml!o4-9Lt_K?nk*s5zo8R%TZ^(HdWX-{t=qzy2Am!ND3y zNA5S}zrQovFI|Mv`y$^%8O_&S@z+e%Y*Ze1=YBLqfzDsL=lXd2Z16Y?C4~M05i3Tz zH*xeB4|5z_o3%|PyiR=h=c1covZf2b;37i0e8Glxuv<8c)os>l9k?mNZh3M=&wiFG z4ayY~ihBsfhDi11tGef=KU-%=2d!(QlY`G(BzaKlki`Y}20L6PzdeZxNLW>+ z@$;;51^;gOSrLt009uR`@7+GM8^YH!?e~Bx%anT6^-i_&Ma#FIS{id=!>f#_e#rN4 znFXIeGNtJ4qw`YzW6eCuh0Y^6DvyO={qC|bqI$Wm5v^qfss#-JlNz zRG(Ogt-DvmHP-{TC&x}dncb6N6J|%T>(GidSr`ow9aIOXQRDCxg()MD2@nqBTnD{9 zBmh}JYYHnWD1M$fXKLr`yE|ctE7ln|aOU!1yXoDz|8xHR!ARw_54Q=N_LLHAe?gQQ zypBIDq~F!qeBq&jo#d0X8}Y|@A$YO&8iwaOgX+B+Oc-Ftfr9{#1gFv%z$j;`x2<7Uay3+;FTc;h zDKt};18imZ%oUl>Tt66C&*j<-nwj#?^Ks_>alyPT|3q*WQLgf57^7-8}S4 zzy)2(y7*C({q$lW_aPE%s0X5M*s|AjNdH61O9sBWkI7#w9g+)v$CXU9{@086pdcyE z&^HoQ&|#_Jg>9XmeP{1l02ZlYOh)YJWwY|rPtT!ZB{b52L?dlCLHp>i92cK!g%E;R zLOc*q7ly~`JV5OkoBkxAf<;xS2nYyx0r>ne zs1uD*$K3}=Q=YUIqNI^CzJk%{<-4NTJfT53q7`@YQSu}Zf`Mblj?o^<3cGumm5`X^ zz$ie6ebk~V!H+EnkBcCY$!fD5qZStGCkYTH6{?vlP6kMWiHU|d67Y8J{bco==ujbT zX&?45gHhWt59gEORO@LSTmbA>HDe-!;YJW^&r=;6i=2-$n^tYItj)TC_e;>-SbOjh zK?@t@=@VbXH?50HBt(68gSF@KyK-U6>yDC;POuje&>gBTP56fCf;*FChrjFV0LH~< z6?D(p^=ds;=yZ!j6EUKSIZMuxIiT+gVy?mN;~=<&&I8g9PZ@2`2zQnoOfi{7Z}hUz z1+kUMlud>pn^%L}-%~}D`N=$;>z0diH?h5E#jms7aFn^O~b9S9s<|-V?Bp$u}SZK(=`3&yX?K z`=znn+TDm8lk_0@p8JNHq&jwImB`E*x^_$;H9s?e&gJns>i<#ifDa2pNPh&Xtd@qd zL*8-jy0as#ZT_M)S~{a%Xp_}7gQ(#|HnX!a#)`Nd9vP}u#b*E5Q3?D#f7Y7#6lfpi z454laPjG*+qt}83nK@B&dqK*00g^T zln@^i7GW1_kb+zh7mu}@)-+Bl(nZRuI9A^9vJ5xC)KIzKM6SG{d)0~qdo5Y;dPfK0O>epA&weIt{{ z{Yb__&Uy-l2ucj6d6N(ev=pJ!HI4n{`nt@~kjc1vg_W}+NEI;W5zE<((k#eLIlMwL zIDxi1$=X8qEF)g_BiVBzfoEn)x@yNc=2{x!8#cX1KABC(H znF-u%1l5=Z{m>NfrFh)9iIYM^^=?Wgu4XfHfD?eW=`?nD=J1tO0S1!tt_Kn}PMS*O zQETPV=@Sm97OagpcN+S$vZU#iskV&D&AW*fG{Slom$%kO_n-`nz_%t=rW!-4na^4G12} zt@)+fL(z};`?6qa2|LugvR(EFKUTCt25LvnOd+fZoSf{;Z+M_nVm~7IAJ22&HZxyI z^c|nl74j~ev6~oVB}HB8*JFh2&;Sb$NBmj_=f`S&soc%>IsA?xw?*U?bMC|f@ydh) zW`L-6>~n4mwi&yu8Eabrw&W}-qsxvBGk#QEv}AuRXZNNKh){7*NAw|Ey_-Xj{A74i@QR)ZGGci8%Iuaq=0+NhrEt zO#~DrLs!!xw)Ewjn={NkQedPV&<~pur3W0y%LK>knqp3n+$l^<&l5m3sDi^R5}i0F zIeMyh(l!DO|NPzXxjP%Lqnmr`CudERChwN|P1~epx)7a0-Ac{IFe6QP%N6Z&{ir6>;? z`5hU&)vnK)@0}mh-tS$P-tdG_fMx$EDuW@*+wGYs?E$$@&ApC;k>KO4yK8w-gQ``_P z5%5rOTcl+dp$eB`J>^^zSHwiKXXmRqKEm+0l|dF}V`m7@dR-6TL>vfH8=WG2ijUsQ z-FF-X4WY@=;gi&l)XZDIMc^CWD331ScCUz0X;a!w`t0e+&SSAOaK#mH+;sfv?zr}> zUN$2BWj#a!fy=rJnpINosdA~m5-j%sIA`>ZS98&D+-*&j4d38mcPc+)GT8p#TNcq z-l$zjQb~$V&4k>S-iyL=Sr zy@&CH;0GfDjql$fL(u}0RiK@VezhFO#gMbK8%H-%2-`r)Zpt5#xmj1hkz+#stB-RO zi*w@~A8%}1Z#;}~qCbG<|JR5(%md?~4{}&s=0OH0T%+GCdFNZwX9rGT6G{ho)`#Uv zIEb@E3P%0tK?$!PU$h8r|xXr3MD9i3;2twXv{@s98}B5_~ic zSj9|-Zi)6v8lY7DfqxT;ErN(~_QtPg&8vJLvCxq;QG2JPK2@6fmdX@yfbf^`1lB?i zHLK=w7xMu$@_Zc16Is*3zI7iV&Ig%eOB2&zp)7BQ*n6DcOoQ638uKo1UXVVfjKfd9 ze-e4Ed5p?oqlz0vsu4t_F2UlN8P_#Oooi7`d)tUB-nB?wd9!pRxA3RkM54#>0vou< zbh(&rlMV>5n0MLXOw~%Ly^clun*FkT*WFwzHwcbf-(T}2k)8z?(|%U5HS5dlE}`;1a(x#h$ZDsQ!&ba(s{g94* z9p&>}d|@wQk--G>cB!9DmSZ*hCkLX7Ipa4w==MH+NpIVJzY6}}hzXF|e~Ju<5yH*f zsra6Rua}0*kuoX*SWF07lE%=3Labee{Fsk|!cI_3y zBwzvGTtWvx8$Q2}LwYSH9;i`zRPuYeXiRyJ2~h#kA+ofTLW-4|!JO@E43&wHym=IK z7(SInLUM&2tdf+AcJaXIfWT{JOH>LX=`syT93dyWvExSwoJu*b|ZSF zYTgig8Zo8l2;{6EVYoD?tS{R3qyw}#O>k6J!rN*tqJ#N?ukx*C?A?LU(icvUFL*9; z8$=THv_4WYI=@nuAk1Y2E+IG}JBvY%X(WIsN^qcn_-Uja#0VDbEGF#mScNBHWBrg` z<=0(v2~68mk14f7Bi>tID#Md)N2b+Q${jM{FVC(hRT87vw+@<2@f*XcBuUl3se4ik_!T#0 zbaN$xEdp&+K7s=Oj@@wBl@|*D8_{XM`TpMo703htW0hHj4Ub5E2!VElfR(c}oo>eK z3$irpSZ*{d8eo&+++WOWS|$J?t=AB57?AwS=Pd6`fdfOZGU3@ zk!$yy(^j8ESR9bpW}XY9*`~u4rXJ?`R~^^+5v|`v_<&bG_dNdIV1wg%F48l~^B{rJ zAeBK>vKk?mV>Z=a3M)Qt1xj@W?Gkbl2&)Ofc&QJfl7Pkj20NlM ze%12X4&ybIH@WW|f_$ZHR5jeK-K}H|0j;t-6(o)C4IG{_gYM#;_Pc$N;Es+ROM6iQYK)Iml@M(jiC!^eYVPO9wJoay*lt2tH{8#R(lVQR;mWjwWQMKS+YkfX|89W}sNu zSQbAUpIa4lN-nBVc~S+{0B{=EV&uxe$w}rZ=OwF)?}=}l({qGR_#;FudEd?i{48t` zg${-JMaqWzqW!d6G_CUi&c^2K8*NJKN;dFXOjp52@Cq;0pWtkl`E;5l6f2VVc+rG7 zj}UV-2bc)Cr2aunHDcX04iH_sbzc&YSwAN#toa9yYtBs5^Cj+4j@JExSO=ELp(HOw zn|h0kYwpTJ14I)rjAxe=N9_n>IP&=xpmD>tm8mz-#+Z^Bny&4A@p8KM_<>GuI3H;L zU#a|`%GnF@k058HmLL&K4*|!KuqFu>9}WB+a!sUdz-KGMEF5w~snr;P<{sy6qo|Nei?;%@V zv?7U&kStMbyCgd%4N8il!%WWiV16!{;OOMOX%73a9@_%c&c*+%=o0TxNP71kd6T+V z!{M2?z>PUK8y1qov7anq^){OKhT%w*NE4M;&lEA8j#^JJ7GhsFv6(~&I>-X(5?npc zcBuVpy>O*d%*5X#NT{10iEVKzj5hIX#yE&~Kx2RsKfh8r#K8*DupIzw(IJAmWH7{0 z&;6Hr$&SHnDAgm|7w`p>{mTfJWFeKo4JDZTW=$mwEB^=p7mZ@!AI$x(y~bSs@d7{{ zUdCC;@)PsZSsGIwlM^|Rg@=W}(rkLpOBwJ4e@S#JhZjIb6+kOum^uR83y3Y+#vey4 zr5_cO*adMRmFA|60`&s{s|{^{_PRHn_Z&a7{#nDte)!`<`H45dUVIb@sQ?!>b|VlF zVlw5)RA|*KyZ6)1&i%e0g_j}$X(We%%`gcFCM>rllIb>I9dLa<`cw=*lPtonrfOO@ zVZ6;p5cW|cmZ=KjXHsRE!d!%}Jig+~@U$7BsV+sJ6ddQJD;14>BP8z99lQdR)y(IH_BuD z(Fg}D7l*`uI@TcEFzf45?XWBxrLuGC9B@Wapr~{4+LxZCT<4Bz)P}A{`-im4;r(QV zt0dHJaMFyZ`!S9J%O34XOTy3F*I*0D3U={b?0q|OIuYv=Sj05+KfPce69JeG@zYj1 zA}Bw?pq;0>D`0ue7E(Gw0w&ljrcSr^amr3GwA#JF>UKE-5g2>)qkrgELYCfV31MIa zCGtD{oeALT;jcYs3@04*@eg-5+s&*vB)%c(hdX2;f;Lpv9%{lW1j|}!I>tVclF3Da z7ZVm9I@|CM2P@o(nz5sx-tuIbY!RX3d82Z-mzNDO22{E7CyimxADdJDdMm97-AP)F znc7WcHRFW&oh;sXkt@UmL`{l|sn+U3a#d5^i+zU^sCE>B`3Tf32s=L+q0M115C1(O z8Xb=GHBtELyB@zCchd^=A#7*zXjJ5Zl6#2S>oKSJc$eO$s%gejf`g*E9mG@CrPiN} z4w;3!oHiq3hxdi%>6H``U#vMkJ}k$~O_&6Q)T#Pc;ADvaCxokTCBpVV)3D&|2Tnjw zO#~qnbzmcRG`vvGOxw&s0Ji9zQJ)0N5iW#>*-K*K?#{+3Ov^~9#G)Ma+w#4>pAI!_zq%HvB}bOQ{Z;~0XjV#d@Zbc$1n*8F^34r6(8{Y8ryg5$iqoJ?Q8Cw6 zna`h|p8X$(3~8csq|sw)umbt!-L0Ds_SP14;kY@btQP;QXCA{k=^m4sB`{7OwWnB= z2=Qq^^nBjQxu{t@J|=qtc*Pacd=%s69<5cWRU*Eh_ZJqn2-_)7_a9k_Y$w3TT<;l(5e7WBpDhjCLYWhcL)Z!m|=j{fJBu>qQkpz6p$Dh7!)qQ zTIMMn7XU5}4PA|^1uBJW9W)M(eX>QQi-)GS50#EshchmcJ9aB6vj3ewsZGNVDaAU^=)8YRXWgR$0o0kcWR-iHKtci1^x%jB(m< ztlT!CmsSiX8K^S6-r_SKp#P&;pLdi;`tS;oDvG;!58ah%~X-y=%V5r z4zu#F$e!J;JuGHP{*FRVKf!4gG3grh@U2z?y~o+ch2W^y$LHc>kHSXHXe`=Wsbo3g zEg?osfO>kG^5mXbw2xrq`b852s}~5&q^NZW0kQ<7i|5>9nvq`zPQNtb${lhv_WC1_ z>Vi-7#DrDg+8@~;)&VKHnO2);(q>cJQ5;A)xKkQ6A{1H>3s3A-O^#5DeMZ0lG-$#| zleJjh$Oiv931s1CiT{7>{!h^Q?xK>Q6og{b`RQYclr)GV^o59@+%gt>JvDxte|0}p zxFNLiOP&qCBS1wAgQH4zQ;nY3+x2IIm}q3`J9pg3ITR(Q`r>*i=;)6aB^8*WzI|bK zgR}BX|KXiO#3fsV%*fYnA*~ch3PDQAHS@Fqm(iA2^>ol1d!KH$rV|-L8O@tbX_Jg= zBOl*omcm=(AA^Gq$8xJf8)OZ~vEadXGoV$dO%b5zNJ3b%rm51+%OstYU5H<`KEv5Rqt>5!BT4uMl}q zPZ6y4VOq-^s!)7{lNQYD%{V^xP$<8wNYz713N-4dU?UhA$#KRg zr}jkvN^q^(?tf?tv9t%%PEjB9Nm^t?E4bo#tb88^6OHP#k37r8Wzgxjrv~Bg@>I2t zB_kFeyaVT*pSIn&?>n>u_i?fdm>@+>wt>@rFzpB?lsjk;0vT+U8TY`$Zen*SIdO5M z`XcR7hg>HID)C7LaNsO6DYDviGPTK^0OGoMHM(Ms10mon#ur8H=jEqi$7VXeQ6y9LJ?z7sM1v;fL z3@8VDxrVjZK-rMyCU?vn_JrvGd4Ag_X_m#8xNtvYNu z-PvYS(}o|!t4YMjdU=NGO&=J(xj^q6{8Z|Y1f9LoTCm6aZO@6jftHq&LGmXusN_w# zP|*vD;jl18s{~4#m?}snS7H#i&JcA0aKv~24zn51j%1gYmlxb2+xZ&}MJHtk$*>Gg_#p(Kh%p>*^*?QzY@zWM=`1iN04f*rgggIHP0v4QGWjiCDZ zkByn~nIr47$`zXg4BSC8=VxG)UV|?2`Fh;ZO&m-@nxjJ?PhQGyY?b*QUIwryfo32T z+cN|LQu8lZ%(K2mlEnAQP30=Qf+$X;;I*Uu&Ox?AW#W(=3fagDzH_OgwBO!}=x9pEoF>Ds<3IaVZiW@ayuJ1&<#nm_$5M)GvaL4*Dg(KaE@hmQZWg=c?E~Dl zHs#hoq;UF~jd@jIKcZmtWO(Y6&|E4m1oh(cwmX!DuA^W6gA@PX+k5{*vL6Dv;Oa@0 z+&^yX7}lim;b5+I+v>q5_x#{+OIDm(4Uyw= zJ-QKdnXcOYiN6PVa;YoZq4mk;1&U&#WxG1i`{~i4jq5!BqdU^JcE@MrhsEWdIj(Q# zh}KH`M6ObKZoWwCQ!D2(vB%pT$0*@?j9fkg1fsr!9BRU zLvVMu;O(Wwkysem?1HUBwY+CD^> zYcz@Q?xUJP@xM{gz5}F>f+)Lu0T%p(3TJ|;{_H&X;(1ca71A?yE5zB32X;N6>vPyj zP#-XXj6yG8A6~4Sw+f2#b|3tWwNl9KQ#N8Kg0R3sYs>Y1=xJ%U+q;;N`TCKrs$wg< zdFy7KP_9#{UE9Jn1W@JUnC==r9`d&;zZGLmgInQzvwP|NoeXDxqW>!$7W`!J0s44{L`AB^Lld-VF`gV_FOyGa2t-!SObIH@R@FnPNrzQv7!(Wj`ycB{ z#h=AU0-quSXo|ApGcyFdp4LF)LhVitmp3I||31zC$!7wy$k3|VG~~yBin(V|TcyN1 z4a#w!PJKu&*OcZowsuA&S8nhlBhVIQHM1LWOvvIII=_Pd8HjeVJB(||=Bx2v@XCMg z9=K2AnF&dL6$-y8*CRm-uv#)z3kVtfOX^)Q@4xrp`eV97iOd!byr=UH&WDHf|N8R( zJZ^1JlCj2Uqm2mRI|&Gyq26t7>c2byi#_V4Pb~38 zJcU-VuKaI3{!eAIwd#4rX8CQR~Jae{1W^}y3hn^Nr|{B0-oqG{!p8bhsi$uNQ) zxa{pYR5D+BeBCPKYgx&dICJrEC>5O(*s|u_yBdrMy|j`lo5an_t;q?brK+nJk311> zbG?&e>=m4PU$``jDqm%xe<-B?6WBeWAt4`95u(NEFzRDN|K*%zr|*jm6yy|BZ&{ZKIOFd<=I0WKh3CWOYKkNU8id?B5VveT zn739ZJ{S|*d@rpTsE9VuYI?gVa#A?B`v%B;^gKsV0fCIaKkc`o09$iy8&@Y>AOlhF zYT&AM;~jU~Z631cn~9lhXN2rGE9s4uty0!7D@ry#l|nC*@j};4>N#;pFy zfp}|iYPrK=FS?B_)9Jp~pdv_LKaarLiY4w03()`Rl3RxbPRjveb8>h7wWBlD%X#PQ z;@ZOJ-)G^c7`mmUb;H?4nb4(YE%EU%C1p-aUR?vydS5S?ULb2=ipQJEK2C(&FhLhM z-Lo*s;F??1O4^BO8WR(_9*628OR_*t@-7hQ`L8-{$Kk0oECnGbiY-YBN6I`=`d&;!+HXfSRo6_cI^rwFB z$^||0>!bd~A>;!XDGRSU1S?7rz8MY>%pCHo;`=aKp#E52kk~DskJeZz7|ekjQW8Th z97i*qVLtEdQ6oBw=$GDM1^8;F)AB<8=HJu&*ZDt%g054_%p_pOK+w`*l$2;2o5SL0 zZedk&VXMby4l$Rc3~A7849%1~AFKCacQu8t{u?eLkko)Wy_Ftk2Ux{ymVg6RG2&3H znfViVHoqGSV5`qA%fE##Y}{u9k6v$Ge)SO?*$mFr3B9a+d;$hDL;jwa@CaqKs+r%W zK62@FuKl^i*nULdP0J9;{GKW4z1~a6XP8aIrq(lBi%}wMmh>r9Z*(p?Bdn2g;UlF0$RPJ%E_~L)(&_seMkC*q^o(#rZU+ z{I1%+KLwMLG)=?l5Q{lSRkVVKopK+o-N2`I4dCJqR_lXGIN%}#=y4Xs>>q+T$E9Ra z>^_|;vG&k>&I3|^`VApy`f(3aAj188)>>YvKCwgA_x0o)*)7key7Tgfooc7`m(4bh z>m>Ql;~VSG$j2JhD!K42TV36$wVZoLXia*1OXKA@9)nS_Dt65#)_K7R8!v0x0@z^< z*35W!@BZAY<#3tIPVGw+6x(=R&0)ZwwdcydP(jW&iY03G5AD%`Q1B-fsTHnbGo#wf{HVa7WBSonL6Vzxh^!TmU_X90acP!bAyiQre$@tZz0!;(8uO!mmPS@${@ATxv8$#3A| zYhS1AIk$3VS!Za+o|GD_5A`d8x0Z+SkW-nBZ4p6vD;FD`!rleG?V6^|fl`heEzDlo zl-U5E-}RN-(^d@q&)j9^tiUx#3KD+DJ4LKeZ&7Gm5-g(DWkYOeJ8E;C!Rz71;GNqX z8-BQ>FJ8a6C`s04Mf2#3bP*#ua^gGd1>dYh$Q}L1kae$#d=Ar@*2&t+H~W#jMLzC> zw*Qy5|9>wa;y@tcSx0kI3xHA?X>|A@TPTCkWuv$! zihsH9jsH?)O|g>MvYHJ#8<=&Rj3wFMv|QvLB~WEZWlo@5-4}oY3vTv%lDO*<(S+t@I{%)fY@iBFN+ps$IvpQ=+oAj1{3Y499(A^=%asMCRN@onF>8Mu5WSXC zT^R#1tpTPfj8mN6aNDe@+w z_&Rx7j7>24bmYgOsM@9%-EW`XJNItgTQr%v#?#GgOR&U8n?PZY133G}V`dZXVC(sf zw+Noiop$N)XLnNcw%*-gU)wfT;J?$3_bkYYY&PIW>C&EbtFG@g0Tg9SQ`sDj&ueSk z>Ya}O8(B$4|0743UU{8$qbeih&fjND|9&aa>;kDRBge1N_m(*!a3dmosAwh@c%HPr z2fy3*%^`xTB`~dz|5M44+D47Oc8ftTyUE-A6@?odtW7o1ZKLX^iWwvzslWdp6lAHn z+5B@hgjhdADS<3zz)&3SsmM$CXLq9>OD`|(Q_BF@k{Y9*yaoN2yNz(C{x8>*?)j}_ z7^?J7_oqRMx>~~*rbS@l7ceB4l&Hmm^t{ESs2Yvo(0!IfhBiPaH$G>AbOsc~ss!BZ z?y$u6;(`9Lwq($(Y+M#6%xC-d92W-&Htmj(VIRkLNMQvhrR-&QUq2RiUqo4TItp26 zt*%XmersCI{b|0~b7$L{qN??D%cu%L70GM4=9D^kA^&80ubKC9A|hanN@U-7w#@Bw zuyo>nHc8=ACQ2iOE!((#U#|Z&NJ`Q`OA@UkBS8N>gSEn7ZHORbm?{0`o|P4_`DQ-m zj19Ty9o8LwT$n)tk-qgC3GgpkgY9CbcZQmY*VI!RAo~t9r{{jcFnlTvg4d#2!W7kZ zkQ~zNx^rQY#>r2TpEkq!wZUv=TtS^U#he*IdcAG7wa?zb*UKRF^`(#+R|H zD@sFl@bfjF$mhmAt(f9+2wMJPLa~Ha0?~}mCKXvgZ@1?nb*Qys6?}=%4IeR#@HqDU zA6nx8b0l^7NM=OV0f*yE7U0k~?+w432@L41cH3}(l#NC>9b6V#EG;e2uq`iJ7AjMHyT`r?pUfx)PE4Gg{JF4r(V zU|k$m#OR{V`iMokXmG-g5Tq2ZT{$zX|>>@R3ht8XG)cg01s4m0g#R3CE@+o5$y(-~Qy> zx~VcdR-zAr4E3D^hC>~6A^j!hZoKyaR|Y(1Qr*%g=U~X>@98(RuVU?96pBXf3n7F9 z=Lw6L%7hK5)4yw`IYiQTk(n~PCyANk6?G=HOz3>Te4n&|WIF5+dI751zmlQ~3L3uc z8wgp(k;DP{H@H`{Zk4yRzZ>d?p)`RmgTatz4^(spV+d;PBmiWwFnvOkG79QEX923l zLE;gc274a5#AU~M-guK*CV%BDTky?&Gd+zb=iK3)aA?03Tm!f-|2(;63X8>8l( zHHthIQ9_y*^l+@STaPZW2}dNTY0*u#TxQRQkZRKN zTtp+fRq<6}qZ*c^quq-H6altH*dxpabq+{z+AqkR1G9jNakFND66h+ z>}V3yc?=RXu=%J9+qIglT*|&`a*We7<{{s!CQ@mWoDOmImtst5HTzNsu5{z=O*3$d z><><^kkh!GYmXR3;0-H)tG4*^63@!y?GO$Q{Fjp5#zw#OVKv#;nHlcyA2*M}!7x-e zZ4C{)^GtI_wz$pL5H1N@3bMi*9T%&c4;zHV1}x&Ix+77Rp*-%8CLmq$2KnQgP6>IZ ztI?R>t3H8B7|*F=%sgYwCE^AN^=LlLgqZ##xKW}ni7<~C(qsOA6v)RCkC z*6qfe3syc4X*VotNCfk3hugB5u5;cjP?=S zUg`tBs3-B+uV)c(sSaRAxOT!k4_`k)ghYU55nsz?p1?Qt?or`W7}r`pFSqnhOCW@a z#<#%mE66i1EEo`2M$ESyN$6MG4Y8k39O@fIl^THbjoCi|H6Ga)i`2g!fLCf2jiOmW z;tjh<3z~w)s7{lYfBVQ>vk?{Z?+JOlu&RQ^x=N>%1m_)kuR()NjMj1-{aw%V$uC#U zURjzp-C&O%m)Tr?^kx~-^Hzj` zU&A!lJSkhM3B<>cpP})(2+#Mb#lG&)Sk=|&7`LVr#iKr-^F-{0zq!5on z5lyr;IfH_9Su4zI8n@;4&A4mB$6-VGOWM|2cFNIazlk2C+94LWWB7J&(#^x3)NB(^ zqpA=n5)$!AI)JMxCUuB&Kk4q^G&IeENi1SK81)v|>Td&W4CjC%$dvoDYsAktY?dhc zC&H%RJA!&G@6KWwpL5*zKT#R~IFY=@u^(#I+aR%+`3h1t&}pK2 zmLV;WQx=}H*z|sP74!7RsEyZ{aXjO}#n?yPkiZ`JJ)M`+{FA~gjlWGsSHFdc+`!f0 zDfIg$_SljhWzaOx(h;&+dGZc+S$<*NM6GD+@_idYq1xEe4 z=$17!?EE;aL>^YtyI;SS-2)RJhh`?GQyw}3+W$GG-vvxA-~E%&Yhx)$@I$_C3I7!&hGp-`3m}Wyf^of^FMK&2Lh!lUX=1K{PQ7oh z)B=+9`|Jc#vRC0%tOh=;31MXhWNb+0g9 z3x!(D2{;_Ua~kz*?O~9D>lWgwv_@*y$Sovf-Qp=8xHjY{q~@cn1g`t5Uckzwvx()J zP~(M3U65@U3?bqM68M%R+Rmy*yJhpaX8>RkZU15W^w-NS>BuSWxmmO&j?Kx}j@cYI z($faakR)W3A*T5TL#vvX>MZeZ<7h(X-R}dMWn!DzxW@P_%x?A91+;!&;Z`AM1v-jb@cR(YLMV2Q#0z zy08&cDZ7ggL3w!5JD!xuR)s0No zP!Iwjmc|Tgp%I2l2j)z6?CQei7ei!XFywGyeYr`yaA4`l%?(=f$D{3Di1qkSGGGDgjl^uH*a%uYVE^odY; z`VSgFCW6H~Xs?RrM1HNisp_OG75DO*hr$OOP z1RxW|0LUns=kqd@6qu+1SR{?V9FMr+t5<|&=N#0`$^^2+CtVpnr%DO%1?>OB1s^ZE zmXz1bEK#gY5D<@|>kp<3@1r^SdXT>4DHDHGw*Pq?|AhG8n^PHnjpT@ol9i0N1_L&J z;7Rl#YVBKCI8x=(4xYh7^Tz|bx!_W%&tbmm(t1mHUCg$c8);uml2eXZ-Uq(Pbq+t#8^vPG9i~fy}okB^ZKDX+55F-~w z-a~*G18hVc0Sj!#8X?yLWgHYiZ{c)%s}qMjvl<8s6`v3+TEuFQT*IqzHA2-WEJ%F= zMuvaMvKVznCIZO@{eFlS^5bKWNlPag!8fSG+S*mG=00t(3%tY(Mo*c8mQX`wkZ+p5 z42o>vH*CC`ZwSbb5to@Hnkr=E%)G0qb#%!~vPC>==Sw8T9M5Q-ElmvngX3kB>rl5cCdaaz=Glaori=XhuBH($(K_1-SI zjD#9`co8tsv85#G49JO0+A90aJ|D@z?SNj`Z>Xf1k{C_y(@qfwVtc(TrZ++^(y6-- z+~>_2r3QLi+EeZASf0!p7?QpgH~)?k9ggFHN8(~}2QqlNQ;~(Lut`(56Gjv}ZjF}F zV9_PDdTeC68CQ>7y5q%i12Hl&SbGKSEow_`6WG$w{`3z^XAx+l!G}^O9Gd5%l~Jo% zq<9sR0!#NTnMjpIYqAfVosR^wli_#tdHukSS?LuO$kz zD8A`>C6~8SZzni=GSd&rGg8U%8skmH|EMI;^w?U?JbODZNB6q<(IeS0eAQGdnG1}e zA0xEHu4H@r98ZLJhbUGibqNdn@*6n$!yQLf^@LyNMQM-$jqx_AtmFK(`&$8sE8VY? z@SpYMJ$!KauV^6nNq~$@VmtwdL;Zwzm7QBBYz4M`d*!@$>d<@iTz;jbAVd{fG@_03Ktr4h+Ynpy9`$r;qcxT= zb>Q<(o`n}@dClw1ZQyD^Z{|48S_nuFRvBI9!9P9uK|TibAgn!OYw#7lDb|>WXo&Dz zkm}LC&=J=%8t*vb_e+hYnswnjlC72*obM&fhx?7tX{j3H%~NUD%W|2Hpi_bQvg%!b z!_(J!DSe~EE=N8iEvi=y=dsy@C;`fA86%@#_Tq%=6&510#U&%yfE{D%tfIM0Nz3Xx zolfwZ3ipx(cpzT4Xa}j;r36<{T%~W(z}Ypd`f=Xy$fc+?X~@X1IylZ9Q3;OTUoy-V zw8;GUx@xP2B1aX+5Ls-U#2c5@+4TsX{s-~M`MW=J^}iJT*5~MewP+hHgqy>s5@&(b zgd(Mr{$Bggm(PN0cRe;+E5%F3u51K^>e=5J1=oXkV_*K_bWwRC&Rk3BuWHnJdvMo( zQPzefS1}9ADWPE>^+x?L3O~*I`*Jk?f_4MGy12kjsnNu=-$QlI| zwd>0`G`{ReLBzfU!g*jb>@;;>r)H@l|6kPn|3%g?SuWOh{v%flQv! zx>7cY_!|0mg&T6e`@umT;kU>fLdGrRI`soza`6z?Y|Bt4G!m!%7Z`EVAlDqqaAQc! zfi!s0DFS(ZRk%Z~4%1-@q+?YmelWVjsbiK+6x=iqwBP;|)7K zQFhfdDX}$ip%xdVfZVLejPXc}15lG7%MVr6j7+77Ynfe^@PTB&Fsxd|WrZ?1&d{Y@ z;Yvq`t}km3iy!95^p=P=@T`*_`Gpc%;-(LnDdVy_j=l@DyVsbQRZ!x3T32x@58{vu zRXmaxN@r!_S)*V!NHAyu!vtZVkx7t$$*qRyg?9um(R3$VoIxW0#&$f3V1ZSZ3v=q_ zSET5g#i>Fsjh%eUm&ufiX+pk9oMM)LPsPP{=>#@+I*jP0ZtWwPV4a*cp4I4|SX08V zzhO7hXJuxJPU2ieyGNZ~fWYMM1r=y;f)xC}ltNz`OyJ8E)pPlFb%fi{V$|OY&^p;H zbl@yDs<_m+W=MK=K2X*ijl(~_@(1v9Wy&uzg$VUCu9aC_O{qpP0!$$BfFb2vr0oUr z4xkwoN_G?5r4nyEU6KelTG%u&-kfJ+vlRQ|Y%HA#vH4tw=+FmNr~!&A z?6rGx?fWXUw1U?u~kXi(!dPKnVJ);ow+1|l?jCzJ_(;?Bm9 z(J_(vtq;IoCzAuN2?A_i-UqO=`A&2K{$B$~#C=SGC9-VX9&K%GD zLG8K$6$D9CPHZIZ>Un#X)`{q(!1TdNvYCdSE@)%Z3%sFwY@>pPApfo}3RtM|rqkwg z_uobX=d(yC&8$Q+l$*x3KDV|2pk&~)L?t=rqXX!n|4h2Z?-WErnd7>&)ai1a`ktKG zg_0fCzoJ0Pmn$E1`X?_1^#fLLTOc@xnK?`dD9Kxg47F0Os4O`;4ZUw82!sYznnZK+ z=e{0`N~BR*q>>W^Vf8#E>EP4hzOZ;J>IFn4hUtjuJ*u7#V~2QT%0Mx~h{zg&_3-NN z7+iCa7AOfXyY(_YYrQhcckw_T^I+5B?@zouk5oJCQh64o?~~?IwMg`FxyR&{VWXr3 zTf(vy@vE@)+SN&h|-^`dY}b29jY*A6pSOQ0BfFV95Mi^D568SR%vELyx`Y9SUemvxcQI>H%TVg zRkE1a0ETJ~LxCym70fy6EIXA>wT4%ieokPi7sf2ZmAh63?YbSJF$!)9R0wMh)y~&W zXlbjqVif^2R3W#nb=c0!>_R(61uq?A`%atCL}5@2jyM)K_t0sT3%rmwAW<4LkYN_4r)c;(Yc{HB{DMPh0!GR0G5T8x` zdeUAF8U9t+c@+qN7hdlkIEdF@MU(gD`Ee(87A(d3lEE87t_unZmXXFuq z{_e9FCkv^43KDmlf~(BCUZO$Y6{>en*HIH8&|w>Wf9-vUSc5ln#sHgLiDU}lt7G9$ z;PAJQSA+(yv%rQ)!nKEh}GD(76S>uWBP3ILiyWpCHjM9uX=2 zceHTe`#~rOoCp(e7IY2S^y8OV#v61*1)abAMdu8W8mX-YEJYFxZh{m*Qgy}XP?WsYCr3<)1WbNR$IWSGzea#@U|CV^YL@OtkN z2Tby`Yf?jmY&=~<-lYryFm=_>_rHkw(CTaRDX(UaK0YOFPJkvSr8*nRAUlBp@dvAM zY2dAo@U>9E?%N3;pEUfn8%SSXiuH1)2@|l;coccqLU_kD;OyL-r(Z`D8dKHqFenO4 zirIY+cCeq;4?0e5Hu-Fa!pxs;v!WmfMj~b_?p>bzl#nlWB2u6cmPycw!z73gp1bv9 ztRYfsE6@o(bMs|GOy>b~lFGylNKl1>bUPpeoaUj@=J4?eb?Oy%q;70KU0 zws~|UB2dLO%nPDZB^*=+IN}ze2%JJW^^Ld-%XgmPF~^yY)rk0h@(@@f5$4G`i(Yo) zO|Rc8(xVtj(s8?2p&^tj$H~%bNNokAAmMNIS*G6WE!Q=@vq)+HWgD9;sUmQ)#_;Eo zC9}%*lY!npFrLmPA}GSR%~5DOaQ!7zK~+eeVBbYeU>RYE{iMK4o2`x2#l-gZP8;0W zrebgAQr6k4U9m%kjG;f-?4NP<3m;bYswueCmpT4T#Q)F{7pr7sMI|`%v%n?m-X~V& zRXO!DPQ2)K-$QA##MQ{V!9OJ-FS}{iXzihXsPp{?eQDnG!$6wffMAqf$MneWX^V=EX|2oum9j`_GY<8L?<&*NQ1PZDe z@~oNzSrg$imLWNAj9ewsa)U?i-!Vrsu8ea`GkETuSgx{gklD;fA9%h$!5yCEv}%?? z$+x=dw1cD^pu{hyT;Rg9nN=SRnwUhi@FqR%9z0Za-=Xxb5C-GKiy+!Xa`O6T^$__M zqXt{kIA-?bl zrih;+UKAE4Af&GgUIK9VsU8oZmxct!elKGPPvcP4KjN~bWvK?rjSG1OAYc(etI}Q# z^V6W4c9$Kwr`7iWj=Q0xov1eSj+M`&{4Kxwr;YDrvF!HU^z?3oV;NpQ^Q4=2N|zEw z050(UTEo1$PFe!M#mddQCgS@pZw}M~-7C3h`Yzo5+~k=OTa_hH*2k7E(crGMk2ur0 zHTV>fJy3dc9QO)t{HK$y>&Ay`~j<{CCQ#JS|$bR^+8B0Mgfa&ho1d(Y<$6mB}0lOq! zcZomfciXT)!;IZuB^)pcC-jRiRGYQqzU}|XybRwcwvd!^L5ORgRq=*x7_mD;oCI9E zW@7V>n?dY>yNAR9x1-h=|ISY!7Ls>_`YUtRJ_Cil>N_7jwD(8ZNB zo7S4bvZaz19A;h8k?xNeqadVj6MRoO?`;!sC?lt{h5!;D<34=LUq{N!rr_rc7@ylE zdY{X6NyBagmFcA&;JhtR|8X^)nPut9TJ~h?A4D#T+qWbV-)drYesk`Y!z;$;o;xud-5RW^Ja{=9@(HL zdE@d0C`YFVKiDyZLh5GW%tAmCBGL6So!AYF<8YDrqucr-RWXtk(NdGCXtkb(G84A= z!ZyM35E2tiFKL9LF+B}@yF6!vl=gZ6dYm&INyK%+P#My`*6mYcP*ASNPAEV&+C!$O z7?kR63uGR_AZ0f#`mEM#(#ch2{mh0H5qXIU(dP@>_F*s59$piF7`cndccSju1PmF~ zfCcjn*y<1KNRpG7;YDAQPOrWx$}eOL4MJjMI?*UXC-JO30Aqj@i3Gw z=}H|t3AEd_&V?r5sn>^dqB8=^#?Ni6(a)?YtcMdgiP9+xlZ{l4k<4K^IUG}G0mxwQ5= z2fvffDfm8b+PM}#L$v$FZ+GW5WeYSCEhVp^ITYO%9V$(;$He(*$Zi`Z_cB}MUf4Zu zbI0Z|PU>RybBp+Qo5eaAsI#&%0%X4$1&ex|arK{9%(IS+<*orNcDkmKySf_(V@ZVq zp7cJmL`ezwv&iUbxo{M-#3ex())JEy`K|^?Pfw7>(DdN_*c% zSUNpt*JIzB1mqVi`Pw^uyun+Rs2+c+rei#-3Nmzv1j ztz?13Z!7=u)M$l;Tzo_#WAlHCn>5^yxj1ZUQSDvbufSqOeVrzAq`INdY`0h@{^}_A zhBP`X>d1c2TkY}bYy|?IWkudJSN7R{mVS@)`QB7p(;N~PS~Z~fN;c*_Bp?8J`@gPnDyAZjZ7&l z&bU$-Z6wc3N%)vqYiE)MGjkd{jhf=q$14IOLO}_qObGp-9Sv5!mZQ(;O-w30>;^5| z(H1zbt8A%OkfqNGki55v5%_AJA|WvvOpd%{csV*W`-?_g7Eq{%PIVevvOO0E@G||I z_9P++oT}=g7c&^x4QYL@lItHv9{f8>-(pCE{<6c8!DI)v+Y zyj=@=fp-Y@*esaw{N9wnP7|FL6cI|b+sE`s)fg|a;IdrQ@a6w#0l+Ajv)3H~uyU#1 zZdoT{H?-2HfM4|S@g0BY=+>5h`!ga?s|@%vKpoN2)x@StL&jDEE@K4kVp z>JQ^|1aOvim~&CrjK;Rc0>_E zi{zDm$~*6tkvq0JNo1F2M*b-S+Y0~uWfO6V7;2QH2uKe>2tY#Y|_)}MDfTv=Jhm1*xQ1S6BH`l z4Lh?T50OE5CwETMyvVGxBG&*&!F&Ll^-DT^LTZI17y8H%s1^F8pJ@u?IhBo-(7^)s zX(s1#{(CGiF5`+?Rh3=D>J!wuaB?*2=LhQ53Qo=)@t@-fY}l%-k6vuob6meyqEye} z*@x?`1!6;GG(PYwDJ5*GR16XPI6v-%k zpXBe=sp_DZ^XP#o6V!jW$zfbS*KW+0n0*uTFMvdpt^8Ey$FM~D%C$<}MZV207)VbQ zHzI{$OcrGktlr|mm0J-fjE^+dNcy9U)odN!GEA55liS?>UWLW*F#~crNo^X&jMoYa zwcU26pZl_I=dniDUSNUW&w!OradBsAV2gz8A2tILEHrim#POOsNfQBc1T;4Z49k5? z^}2P~;?zxr)iP7s{;kF($$2Ytr|G%62<}d&1S#;PSw_sH;m#i~RR`S6FZ7Sl_yWj& zcO_|Xn|orycM1YASbUI&==Y8=iu-GEucm{wNP4l4=Qz#mT)@Szf4(kzO-1V=`uS_5 zJl%%HJZ9kTXe9EWMmiVhXvuTg$K#Hd4LF=~=tD~hiY>D*p75@?r-w%!mVAvZ9s9Eo ztq+5*gl1JOTlxt##Prw0K9Iz8xf}%~%}!8Db!5HS&uAV!ixQbw!y%JsU&Y7-vGb0y z&29oubuf$V(=Wu#uP)E1Zc&&ZWO&|$jsNJ~KU(Ds!LuS*;*}j)Z0R`X)?kPpg5?}! zx7t6Fagn^ z-PL}zM$ho|Tkf@ZMe`Ah!OF*ikLN4XuTVU*3o$%$j47g`df|s&Z&jTlbWk(M>1$>= z2EP~HGqX5p9bA3JZN3~QO)q;{J{Eu}1+pqZv0g=I53de0M7hS{Szhv6n*EkB9Tpl{ z#kvqrT$lg3E9R)Ft$83eyvIU&eTi=Fv-Ob-_W{7G=8zC1PAWOM*aBSb=Pmqx{~KZk z&X3VJ)6_;Z1d)00K#n?(%cs*pDzeS`IX%Oup|MNj;m#(Vgui~FXqH$<3N(ds1Z4(G zd@6FX5$Z?PoRwdfb$I?>fuqEpHPVjpWqN31u0cC8>t(eB340%Dm5>~?;6;es9>rU8 z7L&W&EO5_)H<8uU4fMMk$ol}d;rJ*`8WhK0+~J>gRq@4^Xe29!!<`U{xQiXd&2IV5 zwx4$?B^8(t-P!V1%{X$~c@`nmTy%Ed>8&7;d5>;4Ak>5%`9gupORe6&>@E-IQTZ$V zyucC5IXIpR9sny`Tdb1$x1eHl0jf1GhQ0U4cfa2MH2vR;Q}iM04=4UXT^~MIgbDUT zGEunmt2P$kg=5BCKW(M^;&aV9!_G0!fVahKyTozqpGe@zq8rRUD#kM!ki94`lJ$Db zH{{zPwa%~f7YRWSHuYU2)!fF#>=5(7fwRZb0D(0;@#G2Rsj?SMs!8maHyjFPB0^18 zncbmkm{LhgNZ;*Oc6kCO=(w8oG>m8Q98fNF`&1q(Oy6W4dT@@loqn?QyHrp^#CO>t z`=nLhvsR`r(eKIHgjq#m=&&tD(csVv#W;dHfTOp!zol8IdB;>Ui9GDvOw4QL3ICW- z-r3D$k&6}MOqCT!gz0=!%J4YWtQW^gidd;M;u=60TbDTxbNA8(`4Ry1pePQqXbm88 z6mWkj0#ZH8S+>HM*^_ zxn42XO)UU*@SdvArQJL+tM8{_h59alVO0#t)3Jtp(ZY*$h2a#k0-3AUwOe`BU|;wr zom3Ul@4HauiBk~D`+|c=QS=s#t2GuV~lk_dh&;QyB(Uj23`(DC=vd zD?@UeoiOYFdSbkeD*RqOLj2ZpmT3EEG#_&x*5Ep_`-XOFEi$$4{2}k*JLYvw3m;O& zi~vKUAEsCdK<35o9oH$7vs=7B-v26f90!lPL<#Fts_2VO!{53OZXAy>I9m2>?v^#7vq1_QRx z->4$y#d1F&<)S9kVz#x3`uhlwpL8Ec)qI$1E}_|&{@o&@t;4*ryx+yMjF-2|aoLMj zhcq(W>?~mRX!0Lwv=0~gqld#@tG`L5wnqP*hez#N=3UZ#V#`U& zHs^`!I}4_G8Jo4;U%CK$j(>|bb%Y+;rPBE=iS<;9eijeTRkfTG%_|HVz{gS)! z!0$}Bk(ZLsiT5kI30QW29@J&TU>xxaXNbR(+`Aj=eTN?b6+{Y0sC>`iQ)^ww&LR)@ z4O^=FA@pnu!i)Nih9}7^@AK3FYX41{{Gt3~WnoInr(F|_{xa%$2=>qyJ2(@a^49C2 zWgp29E|cy*Zo*%HW(#T5g+q9vjuD;_y6287?fyus(Hd6rY|}to~|wCAdd$d%B0+WBqC8tD{ePu$7$=|GysYlAv1zJH!6Uf#7>UNh3railSN8URUs`ru(uVdsy-J!vXq> zGHS2R((YJ{4*3oJ>55_r%)XL%p)Xz-;2^}4>RW|Ac_X~EV@&w2xFh4eF4l>Sr-h{) zD1$nkhUv~GPsgmLlZLHS6HFt#KuoV3@w7mWFLUu>jjX-EUK4!lwnXs5cZr>gVR^$$ zCN2hGsJupjS1{fAQP4Fw5nXcTDw#Df<`A<`^{08k zniu>ilsF?;n>@{L`1WLhho^fN>vym^x2AkZq((ZjRK)vl<>5YXti zG;UF0Gq%y|2-c38GIkDI{LcPrm$~-?X`xzl`Of<&;-=g5~pgr5_yw!N1>F64g&1lRuMcORH5C)_36YenV%( z8`Fbt5Oy_QEW}2K_9kOXm#rb#uQTG`Rm$pA9Uf0|8 zA#Kv%rolbH(VKSPdx?#*b!6}5C%O8SK87T@k%7u;w>1ktw;~VtGe=3er8gv2^KQ$4 zdY>6nh+W^-Wa`rRnTIcL7*j$3-=-$Xv295ySI|~sa)fR7YcLy9*xZzymv1tDCz9mK z-oy@1l(RP*Z7@MlZ!s?+o@COeJ^LDqn7q1KHRp(H{ah{z@)^IML+C`7adux%9uw`K zgjQmH*U1u~8x`*B&i$;lk+-^bjhTby0nZ_SJjZxssKq(ZE7B9Nw?T6Q{|Og=7G12C zh@G5aW{VAFNFYe=*eQQi_`jO>AqbxWEx-hFpM||W<_T2LvpQQ$^PoR)zLCs4#u~%Ryo@(gv3J zPzDp6YfD@uP0M~tO|ZM)jx@R-aeH$IAp1*u5*n?j#H{s6LQ7C=s;>gL9VixzzOWp- zeRY`6t>N4v35jbjiJpk@V_j85C#c2?eVKmx6j(vXUxDp1=>V)(=rzx6%LgoCB21fMmvXM^RUuQHe|Cn@=R2b&SXP}MQe!;Py0`-QDoHX}>? zQ*8hf!ye*}72;SFSy%*4>vqTM(qG}7pTS(L=$Q=w8XU%Z`!BWT8lTuTeAqc~5lqVYV zB^1QIIV4F=YFN*39e{VlWYtMD8Fel0EFBFCd%Z**l7RZD!ENvhONRB>DS-PFB783& z{Eq~_*kbzc1ImLCC)yIYs)9M1@9aeh2Y6GemI*Ip5EM{*OW~gKz=n$O9!}v*;EX}D zxmf9{eoj)+QMCJ7y(r`l=w_Y*wj>EBRr5K`(}N}!!vnoE<=5k}FeA1d7Rsx`;D{-$ zuBkxjq8LA|KwxWA9tT9e-_tv3;!%+?} zrY%xaff@$3Es6lqq8!YNUo~x^%K$^86kh&Dum$Qn5W)a1Q+6OYW^BDl4C@**n_1rE zvPs6RQzZ_LDty?X&Q*i#~;mZ!)cpztSwYo8bxS=6D88psl|@s z13;NFX;B9$*?^lctuMpuSN0kxNF0_d!Wt^m#bvZKRvQqIArhAbH(XyJ(6l^&)6{Pd zB!$(G%1Ch&Q5LpWsg$thRpf>~J_EWpE~|G}7;?Bowr+3|s`5E*C_IIF7s-cp&u3uT zIrzj))ZE=ZhX+}>Sd}BjF zzWWx{zKjEkFpfmtEQIf-QxQX9C=;WRhVctJwcNcF04nJ z+qOW#BIAmqe(M3iS?mLOULD3U^aYqKy@2r|CKAYiG&?p|2kJZc@mK;1v7$Ikg*?_# zVa(I(qS;U7-Jy9Bz5=DM9zuZ@&7HZZvGT6HFp@$JUtj&XM5D8dD88RC&~p!|C%9+!&0Ffz?iz1LchPiXo+|a?U;nNw_YKh&Hj=5-$F>)F(JIpO#GP=vi?~t@Wv3oT;!(Po z#?@;L4My$rkfeWyYvL?eG_=qo&@6?&@+f?#((J*T4~dh<7K38IJy0_CYX#U524gG3 zQixX-5+>4L{ZW8~N(c$eK}}m7Umq&BRRs)4h!u9E2G43I_#xo&F#&&X`J5p?I{rU^ z?dlVtZItoJa))b)YnHr@`m4<9snf4^gwM@XPQDr_{dF}6b=Ym*g7p^Rd3&<1cFXa; z2Q-s7>IGkDkIQu{_?chpWV8yyG9`mUO~#6cuXFkQSF|mQD<5|@BG00~CbkfhwQ=a| zd*!TF;u9N%_}G|*?r_;Mo#*dve+NI#JHFHW?ZqXv786*)jtw;}^N*;+3SM++N_NX!4Vq8cjxv~KZD?kYz{f!sm z{)Bhsw|g_h$$+H!0N3tOr2~H!;pn`mN0>iLKke~zzcWH258nQ>y#BqjF;&AiGl(=K z5%i`YQ}C!#O}EtJ=rJLC!5zs*ME&7b>Yx7W#p^TZ)7lI-VFQ=NPb`eY8C>@&*-s_M#4S z`<#&jqi7PT#vq}LC`P4f<)W03f^iEa(2+qfMD-YzI0^x_HB`B!_0D{v!awB}4vWLP zkpWESHRka>vMc%|F{FuhoCiF{kzX&V&`8PVg4Un7JB1}9IAy3K?NN1uZJ5K({Vpyv z)3itwuFjd{QBpV#aRCtq=LCOkV8{p2@2qjned&?xs?&0`f~`jwL! zST`%ZJ2ptvV%N7nK9D&ExQMePi#b|abWAP520=LY38QKdA(J8UB1Q}=xa|WeRO77` zFkJOGX?Ba7doRTo)Ka1(Jhr;Y$V$zgiWOvXf22X*VW3veVbEU!J0U@v1 z!I+HEo?l+oX%v_)2EIGV2%rfTEXkr0mDoE`M9#C>OSds#DIv0g|D@`!F4D*NODl<< zfqAh*Dkf8@@~oI}1lE7-7?I@jS1?3K88AXz9lxgkHb~QbBg!pMzN&yLq7)<^C%y3{ zAFqKqzjm{Rq9~N6B)~$VX^v%8xO6@*hecDWE_72oDt?zySi#i6o`zytF{&%uw@kqJ zL1|fQ#IeA49rcA}%jP1`IyEL%qL}_>fQiv=(`5gH%-B!@elJn4epG7Z=N{R4Nrw zUAz&fXu<>W`aItA1&89BVooEFasxTrIY|;VT;{2;h!y14!D#(!yoYDWLzX}Q55F%F< z4k-WE7O4;4^HJxTnNb?B;r?J%zMFBOfYc=2Wxo)6|Ayre6>4y=@7JM@e)H&>X0sAv zxaF(ganXBA>4XXQJQ7<8IB9%e&F9=5vWg4k88&F)*`yeuN~HPj-QkdTbF*dGPiX1~ zoeL$o-nRP#NvV;4SP`B8ei^+6|1N||9kAr}r8cA z^mt-TGe=F>h)foKh&6nVU~gLX_V%gjZ5?jc z9V;UZ2@ugs9F}borM|A&X~^b2kMwD+DcLw>JV0<6b!Jb-kf|>Zbx@nMQN{73{nv~W zJYoLjTFi$9`q?NqFnFrgU)a7(TF6?(S`>_2Y|k0X?<*%ji{F9jK^u`_gJ`uK^|J)} zwk0&0IbGzpsCulvTcETomEmhRPS_agOxX(AKLn^4IHVJl;gqM+xNM@90+YS^76yu0RGbIv4dq`Nu90`;XYcl?IeZe4= z$pEAJ;7E?nn()fm(F27u<0XPittVy7EZ2}Ul-jb*JoVqzZ_R>&$P*zam^u;a7oQ>% zYhP}0k&ftADubW5T_#xu$!Rz=ZnpP-*iP84L z_f+uK-xmwr2$EW@TIq!Mr%w8D9o1k@`91xO_TqWkOM6m)<7OMC=$S$V+`lN7?U0>L zk-TYF7rLMx_8M{pR^}%#%G?6RG0PsJU@2A8!e&tdoGNH=(i%986ikKt2NHl&&`wO} zB-=`f)0Wi028$tuBZKCn#)L3RfxKW0kc>S?ro$;6K>=KMqixBgtt+5_3PK{sa!iUe zIY6Y86P3(O9G;vXPFjk(F*^pEI83EOcSA>sE!Y4>6JawG*>=yB57BxbpQ7CVRePfm z$$?1^i_W}J+NN?MRW=mS3?q^q{{HB44s)x#;YgwgDecdw#b||{k6RR!x5S+NI_n~b z@QL(PrnRjf&7yjPV{2ie$i_B!jLyuA~coM7avEcU9@=p2#!<+1Y3|U_p+3n|7 zRe-_psH5%k6_&A8gBrtxbIeHXAIPc!=7DG-KEP86Wp_Lw_|P2X$mn9oNqN~e5qV=U ztr1XiAa%(v!E-(Xgs5VeAt_Y16i)x8pPH5#Ge1wA-TT34C#SHAZ1l`+ST5KHD(BWk ztc*DkQl@6a^)l~$wTv$4+o`e0WfJt-h0=#IzBQt*dei(8A%};_1zb8p5SE)c>0i`2tb? zEoG=?*sXcA(d_3uw$J4YwN6#$@tJ3@>yY33-)vn=nY3t^5518a!%@GZ;o6Jl@9!@3 zQ5@%L#)NwPl(+X^1l!ZUzrc{)l_r+dN}I`A>uWlbyV{?=U-|Omy!iZrcKw<#l72w;!hBBYCeZ;%0Fval3Y1m6+h%5FqC^I0lr2{zsV)Ia7!0~;*5TB-5xi*o_ zQDGuShA)cYSAIsvW4#4XfHHHMY1<&fv_r&5#_bg%nAB*DMKOEk3D46~?CQf3do^vO z#_g;8Yl!q+n3*R_!yEjV-tvl)&wpy;j9}{7-8;gG`^H6JAHzuKb2F0yC#V@WY4$)4 zGO1jNi%{Zc%J;E$`M=R<<{69p1dipn=}>ldOJc^D;BnUVm9Z*{04?wj(91P zQ>%TUtcd#JKQ1J?fgNHeNYCGd?AgbL5k3>mm5>fFlH$V2I0_?Zx1So&$rTh)in?ju zjeporP_lMR?S>UtagB?C*hqQQhln?YgFv9LXTjwGp7|hF8Y1c__z~`eJqPiMkss*! z#1H$MCpN>Yz`%M;w=`7t2r^*R;fv5Ap#)>Zq#P8aF`z)H9X3|6UwzW zYKQZB#`LWHH~ByPP!n$Kh)oRec=gMBV@>6Yyfk2E$S7ns zG}iii#I!-s@JleFGg3{{uvDOra=N&3T>5>_YixD_)%n~VkTzK&v5Y*C^Q%wZ)AnLl z({{w&*I?MMB|o(8Zo{+%m}~Ld*i*$oX+{0hGD$iNQJm|bFK~=B1-!jh1H+yLkO|49 z37U5~U-TPQ%#DSj*pS)9i+$a8TUl#Kg_n&j&Bnj8R4p_-JJyEKtu_7mtGLFjqF~BXhRO?ZR|!CiY`uRo~-iH151vyytQP}o%0(j8ph7tZyJVKE@+~UF3#}1 zN55MG+WGiYb+83WqPM+yoR`<6#omY5EZg{*t0Z7j5d(U_n7E~iYei=k0<~A%C@L-n z)elNMRV(EF8;XOfM6|lCuyj9BVxai^ILsBaLLR0cXCFlJ%=9V+snm=Je+HFWC2VaP zG*nMGokD$JL@JuK^eH9t7KR3$%im+V$qYfJPpi@Vs3s7049sg8jHoJy7{*s~MiXuK z7?h4cNZjND3P@N%x4$kr`Qn;u)BuiR@G~WAY!A08lAdIgAb7u$5>AU;@bQMWg2ZWQ z6Sbg7R$?iY;G4U!PAj>!TiD9kkFUTp``R^)E)yBdF3|Q(ng@$h$Y5h*&GvK#`Qd2z z?bxLZ$WUVy*IoiyV=Q>6O)sa}VIen5c~1UzBx7m4X3C=;XqaaM?GB}l-aKmPl8LBmF?D(>Fy`Q-ap-XS!3SrN#hxBt*zp?6(5KCfNQqSj^E z)+9cE5McWEsqZnc+U2$NaEDSNZgGYSDdDUk*3<-KZ{^@p5`H-Cmz(`EOi z2JH|G$~9)P;xGJ7tsZ2}G0SIJWkakz@bT&W1~6(NoRw^Eg~`G_s3@8}d1aDr0Q!B% zih*i3fIuZG&AD}!qZmF}>m$kKd%W>ixVQL&5=CrQ};Cbe8R4IFe}Kdf8ofsDsO- z^0$57jEwQVO7uoRS&)%_cQg)LmZIvv;>V6q@kRvP3PYXBG#RsY1G1G{g9Azt#gO1E zSn7XvQ&pN&1w9vwvXyf*p7aRX}tH*%52qidH)i!tNC}ED}3la=n zk_Q_$V-_5>w{KE9zwuWhSHE7m2PIA=| zM1?%-U)0V8%M45}VMx?c|I+^3_Bj*5WBBQiI`oI`D{rbFxT`r)ho*l{f3rIU}zqq+mLPK|P=sg0wv zqVlVO{f*#4_C^`f71IRjemcD7r0bJovUM}9O{Zq~W4ib0(rL=^c;E_t%MQI1B@O03 z@9X!S9w<)cuiCHo(zYMZd3A}-tJUU54H2mpqRk>{I;UWw_3H00MoN|TZj-jg#m{K~ z65#D?js?x5Zgz!XSf0*aK4|Z{ZZd`H|2z?RByWQgakm0W5x2(wnM|+G3Go z48S<20X@gxs8tG7ML&fRF{{IIDu#JCvIwLXQ;3qh4Wi#f;oAoSC)`QGgbSikD@8*_ zf%TfZfiz?DUL2>omK~$de9|2 zKVCD1%UGj!@^nqCc^#*fd)vq&T7H=gxY?jmP+bGVgj_bJJkh#lxU8nB>3nL5W#lb+ zO%xs~HtWU~tTEkB{G~)(_Zs;w*atLQn`Vm`IPEGTm1R@d~_nS#P5_65lxV-aS$dI-)8z*sqxU|8K9rm03C zK!?9EBBiq&I2Tx!#Q)+u4i;01jBSXIMM{p8Fbp1_Mdtp5dq%(c+RKd^(F1mMt|AC5 zmiA?;SRSL>gv^`;GIsj3x`r}~AOSfhu6`~rE{%~D=E*e>tT^Z$=pt&k_u}*E!K0$* zajBh^#dI+b%>*Lj-C{Jl_I^z@hb}1u6;?BDA2FdPwC9?sui4HY2c% zr2x4S*OzwlN71TWcJKD8sbp+F>{mh)Vs(57Mw#z-1nZ}g`qk(z$-V1Oos7dBpOYaZ z$UROGIdNLbYxfb!0;Bv3)k_3b4R0oj=K*wjv{bcQ>z*r4s|7rGW?Pmggc%ioq92u9 z64q&?-IWb~Cs3|;*9qBLi6UKf3csq*hj5xtk%oH-u4EgmyvIg8)_y&2S^Vd@!4_)` z$qbb)Fg!Z>VFczU>zClusa&eK5!xYOvU;Vs8EzajYUtM=s`j7+ud;G~0HM<0WL-}q zAI%`xXg!OUje0Ijb}-SQE92NZvXWc`-~BIZy7JYv@20d=m2*o)l4b+MA$+Js`|nc= zE7uP|v{)rw17&eM?6=HJ` zO3*W9S~sdsv|B3S0nP#3qh<;lvuK#2T=rt{L23i%2{PtR>H&>?IS%Ljipl8=q=IWK zAwml5`9RG)fF#a>_zwa+R?wm(9AAY(lA7;cu}|-3nkXE%m%(X`Y&&q+ooFatVbNAN zYe;DoKMSuK`(GMBqMAQC!e+4mD=a!6jY77#jfYKoog#Y%X&N^36ww-I-9mUj!k&M5 z)o5~x3$16mzHXV#kML%YMz0=0`#iJP`5ysAJqhGi^WU7b!@MjP)afWCPI!~TLP{A! z)8$c^`amx>YB9)G*i~*Z05(Awq^KTydz)VV*i;yKyi2Yz19oa*oN6H~cAZpm*A(1~ zQYAkw1txNH+k)N(C&1rYD&Q-Bw8Hvfn)5f>JlFLAi7Mb7%Qyz#$*GTm`6=H`f}%Zh zhBsDQS4aAq^TP$rR0Ye!+5T(3%O_8Kn5UGn?DZ^POAY&bTP_WHf@rx_>50O`b4Y9{ zKw7*?N0`TTtxA3-!pSX|dA3CNWas3+@1%Uf5ZmRg%c~tDUv~1Jja%K!7L4v3$kx0Z zg0|FgBbQr)3wbX;fN5xvy682g+OwuQbNa6>9DQi&lHEwl5{H=8;JAQ%W&^3UaaCGA zSF|*#YHR|(Drp_qvM#Ke_^nR7%U$2!%NyV#=>V3fS+cmc{{AB0`?;bV!T7*z0hRX0 zTG}Ko8%@SdN)!USX5a4SD#^*z^rK5-PV>^~=~XL{lZ1!n%~hY2W5N(UTb_$zEl*wDbGxUn`$^-sk$x;#MjVSn z7lD|rIAX=sS*vN7Q32#ySq>WJyO6=$&MTXG(I+n5aIzz(T~4;l`fv9f9IYl>8)uAQ z#xHNzitFtOJZ1)qxMMS@EiK{~36i{aPn=2($}!qFqY?=#bBffA2m?Moiq+=m+I(J| z_Qx=dRmY+4G0`!G)lL)l9^scgA8mbuS!5kOZZ6wQ2HEuorHLMoKiAP4&yS-YL7+g9 zpiW!IB!Mx4`1s#n{@-aWQ_ID#abpi7X4sz>UVl~*a`@8f;svuCz}Iu9t#@3d;XmmO zA$0$9maJD#+*ISqjx6X4Cn2{hLoqpGkH%Oc{SD_xlvE}M)Kodz{02s;cST85B|AYI zi77g#LhuBUs*EOwm2{P~-*W*ZB%&BbX*pzWo@}aq)tA+?t`)VRsi`nFPf51bfWFXF&N3f$I2WSQO7Y1Xz&>ZHA z&`SlX8`$HT71tKhaSrXenv>x>>2`e3KiB^K_?+XCHdA7ihq6UafxQT z%n_ZqjQ*yR$8#b+ghWO!uJEK4YKamZz`(#Hs3sbwdT8IN`@dk7X}b&y^Cp(!)BJ`# zTH{uCf~adsY#krBPIf48HUdV?KR!NcM9*U_MN7xFk644*m+!F~`*Fq!o7q|fflw!> zM)~)|LO~Hrk*#DCBXm+?x%^RgWTonPj#`xBM3v$OrJDG$!QOPZRu~jKnE%dRQxezf z$GW6NEObJ%&sk`eM3dK+w@p|_?1+L%WE;LYKpi0mRTYgX%E^vU{7H%-hl>$g!$MS< z3iNoUUkvB>;_xTK5nJ_V`NPKGBC;1&F{`8rFgLb$F>4(Yf-;LnBJmN!sW_n0^K^qK zQR-f@J8Q7s996-&Guw3f3dLMO!L*Eh^|Uc2=lPax%62!mx%4}%N9CX|@d6chGy1^8{gzl;ZbJj9RK zB@7nn_K-=luoqY|qq+MzmI}D##W~%&sQxK1o9>Yt8!L}&BINm+e|^0^zC8Gbdz@I& zoZ*UczP@dx_TiIX9<=qYs9^q z#-f(!9y7k$8=fckMjlgTG6-#cRJa6m8l~-1kA$J<7(3 z>-xRlFlF-yMEHnrvqgpVi8Oofn0q-iF{k5gN^>FLmF{CklPGaFKOxdI>>E&8qYdYn zf)`(Hu7Q*3POZ0GSrqgc-RuctS5m6cD9VMZVZ<<|k@s+ift>ZApxj;Y!9J&^r&hR>>0$Arl%;{yQoVE32cewRlYG&+q#R;cGqk z3>4RxcAg~i zF3=t_dXs%GENQ%m5)`XMs2hkit2Hh9$Lr6gc(}`HSg)`tDQ<}97!stciOswU!<82Z zg0LDXL>M}=jPtLf{C*~)p(_cE1&icKXa2C~H|gjXhL5a4sf1Cm=4$*E=7LkG2of?+ zRC&adqr3zWIiW)yc0r_h$t;uzYgRS|`IrqjP6|G69Rf{R5D%_M+(epXO}w0uN$__H z#D-F$RSS(fKX(x;V#p0%R|mSdXv7gzO)e>t*iehaU~p2ePnvyu6p3ZyV7yY$s_o*sA$FF8T`^XF)PE61R_D=h}hX0e_Yg$&|Rra3)@=9 z&Ba}}6?>rmvtP6&QRHDt!QB4fw>1WiSQn&ow?H>3hLeGEH4=B}^mx_xO@t@=bQ4<0L9 zsqDfYo_d1yJ)W30IZ>Rz22Oh(HU0m7ur4!+L*|zrUT-YfG4tCOD7`(OaY#Zwz^1M#h zeQZ6!UYuwzr{N-B&~TyFG-DgAJ1`3((|W{|v12qoRt~CqxHv7-c3$E{T&?3{&@}Y< zxTk=((GvUk3{s7~{oBpzym*0iwjO4r5KM(xLvKwQ)E?;_|K(S-wC;^}@i&ZQVBhHI zdrn;f?&W)0WYvNZb64GO1HbyoR~;J$WYV`R$JjL|m*Ll^=Jn4UvF{rr`G{Flazw^y zcGzy|YpZxI%zoBs-S1|VOC;HW-wr(P)z-tP)4ue%7K(!Fc6>rxYOGRpg>}{LZ)k)> zg70p%AAgCjnh5nTRJD$0a(^{&?TkYEP1`+vV)^U}O?i8?u40p78G=E-mF^H46YcJ+ z%p-TFvX*A5Zp3YS`_v@e{O$W$LcQ>~U0)Pilxp{;0OH4#fX%tCSCB}OdtJ0I#cLL&D%-e|6QSAj`Rt~>SSDj?OPdxLpfdb7FhD~J?4?`~g zG_cj>kh{bVpde6+yy#&E+MyTJKr4K>f3p2lM!fk&U{GhY=d3W!yY#}-Keoc&i zO3Lri=QwxPWEl^CJ{~v+W{&@RTiD@-yGb_F*D)h@d0j2~c<~>1rbFKMAhU&=MSi`w zJw7Q`=$QF&RZ7kF*iD?>oZE|ed}BS#`poA|hOo!i*DJ^Dk$_B#)&t>McVvd>M8w=E^v zSUxQ8<qFHiq!rQfN^C)t&(P~*!WIyd&)^$#!r(kBiHFsu{2Mxm&Eb-FD zR_8hQ@GilH2sqMy1MsMN5Ql7HU z6Z=NLuRDpQ<^>r|IM+78m)eKdB590znb%zPl=5w&5r^BPxy4g4NuZ9;M%1x!#@K(h zw-;^&2@&v{BNb<6HNMAx#K4PO7z7@Jky~`}a_oIEE~#Uu=~?{^XdP!ox&ofpw%GCd z<@(CEKww>&&c=ki{ojvGxRCn;*K|tFMimWto<9=EOv2f*-46t zvi{Qr%kxW%^6?#MJwX+Bvq!V)(o|1M$esVrsq*rqtnm${S@++Ds)u(nl0RB`A;gPw z7{jCLK5hnd{@+)8QIB`GbwM5u$lHagaz?uirwnZhw!<&I7oG=mV7GZZh1+CSFPQr6 zDGk&M=0&Az>KMXszyA4je-zJ0Zx7Ujv{6!~ReRNEvuz?+W%m0!v?q$u@2OLu)?r>> zH^2XzEuH=E-?#V2xWn;$5PybKQa3oXYu{p(@Pc5Yb_R;i{ce7k$woh`$WYOCkeSQ* z&fd)@{HTD?{5<+dyeMj#aeXCW{o$o7q0Ie|kpwM~Ku`l$IWDlOxl`>ENER_rNu1)T zy`Gorf;q8Im6R*Ha4YgQUggnN~lG?pDG=VT&fP? zw6|Hw*obl>y&5lZi+<3VN)PpL?fF!+_()$_cg-6CxhO&vqx|oE%VCbt;hphD;W80< z4-VjzXso#dopfoZ&i6k)4Gkgw)5bU9&{69T+brUf8CnB)Cy=Zh#lE4!FD6ZmpcYd2Bx2 zYs%qCsB0C{*TZ>w6e_d>44% zOBeOk3&9W#_+A`Eo2)Pp8ILsMBvcwq&C}b^)u!kkye!u}hza2txs?<9xJZ840@)f7 zsOtPSUOAZkrNo_aqNAQgx^wI&~m&g>R<23Un21PQ!nRRts%hU7^MygDWm)o_t6|8rPt^@U3Mi6 zuBgTgo@w!rnks(-j6^&MhAEnZ1OV=(7Fd^rsGKO@L$Va_C{42w$y0EEz}v?fePty= zlJXh(4Qk@i%fUffS&MPGByDx^9WqW&dR*b zZu4J$XsOk}nAnAX#l!GlsY5|p(BpdGbeG|zrb4nn~s)d{Ekgg#U-euNDQKd4s$}7KK54>Cz z%)M&6EA#8fnB=Trk6Ico%MY8ZG3k8m@TZn+phzy~=Z@QL!5B>vMjIMsz%sgx4rzq| z#cH*!d&cr>+W%Z+7bxs*|M22ko5fj=t&(iVbysf=Kc2F zMt*h2-(3C{n}u{%Rvib2U9Uritr4(hmSz`x-t^YpvopHHCCu)B;DWC3BYxk6_7u%uYdZHd7=q+S4PuVPzxUirrOz}h=M5$wK;|Ujyby6@}#;T3qwoL#PY&g zY?0%&EPY1P43pI%DsrO7{0yUg`%3Gr{>nLhv`1Nk=+dk0<+S?l7ma#EU{x)|xmQhR z0CW5q8C|I{rW3<%um9k|e3%-%$ZT@WV3i@R@RZ~fR!uUxBnqi{TK!VotXy;|kVB#Y zrS53q3Y(#>?z#%&;&Jodl!O1Pu>?j+C(EX)lMljLP+5#cp~*9Z@b5dn zFMeRx-H>>`%C2R9ycv<(o!12Z?)rQFh`MjTbR=XXNyHJ>NEKqiNs(?WoxIV3^YUHKEWRYl~sG^RAIkzE<}vG6HD(ZuD&5>oyZ)Ogtaw2w8~Espligh@RmMOo7vokuk9;jh@YPFlu)FV@-| z1myN`f$5>=ZrH5_y*-#gm{BSlELZdoPdNTDe8Bhy6_SC(DC`~J44L@GEr=r`s8$b) zk=XwbTNX-A?iKCHwEl@4S{T1e6{P3XYc=!%`v!2x1I5Kn?>4~SrVrF%aPuj{JjFa8 zRz**=o<)c*p}W?#3}lkTq~N=!*70E+M3G5Z+}hO8HW=c?rL!WcPriw4i?5e=!N07p zl>(d=Lv81N`S4adDt31F>A4sEx|fHJMCBOEj$(_%V)bTk8M6uwwEoa@-w45!5^cos z1f=#Irq&k)X+EYjk=oQ-;FZ3VuH5>>4<)B%20mT#V`C9y3Hqwu^ z>A9r;rmDj}Z_$D81#IRzj~^ZS`L;)cME>krXGumPt9YV1(3J1a zi`ecum7z~S9*hx$Y%j1FIEGNHNujALKBz`J%6)MiUjt#d+w~eC9A^Leh3StauPm~C z3F}0%Tv*EI=-gk;ROz!{GAE1fHXVWhf`=NPb!W`5s;o~vDDc0_U%8*Jx*_?LGLtFG zG+s4TRJA^5N2yffLK5YuVG#9khY4#CG)V(iwab(gCj{A+`ykz-Mvm#-;5Ep0sIf{b zG6b#shJBKRr4nvz8mkPRrT~IrWh$F{lf>g@RJ46rO?KWTK6)k`M6F8GL4I9{PZx5{ z`pP@dN~Y(q2f_=3=Y`i{SHy-LrTN&8qgaYEB^JUqvQlCuRqp<1T-M{ zS#t3egA})KiO0xCOB92NxmR-k`D@DJzxpM7K&5%6`9HS=TTsBi><$>?m)6(+{^dc! zjqNIhLY&9I;%}16w?W9OcN~tCgnWtQr@c-uGc|b=(oCxA%Gp$Cc*E%1?wM-T^D!qw z`(6ldD$8W)n>sf!iV17CUA4iBL-jv(=*&4@?nvOaeSC%_*qj{gf;}Nyqe^o(kga_t zK0ni(u?00o;7WsBdS`>kj}IPK`~&&q{JSrMMhpCXa_qxH8ZcH6@@4Q$LOQ~OMc%Re zA6KwRvfbpntI*DLV}mPy5KEt?%;m9nteI!jJPlMJU*ghF)a1%R;j%3+ANSw*R{%ep6jZh zl+>YVKb1Wx<&*ikh9AV?IrKLE_m$>9f298b-T%WUH$xTa(q5Pg?0qk;i}I7sOxsie z`tipwLlDuXLiZ$Oh_W8QK%40&MR`5bLvsj)0VZ@d#ZYx1{-&u!E0gh&yMfWsU%|UG z+2H+zA12es&Au14BOXc-$wooQuA6b9>m?~hy&b74nA($R)RU(1{2|m~0{Wq1!4nel ztw_pWZ^3ALRzaP|&v?S`xiQ+q#BA;{u+IuS(%Dfl$M?my^8%uV^_n=>J%Qis{coaV zA1{ya*y~UgAt|CAw~G0L7|!XLbyJ$bMYH5JwH!|kozD~J+OKUipAWTdabgDGE-GtO zhs#aA0@+V?o_qvz7M}D5)7+6rnQx}DE-5q?ZSy-Ku$A?^VkAiVDF-%0uaU|!WfAOq zc1y=fMX6HmH>I=G*nhg69K}%^7GVILg=P9$l52M~k1CgN&y0d$16kZ!!x;$4(`q=Mv8`$&XxwZ4|permp(271sps|_LQ#R8|1z}L~pyaE72u}u1cp)=PQk0(;XlpJt3sG1&1aB>c(YiZjz z&^AC3S;xvF0>qACM&9d^r%FmKYAiVR2QT%AJ$ifz*MVFD%40Z=e8Hi(RvIN}6k z1vk=v{;S1xFzFTI4354n&(hgBHXUh+iVkMvt57#E=S~(nMyK*9X5E1#-BZ zHU?QuOlKTjbnJARd2`#jKDP(Uui{r@4AsV(-uMeRctNg~xBE&qT==I-D#p5VANz zBHxmI!XneB`1!`g9<@P}|KH!WIx&JXGv*gtxu4Y^M^A>$2&Ql=Pa6f@e&h~OP!800 z8}g@hhLQjOGWi;QnUR5*CoM)@hN`d|y^`Q-;<9-lrOnDND73o*_i~!K0>GY6a>7R* z0=ozXOsaT*o~hB8vKZPFN&0{KdV?_D>$W`ogPYMKDddV`0N;gCaSFykDaH;|#{;EI zCMQZw2?B3;m*8i}ivj3DJeMTABf(D`+Qf4L6?Hu{LzmD4m2`nwbx={ap?lh6QfbPm z!5$}b4n8MWFwudJ0hxod&7}1dyi#8&hQ1xYThOG*l_;ULVvx_#FKbCE#^Enz0sudr zww!12q$`JZU3a%NeBPCUx4Q9*Al4`RDS=(F`U@0SwBaZEadQFwH|5&35_RFG6P(fIB(veESt;-+l;qyBDDs-#9C%0D$z6YPh6zs!{WJh4GW_UBEp`IQy5W9i>MeZrCrB!W*~nSavtH`*Uq~f#vk=>S7_eA*LU;L zJ{t9t-6H<``c*+_HgSRfeJ_^jh^gX(jvK3G;h=R4gSM=(QF`e`*q;ai=d$5URt<(d ziKNVtP_n>&n1gY1=@zUf@(l{4_GV*7pS2_4W3rc7rT(gWp3_Y+>~pKF@&`w=miG zziY(SDsnj!DP!uY~Aoe zdRnhXU$54f2G8&UW@BANduOo0($Zjjgc0%fUlj>;*h_rNhg&}dmF%qB0Z>gHKmI^C zsX8czkaFwlDdj1wpE<-BIR>gMhMtGeK~ne4#Y2*+U=f3-{bfker?X8p^#Til<8$igQSa^_5V+&ID7qRT{K=)32nh(^Obns`f4kyiR zhE`P#%2y{O+Tsa;GF^$=Wd3@}4TQ3`Sc$-8N zuQI7l3!|SA*yHlHx7N$-hIk-f0%l7Eb87M*8-=G%-@E1X653mQ0q^rjxGY_MCZD!J z@21h9rmD7lMkq6%WXJN4%RG|SYqra}u8vdkZRE8YVa4g$e8;@~Z&ojNMeNvn7=ZmN zls6da?oWan8G|?W*0TZp4;T8AQV8B^bGp8}hmRk*SD6XR7%-TqZsj#4Un^p|% z9^zak1GOCPO8Q(qe-`wow)!3IE06-ke7EcIT{OF;=8*Ah#I2Brupyk(s*zXpGn69W zAQMMj)n3uJo@EVu&7Y3@3rWC4AM822{bbs&@9(m>{lphp5O_=_1=AsEE|EWpS#A~s zuC?qcHTuys6e`Ek?ogDLRIo1OXgoh3$vh|S3{Ju8s4AieV1jR_cOWH=-{aBS%Q6u% zc)F0wQkY)*5#O@bO`^IPbXrxZd5}8M_A$9m0I!B-QtbV2Ni|E$bVgZ=a7PMRo~(;A z4s_9tE_3ca?6{fk32{Pp)5Mnp_So!F(H7JhvU^hTL zuNrB?Yy@#RVgOkJ&@*%Te9gJ+9J;uTgUQY1W96;m))T%@3TDJB8z*2&O(@C|o*{Ps zm|NDcv9t?LlXS`8PnWVkg0-d1`Bx3?i$%Dv>9ipWvA3C$;^6;+<~jP7#HL12xr@T{ z6TQIk4=x|hdr&k|%OF&rvJ?UY!yx9%v^RCAcS6N^Xn6 z-|eqz=$g*o#@#=Zr#A~M2@ukyFop$!@KUWF4#6a=7%e6IJU+FkjlDBOJ~r>hUPxj8 z8vm$e6*=2t}JNrIOs}#-VAVG2TWZB;5zm&^s z(u26Ve5T3xgxQUe<@|g!U%%TLlFy<_z7p2|TJ;u-xpNC8_7Ch9j;dgfBAO)EMOkQ! zp3W&%;Uq>$(SU0xs;@yThCN1FDyXBNG00)WaODYQhQ`d74=MK%VgCXd1Q@)WoyFh1 z4d6D}wd~E4c+(Hi*`t)s=mQeZiQ{I^nNnr^EJ|Kk>g$_@crp`jxoyjkm1fWd@MNJ^ zf1`jFujlH^QbjrnM<%LxxVibdXUSsZlWFOJmrbiDDS{A+5E(spxTi8K?bs+sRm&9- zvv-BFQP?RV6jIc@yj7}QNw!css z%BCsyhYHF7=tb!gmOXG%e;a3{&Z4@|Otw}XvprLiqE!VgqY6nj0}6U=)E}9B*|OtZTI&q zkeug+3bmL)2^o7Yy6)ERFAiq!`p$6q+*|nH^MB!Ic7C)bP+~@OrK{vlj0Fy*AD~Vg zsQs0b|G7s7ZfHVIBv?@IKZ~=o6iYH1nc#`btqn~iFsM+FecYgxepkyUwewKKjtEfQzC&NX45O};XLmRf!t&`uE!@|iMp{LJd z5|t8R8Tu$rFga#7<~z@9t|YSOVLd7AsoT3%wc;!(2V8760AB5+r)F`Z3`MUo-zL3_ zExq!GkS+o=p?>&v4qU}9!iM$-1n=9TeuKH8n?b~|x)}Ls_E6(JlEofWIlTxC8=d6L zRVL9UB1Qf+$7m;A>|Guw<{lBZq62uo+QS41ZAq|*`Z6w;Akp@$j?FFRmV9H*-#li_ zmkI6VR2&6Ql?;RsCzeN|C~iE7J*-?8&N-k1R&-nSd_~a8ubKP%;%=yNn!hcjpoF|W z^YKI%5=iq&Pa1MIigD0}dW*7;gpT_0lB#~8c`BEWy9&TZ@+a|2Fv>UeCcQzvULc_k z#7ThUp8F$wV_MdAWm?%B_PN)=pU+6ti%#kfPXT{TXZntK;oow-YGW4~jXV0CnODey zUHpipw{b1@LFH z1sNW`oIP%p=qu62f_jQKc5Rz=_0QL|`c)47jP&Ea5O^?41#G`rn{`lDM$T?it821_ z#<$zrqq8a+Rgx?8X_F>`Zb#+>$0lrEo`)x5%c6XTP&dO!1>l`5C(p0utca+DZ0*a( zog9Q>Hl_4)L`n&l4=zPFF(#^qLw6~(ntPBN|A4R!XM4MeOcK5Sg->UB5DDSQr7Fh)71b?+l6P$iRO~KZRb3^3Hoi1 z5`b%Mhq5z0T^q_lxsW!LW<=xiB5`vLvzp$V8350+lyu^P)4^92M^j(d)jz|jO|3ij zf^C|?&Fr4^;qcT>#kbPyP8&~l+>e{!wA*-l9uU29_hh{;R{Gp|{uUZj@~EGrqiyqvYmA%&zC=0Y_-*yHKg-qoS>0dSiC}# z5FKAb3-q*1ZK9k}Ex$3UfUU;HX+jF9*!Y>xSf5;0#zNen+$czqt2^;;!j_vy;}q7< zk`B0i*iWFjd{q~dxyNOBqqQO55f0extHnZw+P9xi+un8$r}X|KAg7dlT4ZAU0o>3> zIWcHKvofXZCZLm{ATePS(y+2e?tlJhhvW1PcqX+7GX|;a6t~i{DeRDfQmXgU?N6ugU8fsbluU_C0wwW2jHQ@8av0h`v;F)K z>vU8^=(Hd0Fj;PL2s*Dx&)81Vb_w6Dul_BXXo({Ia)1H;cGKto+^K z-tGQY0?SOx0GBjgJyJ+=chD}4W(<0f>_HY*NG#4@s7bD`u0i`Sn+_*$!yDt$czet(#>&bzozqS9=8UqOt>V`tO4+ zdj3%x)$PeC#3g0l8wR(36umIA<6QTemUY8!Z=Uc7RF4&-jUmI;dqW&3>2Om_1mz&a zq81H&qUO<_|DO)9>Wxs>Y?L>ypQxyaoEtZ?OOnQVg^5(|LOyqbbuPE^p~kBFhLqU?&o!lGRAN_1uTe+=c8E7bzy&S{QQIJC zphT)FdthTyAyZo(^TQWO`nh8C$UY7(3sD#INt;lNK9I)-`B>&&>0>P@EU#mGK;o$Zxj^j8zs$hGE`#Qz?&Cku+O z=83Ks({_Tv)$_sdK;Ns(6^Ul|Hg;Vuy)x6o)K}K-)}HL26}PNT4I{*_#!Fo4jNK3Z z%lN}1&5uQk1i0nhL4|H4eu!P+9@X}%l=Jax=~$Y)L_bXu4FT4l+9dWWnn?{ZivA!U zET}o}GYW90M7*4v11M^}%j26!Xo|i`&5nA2APiKCi)^vUX>?3%jvVR5q@=nu_vd_=D#{PH}pBgoNqBf*R2`h%nm{-v$4 zH-&kcG0f|y9NFpE#^7c}xT`Ipmm=no$fTUKjtv4l- zC8P-m|B8Jz6c$b}?i*&+WV1szeN@0&|9+2w|rQOck(Ag%$UD!Ccp}}e z%xHj=RBmIaugUk7y&I75dOWzPkli*A)cpZb--Ljc8a8Vb1F+E{I^TX%T;7fdgf`;~ z4m`MvZ0mZOZpb0J-nAPF2U4z^RHZnozMR=98>}`gSP8}g4Uf7tHsU0QI(xxZyl3(rv2aq${mcYkzi2-cP5;@^A;m%uDIm3(N)gja(kVx22sI5OE9- zYEyz&O+cv5zkXoVk!%c+$EDM|j?~Zs1kh=R0YLsK{OK6FbGn$=)$zzHCBZJ$a`M-o z$YIVbQE0-e=73fipyM1QtaUIxc>lMR;OljWuV*?KO3t-~HWv0zRL5oM)T0S3J|}_V z^8?pk_Uzoz)zH9Xk}f`n2hl~j42nuv=_I8|=gB(LOVX)T;^71dEMmgKC=uIB3;pw` zwK#p_j)6M;kxt!!1RHMw1<$sapBrsCgT0A5Bax*H+I_~GYgo-taG6zb!ShchSnl3F z2v9#3!55KQ{suWx;t7-eA|e9W4Yy^1mfbnw^<7{4>i41tN<9EwzX!H_L{EVYs;+fr z@b%{8lbN5oRlAFvpgXgbg^Y_2FZIygd8*2IS>=wZNS^=F|N3_SJ>rh-(5qT?aB>Z` z*j{HN=L?YM86loa1sjwA)*KjqXttMRwE<}>Ex8D3|Laqj7o2d>ai*qrv}jKUG=0dzzatzk=rqlvc%jyAoN%P z`ox4ZICL)>*@fuc=t4X?-xi<~ayy6b%B2HCo}0;X8hgCWW?7YtcU26SQmbioZQ@0? z?Pf$jn{k%u49S-&!gPBQy0UXrJ<484B!Bo6E=gV*;T zmb9iYVdEwHMTB|J`pd^yS>4(RxhDH$1V9hDcFh?^hJgi$FA1LKjWA6S7v({YH`hlm zp!n`>n-1^(Q6+oq7`SDVSQ&1l*yFLX$je-!tol4(fivBokOwwracg+pvlbiLHoBz3 z=@>-i{ow5dE5L;YioA1%Rz1*U2|QO;SA$hQK%^3ADmG>7&{CFn-f~20)BNHtZ8SaX z21PL1C3RadE^r=7CjjdBa2($DaTt%wfdd7=^uW?yjN~3Sz+KvZwM9rUhtw?Y;tsLV z>I+E3JB2xrRN%ZmW+&v+#6uR>i{<8d|IEWj8cE%&o*g`^nxKhpTkSl*fm$lrtl4Lo z1~W@Z#}_3OUed1SyzUHx--Zn4;*=Md{~oYpph`5JZ?4#~`5JX>E&MQ{`HN0(V7BSp- zA{B2wQ+<={q;c=;hUUx#m2WNYXzh}3WUC*nx{~sA+Y!t#dN>Zr$j0+=dZhLrD>N0A zNuF)ofP;O6!FBnDoOC!~^~fwxeSKH1Dd?I4S?$a3DiYD8x?4O>a;lp)Hs)W7cC(~> ztL7cgMa#>W&1^o+JJQ3A;4T9tY%ZQ`h55INIp>Le%(ZA>$Y-P}tSFaZqc=*~4tG{xI zKB&VDO5>BNq=uT}XA4Fv^Hp>fC=n%dNj z+URN94WSDMIl`e&ZF-hWUK}rFV-+_tI62*8^2+ZphXbrPzK9>A>gu33y11x547qT` zn~VCf8~J}cSg=ErPsk2}K~@2;2#YWSfX4x&m%H!FhX-Vl*`eqe8L}KQgUKk2!Okih z)sWQF6KoExM_(__&nQxbi}A_2xy>*AGMivd9jrcgXO5PI*Om6%HiO80cY7a!2_z)x zWyCY9>L^VG6@(!pCv9C|qxlQ|MLWS4%E7FWKN#9|tp+1vsnz7fTE9tFNt*3Ci0mAc zdtrwuoHDNePt zaq3IiyHt%Ty#ClW`k(RZ*;|Qw1j>8AZtA)|g|NqFa%4m&Bie_^)YRINL+g~9#l7rd zx3t(MtrOQ(#-z8`+C)f2Ox-r<6118T-LPR3*)Re){_wo&mImw(gwXH>dW>>CS1q{z ztV8ZM!Sx92dFl8K9xzY>rq)9qiO;s&kDMF4P56Rm-_wO%|4b!udc|OQWqrr-#2u~W z2q6T43 z{H<4e16;z?JN;P#=Pzn9Pj1v22wM2x1{(=RQb=DApPHaU_tkC_H@~OK6Or_J9-!ms z8)0TJZ%JtLWmHvub8w3nVFI^$MjKBvg*c?Ok?aQl>07-U7R_rk=q71Zh6T0+e3-&8 zNjKRKUMq7M*5h}id)T7~;j;Du*+2LGp*d+KI_q!Dn;PgL(10zm@ zNXQIY@Os)TW3PhlzKzcXvX_H@H<=xq=$VY>en`}UwlG?rtP-#%0%@uKPluv%3c!Nv;S`6dV9s8(E9prNI&Q@Mqns^0XF#GNY;N$ zIbBF*;mQ+hZ&wY(+YD*fxR>=$u=sWIC5!Jnt|W7oYIZPmST*%Axd65^GxV73DSm{siY z8~9CFEc9O&Ayo}uSi{I!VJ=M28h5Q{Av3}coQPpwzP>`4I3*C!uei`VA&EUH=jJs- z2^OM?>fA+kyK?#+gluK%OOk$a{2W&i$3 zj499vu(n+2WA=`CZ(0c-;t5}=ayno^N9&{A zY#Q>->;c&!8VMVtMPpXQZ_JswdUv{VmdZG9s^2QeFJmzJTYB({zT1`Lh=`cbDV3#* z;{Q!}K;#(xF-)ILMF~riWnX{Too_dS?(~^Vrhhl;!7S2HqXd0|ut&d~>z1m(dBUt+X9Ee{=@+uL4-ocUVbw1!j zYl3y5bz1V>$}CjJo3Md!1>OiCgh!ma)cRv%?0LW}TcVMkWU8!XSZ9dy5A?GyF*ajDq?}~aN=_98~vpX4} z%BdJ}{KLY6`R!L@vx_`wuyT<;F{1ab=h~J-m%bRksFU|H#kV_kwd5rEUG$^KWDb#( z)-6Z9#f4?}Lc0+1xxu0YvgGlJrnRJ?+8Z@^>}x4osDCOlO}}CCnXsrBULHqdXjFYF z6JT1aO0^O`38t8ynu%EFi#myeM`DkT4n=(zWe9~!HTuZVxA?!lvdZ@9i{T;-4&}_S z)$Iac1C6(=i;{0}hNWQ{!z~%ObnU-!x1}tqo6P>os!k^f#vP4a&X>X_2=#W($j&il zHmA69z3szbW?93B&qFfd?{IMFlA`<)Au~X(ZC%9y`dR8b&p}iQqk^k`=K0gqF`?d$ z^xG0-M0v%G5y-IFD9mrFa&JRv4ej&{^HK9l-B}m3 z{{<)cAo$o*lan?G6l&gKM1JRaL$+KImt9;FNl{GsMXRk7c?F}Hf~s%2nwPHnI9*A{ z!oQAncelJzV<#R%G=J4L+9H*Bj{S5#I)>aqpVZ2H@)^6*-8caVzC@#<<~Va|5ha~5 z+Ps5oW7=6lTFqi->9Og;;>MOQLR+gcSy*KOEsRy+AZP^@*M4o(3Re}ruVNv1Q*Xv; zEp7UrXr;3Mm4<6piofD?1Mg8N1Ro76h2La5?9M0zWPGca#ytYzLP#;Wv-QKtNvkE- zLXy55gw2xRQ_4TLp%kZFnAlg zOk+x!LYE#1vA0Nt$uVW`rDsuaAi#%lnGK#YA+X8+QXvq@W;~5*n>J{Q^sZ!YamC=^ z`o6R07^mBd&lwpVBzeHxLsKFsQIhnabKQVhG{8K^E4@oi@Wpo_kmGF;@5OG$7j%_e z3_>2x5tne#3sE*Rc1B&v4Gl8xfoYzw6t5U`T$1%%B#($3YG(#|Eb#0V_FZMTtKt9P z()OA~3~sYH5HsNlfznt(hJ!~MOYR7VL1*#9u=z#Gir9(({Cim9ck>I5i_CLmrlct- zKNS4O#+;b^JtmBucf=DsZnehPz1-4<%j%i22qTZpsX z4*>_RcxhO%?5{1H;VUEcA4zQXD(&uXkfeif1;6D`3JIb~)#Vq>% z*UV<4VW7}H`=D}C1gF;cqQ}3eauuL;muBbM$LxOxmxw5)VW447W!S_y>+)~^TQ-li zmQs1a*L9c|(f2a~B6)NH{f@#V7)Y92DH>g}#xy^hthZ%O5bo&Iy21OC3^=%z(?_Er z%#NJ8T8^T>T=c$Q>1DsRmH$D*gUOBg+oe{Obj3A zg}ps~s!b~Jb2%hXB2h`hC~32;{{^Q1J4@7EQcAU~CAGTj5F#rwx+HotwpmL*C6KTU zud_wvKC@WL$=4b5%YUxx$UNB;!)h7b;pg95A>~V}XLcE7UhSKS@qF8-td2kR>3IWu zTnTlTZ^x9`3|%b_L_lSaMeQB1wBTI?UXTs$LnP7>raSaQ)MbxASO-)Tstbf8Ey0n+Zs>eMW6F&pq+9Lz zqPBEzHH)iD${$G>x(@#@pM2v7q_zcQz7mnswOwBqw|u%=>I};7+-nL7!hft$I<^tq z&xozH3^ETa^=t}ato~r1sC(i#2K*5n@xbE*`hI;|w=JFDw_wkrZa5&NO;C)`w0M}y zT9b z3~+BW$lho-@!PQf`=9Zpi1&1_`RB*AxhEocYs;QZbORv|Rx)v91oV5rNzmIGHUxt1 z_6Br7;enUPMCx0ylKZz~S}JGtj|Ph*E0@g)l;q!ZY!QZJ?WFrz*Rne`4mMtrLF|zSJnMZ|;ac-J8o6zC)yfYSs8l+$7>iT8O)&@~a(_>UX?5ArGrKJPX zMt7H@Mj*zagFlb`Si3?Pd2K#N&xFVOd~A&{KK&z8`FL!JS}JTSVH;EBgZwZnF_Q=4 z1h9efFZa#-)lFlRrS4Q$23`zVih3Q^%TW9bALU#$0)?&X+s!LS$iXfEBPggV&&Ij^ zB9-X(gu-pjAO926WhFl$hYy7JbY3*BwF{E_m@gM>EaJOy6gGW|rS0X*-hhFYGPc2! z4Sqf`uJCa#=b|Vc0Eug?w0Mnh+Ve1N+TR2HeY*dxZa!i@P9+Akuu1Ufd*?cAx^L}Y zEWK@(KBWCKS<~vdv1G^$=Xzi1fxf;f0IQ_9&-B>?o=WUHEYddBd1_pWlvyj&h-%Ho zn9>Z~QkVwrWqjFIc9LLIQ?+V{x3s;L<(3=nQ~mq~YM0y*8SFIMTax{{yQgis44(9I zIa~^Vxz|rR-~aXMgA+$K>R7V@w`%IJz=^1$Vy{fDF(vnOldjPES$&^a((3HFyEOBq zAD!RY5AjZEXe;CMh&N*Iv9zKyx`})P!`cIezr3INUm$^fC zTHOMkGmjz{c1|}N=0HQFW6kXqbX%x-Fj#>hHC~7QICPP@hT8j`9tPOtsNvB@d?*fM ziqLl=!h}2iTjqj-TQdL8XHf@+Hw{N-b`&LUp>VxF!4I|`mA*_O^Ax-ASNExkYHXYA zrpKp$-c9e9nK`*$Hc}P|O;rPj-FL67!GpX9J7&U+P9hQDwWP zb$dnfmwuu><08|W4*(GrewP{FU!IYH)8o^d%>yH-xV?g$s;aJ@&ShPOLiwJ+mkZ2&u!clKC$C zxhNJ~n8$_^ju15%I5#iz{Z4aQf)fy{D$e;?Q_W#3yPawCO8IltBl~74xmoU?C0cFe zwvXz|)~~aKaXmdjrL=!#lv6G_8YeMRaX(=XG;RObO2`GT61 zH_P^IG5P>w@!o`xKlBwwPhr-laY2_V6Me-bKk(taP$i#GlUp=EOZSQxFT=b7RgE}T zEUd@6_}yQvgAJ)<+Y8=pYT4NSS|D6aBv1H3S~5No-9xA&K8W|~ouzWSsaub%$o07` zkpxxHT9U{cdDF9*5$Eb3R9uYmU=F>h<`Pj-jWy9PUsglwW>C>9vil6 ziH4K7phqsX`AuOlCVwON{ZEU*!G0r>+gJO63UttGBUd(dw};J4zYEcb68NRi9w}te z3pPcVIVI}3Ech`n%}iPWqQ6n!6{O5L=zaPBlyCpqarGrE1L+DwlY$w8Gz> zVbh-DqTqKNn4Y)r8W!-}epJms=sqdyZM-V|T)SGIVHKcA@djmkOZxXjbni!RS%C7F zJV*mXm|e3?f6vl>9owB0NBtb1O=SaNSqIT|r~jX@SqBR*R9>*|7moJp52?JV#&_M8sUp-zl<(_W_|EZj!sToiPp^ zmj4c;78Bh(jTcO*U7YVp1P>8rASo}8BeWHuUg3QwG35ohkZWaxr;*a1D}%qpNPe*y z+GxPhZPxbu8hUCvikcoaLRbd6W-zlaN<+Is#_39VtEpr{9o7wna+rcp$qNRLPp$;P z(Srp#m7;l2r#H#*4fg2^a7oyTt`Q7{1IjE%uL;IHxrN+ISbAMzzui*Q^~@7O4U;SP zi3bZ|nRZT1i6gUfdx9nfCtG5MOZ)l+HGf83qG{VOJzCStz`|MBWyiQH+*Klq2nLE* zHxf7so3|lBeB^U3_60A)*sW}bX!-PUs;m7Yj(MdQ`&if=VoAaNaaRCIqlBL;it1+o z2da;zC;2Z6U=a$QsJFM&)(I;_7A0}eP%Yyq{X8oQNAWLj7@=ug*f2TpYcuLZEm`lD zA+@2L*LYHMJu0$T;6i*H1cxA>OsP!rPqUjK>ziohKsc!{2JP4R^iK(=iMVarxW4*F zNS5()rcB6EncCY01l(uClwA&N_EvTjJY20FH5-CnLW83k^(KJ%znS57l)r%q#`};7 z^x4R37r}B04g6*n=BtZ*-+R*%%-da4J>hum9pUYjFKQZpe~J}MV#*h@rEB$^(*=ai z@~KkuKVo8v$8>=pb0)W0IHQR3&w2>}q9i%F9O`1-XPR;_Rlc~VWVA9cdJS?sgtWo3 zn5ZhnwNVhvv%UZbTf3uU*}sWDah#Q|s>5sOl1xLBozIwND+I#6P@thiduA;%WGVc} zk>ZOewJ4y9KSj6S$gI=gu_gYNon&TbP(1hts6gtGpL3HM7&0xuAsB5jb%L?sRCULuO+O0&oDG6e2I}r(W7qh`88n#v@BF=ZQu=wt4Wa|;>4OoDx=o6C)(-3( zeoN5=q_RRx-DpABr)Z>g96hOG8{yX&u&wIQ?SbbTQBrrw-GLNpo$V*HIcJj-b~+o6 zNLtoGeIahH!d4&W4<9KYTSa4til)S~vh(PD(RyWN12KjJuNGU~-yhZg`Lab|d=Q0D zvC-M;b20Z?eD{B0#Lw2_1k91BZgfx`Hgw3X=D@m~axk3wd-<%^B#qgA$u+fWZ^ep~ z2C@@o6@d@1?py2>2Hh9jg&*-wJCcdUx1E8Qe1=CB=hg-q(`7bFqRbE3i7X-FqAtaW zoWdua%HOiLMwe4%WJw5=Hp*v4K&x&ApA-W z-K%*WubIr35;Em6BuM=zcaL+WRlkrM-%l(*jJTjWk}^!**KlLQpoE2qv|$kE{6Jn8 z>i9Yo@-;RdIx-ySjLmJGr|#!-Ulo3!!8kDRssDDW1&5*wmNF_V_>JL(_`K#p1fSPd z@GCn#)>YMZBb^o811&;iEP5{TWyHuNq|f1%$}p=QaVybPRT*ok9xTCBIC3P=auk)s zx`hrbX=~1GCrZ`H10|gvbsQ$h3Y@}tIh-KTFz7P8>|8Qgpf9~a*MqILd&xWpuq_I1 zcE}=2Vaq{K({gczfl|^s&LjD)F?JA4HvHWtMFjXy7 zAaO}L?;Achm2KY+m_WH7IM3z}K_V+d9d{z-iqb5A=W1Ra+&-Q-m%kccy_Pzy^+ zbM5f|oR1DM)sPL@wvv6bZ7+?hy-N?|vGyY(&Xj?Jn=8(i> z>1J0gJah>}xAFh0Nvg=n!vQQQ8Dd{B4iW7FyLNFW%`3|{K_V7#xpE}y7)&!T;%S%> zCjBeNT~eYM$72`#nsFA_-*f!m%RoF0Op{fIX#3`l7aU$Cbyf&RUgzVDds@MyS=0Xa z)c$V;a5JR#0m?cJ{vTy;Jegi!i&D8o;SC-(EA_xSyRNRy#;biQ>dD+lEMfh|hw+me zE6=B(w}aPPTMw_e-mLKyMj-?N^zS`yplWdNicU2~En2AI=)^avx7r%Z;RMXa z$VyJImZ(Mfg8gRI08#95vBd#`guvFXoUYe(jhC&Riv~%(mUGLfy5%IilcZ)_ z#r21ecT@nFeE18r?UyB_Rekw@fW~E(^=+1`l+Yl(&fGwUyBIxvz{4$@4<43Ac)~kn z?x1p$rq0Zob`}MUFMRhi1S!T1Gc950wWhY8!Dc2xXt%33Vt^~8j;gWj*wu#UamxT; zf0{}C0q>+k$ReKDy6KZC*@Sdu6YcN5BoZKlL*BEj-X>xko@?L2tEv*CPt^LG47|R? z-ex?^Oxi(MqGqExsqbqS?FJLg&x~M0jjB7dtI0k3lb~D32)-q zW(7hSZ&yMDnG&S*?5|8e=raFEznid}*;JF)JP(!imNM)z@$x8E$oQL}Fy5BeYpDgs zt}WpaR*?q2PkoXWzsYFZL8sME`lK`iFIKjc@SzFV5s7)kA!yyuZP4^|iUU^;e}$I5 z{xjIIB6-Q2%Vqn8?GvQotk??FPbF1e1N_1j;g2mP2#q?`{)ywp+<>tBX~vU%G`@k? zEthH0@u?uJFOJQFEpEw_Q7$(3@q~0h#xjgr# zW)8Ag@XH5dP{TJZ8|q-TwS#}E_yt7ns*~jf;1<73##4!9~xk0d>{mS#6k2H*q z<#0OG9hqy0wR)5Z6d)zNiq(f=XI~^ej?`RTS}?)?IeJt=3jXHHWJcc zH53cuyGKpUNmbWdH0j3hI^e#%81&`Ned3c@2@Z`x*^kru@`IA*2l8+Mf{g^_;ARd% z9a8SJ#S-veb7c!ZGQq8R^z%}X@r4z()`tEixjz4hkEyD2;6~7jq=~{{i;0wFgoeP? z%8xwcjUn+)&GeBQcKent!L5-bCmXHFNVu3&cID}=Qzf*QofqsYhTYHk(rY6A1)-~9 z84aCLC$XG*0dLucS~M;WC3+gdORR~K9_{}7`pouFBUjgP=l6J_Il~UV`0m>WcO8ez zs<$2)x@+nC=`9qdtzCs2&b>VFr*ypYrijcL!pPhwq$|Q{Bnkk`szq~y?{4kDlYMP& z_6|)BCigQIhvz$mx~iGlIY0NH{(5k)W;wX7UA}5(VJIS@@mlrx_^;X{?`w_c6JAOB zzOUh)QO8gq#?!S}ZvD=TR=YyawpP4~sP*gEc>jl{YOBt&I&ul7qTi{zU0Lvi0gT6! zN9C{VY+AF4{&Y~pUxo#gfr8`1&R=8sk*Q}BukgK!)G_)gtCHACdhu<{D+>me-(tA} z4dZx0Yct{JP(q}*71!?D7_HUSp1D_g+-+1hp7#AV;P4N_aNoDFw!Xtvbi@#}c(nD5 z?rgiQEyEq}_N8_BzISb|h*_oMv0kkXc2qigB5D^}eT5i-kD9`g4oH%cL&sMowB0#$6^p@^{2y&hmTt;r@zK3)K z%85bvwSB*P$NcxFw|77uB#~;broF9X&Im}5M?8=k^z+ECX&<$7ag{i!x3y zOh8E)>+~u*kQQmWzuLM@ZpdzU&=GThm#fh*5}rY&70V^OfvPuf`eWIH1nIe4Rq(xh za~J!^iSXYWw!E}9QHAjsb^w-^l2PzbX&93<@RB!>K?l%+gS4= z1^lUe{U{m;gABvrk-NE1N2w5wK2eo_$5*iTLG$aq{}fB0m{IiKEo=P zA#VmBz$y~qM95z`j)Czb=Vxp!8=~(yIW3i6ChPIEL42^`xfp0Yd$=N2!93$V&bgFV zqHNuZpT+#{FXDHvPfjnvqMfE>c^S=8&<|)zN~;cUj%mJFY(cCcpt3xxR**yd+CL`( zJx1oJ70~Sr_XcmST@!rJ%fH5NVE^}#XitE-?yvf3AA~`N9$v$6@X+}>bU_zVVesI_ zk`zRG3Vwh)sdb}6XTy*m5?cbabh$}So6*Nie9an-kdljR?X)FzErQzU#X62hx*itP z5AgejFxdY?t9FWcUpb=o6UMJY9KYa$I*CyH8hhOHmpAL|llil2(R=0*KTNt&05i zduP))=PFXrV`by^1WOVoq=T}9tg$!jj!>5>AxlBR+c3k#j+Xh)pg_x35W z(g!NZwJem$kIn0NiX$UkiHx5-*NA@%3g}a$*5ETFNl~71#4*=tm9446dY7JCTp|~7 z&uAf1sO&2LgNt0?GQpTBJv`^sJr@|Aoflu9Lf_Tm4_S!(KCR@(@p+^Mr!I7d9mO2C z(JKG;hM(JRdwX-BLYZhq(V54me_QWd2%|M~WphgO8s-fO7t2+_HXD%57tr*_F-aeO zvqKasR{o;jwJa(l3m481UO1a2^P)BwDNBl)F)|d zWS>atGc*03!Of?F@MBK3W_5wRx2~HnwpSopQw&)OaU9!jQQ<2l1GY?XlM}Ay;EZzY zMyQ{b50~b@mT2FT;z{+O-${07hRft(s`znfP7La87=A*y!X zlKJG5r3zttpAc+{cBrMTnt8h3d zp*(TT_g>xnvgvQsc|J9fR6)_gbpK874t@X;0WDJ5d;xKmTURn@M8fzOo~7A@uyd7g zAzfQD$_43t6={kME~f$((( z*EX(7eO`yABgH*vUwbUEA_t66U<2Pk?jOvh98Q*qV+6$&+%Al6Ek0!S(35Cb_>&V< zda#B5?aON&AxhP^GlY;hAC1QXz$3DQ4da-c^+17lnZ+L(j~U+xgMZ;P%coz9Zy!?+_Jd;wZ!XO-1yFj*xY&N4YF0T7q1Pd$*{>MWwoi7xT=l-|UZXbD|lT;8y;D}ZePHbI4m z>EQiD4ycsm;(3OnThKL%r{Kl}sr7-bcouECI!Fb5p}}W>J39LcxY;ho*V}flH|0aU zogml8pb=$IKDhQbBvS>DPhy=`J8Gf)t&fflY*3xy2EoAsGE@zDJH_Vf4YT`KhL*`L zt`Ma|PX;}u+pd6GZg}S0juYqZ79)^qw&oFTPZThBy!2OgPu#}aOR{fCP??1fW zcH{Y%20<*tt?)qWX;#*SBSpiy?y{n{{W#6Mp+Qv5v5)u2%24&olMdyUAD*WCUL*ZN zw}Ovt>TcGSJfF5gMxfNx&C_w0>-u_AyqQG(m3f+`cs{x}KaL~xAt(njzOT*yC@DPP zpYZbCoW?MJIk^Sv^1Yw9l<7UUE5f?NvzMF+En5PO_xiNkK1YD>W z^$n1^7{Cx%e1=LHtf89tdn+ezfFnfnP{_<>FN232mgZ4O-dW(fz^$;C|NNeu0P_5i z7hP1aY=f!CA!>~dJ!C(o-|Fi4f_rh?RY(o@C<4>0?UPC(7?7&d|9Ud@cFv#$EPO*p zi4cZR++Y0dq`?E#1QD&OJJMR$^A#JO+~wwq*s-!9Gu9^q)MC~-1i{Rmj*;ym4AezD zO)W>7D>&g2h6|7#)SW;69&D)HSC?*aY&n;Et`{h769GFQ=z!q_vS z!k_N2(yI2zHyBC4S7AEYhVV&UW6MOcJ%&<`)s^s5GKlBKf)#r5y!#5gM`TT4xR&8u zu}9Q;ZO!7QvDx#&@R<)!>AA*+zqB~Nh5a1piSioW+SGTb!na8OBSG9@taflrCsIsHZqaUy^!?Uef&1&H_P*1L?HeG5LU7qKq%+R;7;P1QMJbZciwcSnE~Idec?kvpLvMt6HhvcMCC0!YipF zfbX4HNuRmEUn+|p`l6M*SfPvO+Xlt<$91K6>fov6X{;?@1A5MdW?X9$#jRVn#zQk( zNGr;fh7Qx&wFQ|xJORJmhv5io_2f)BnwZ8*OgQ)XPfF-UW#dTg9~D`B+Ngs~%R1h5R^6z!ilr$!b`8-hp*e{ik%MizC~+S)XO{tmpTays4PzHRrRunhOmii|j(;hjF=-~12Q_mT0f z0s?0<-ycZciAanc{-NYB{A+x4&L%1bMC+8GUa9KjD*^7>M2KoJrQVvhR2E{am7`~qk zwle~olC!Ya-eebduEQKeJr&ohQ+H8eRd^@V5=+q&SEkewF44%i1z&A-XJQ-dgvv_) zRUw{avo%V=Wd~i;b6-p=(dT_!b!(=Wgffxmh7F!YBXlfA>8WgcHseVejdd7)2L4Rx zx?dhq(Y`c>(a>l_cZ?R;**Zy}dL-{k{SVxIlKK|yY`2I!gwU#up-TAFr;%stn$Ujh zs9T;a!8?%d$YR5N)qTZ9WAkr$?(S|_@NIVBM6dQ6HWz;PDbEzZjef7fnLm0cwHpO} z8ju=@SVEwoiMIVX5?6MWPOmxR{8%!4k~wkL;uc8Oyxw%n{E5W_JAT`fZOugUP<=AjCu;*d)R&#~WG zFsR2(J?iVA`P4$^?RY8cf#rJ8X4xg}S9jg!xNAf_s)XIbec00)*~G%_0OTjZdb~^R zL~ARDrLl9kzJ@4GMs41Z^zw>?XH;l2Ey<(r({k1Hzi($JEC33FDtbm30$$lcfE^8utN#o<(D0qXl4*X z1|)VnQ-kf2`DfW)h6LyWRyD5Nk=9{wy8^LX4hMFprhNL$nFq6GiWbFN^H8cre&sg( zVHq;5Mc?+Rn{(fYzW(|MhjMY&rUg9`g^eCnzzu*PXVU3|WMZk>3!|7~3AjlNmSol< zWu9bg>dz|o+#UO(N*fatHER-%5T6UMHijw~p+CY(9+GgSR37|Qk%z-ZBe-3_KBe4L zy(pU+eK*fsWf2JLTX2sUj%v(mdUfO0l-eA;OxaZuEc1`@d;OhjR8J7luWPvFT*5n$ zcda=)UI+|#DWb++J!J6%z{_x#aV=Ly$wOWi(xzYBaj!S6*p^qkYGqMY9r4f0X>E0M zDwFl^$>JIEI`B!X+|h*};xngCL`17iCBm?9%33DN;5C{1>+5W7+qaKwE%%+*Z6*Cz zVsrsO^@#)h&CGU5e?@{ymIV@{iWh6%3~dkz(C8wt5+MCmGH=LSMu0k?y1v8{G0VRU zwYy;>DO^tstJ@+Hn8N`I=jY621cF!+K~qqSn*B-zi4U=*_A7lJgYm z1Zq{9VV9YCvDId&r^g&(KlN^!>Iy{D`Dd1+Px;t(A;Ebl4v4c8?ttJ+-NDsTT*Z4^ z;?sKm8_qF@ez8EPg0R>#b)fy0ZX3UILDPaaab5nQxnc`>R$Hs^j{^9`tku;&T}l+~ z9~+fhP+)3#_S**U`&E-`ML=s>c#2Mmj)Qy|SjI>PDtI~`j&F|*RSw%Z9Y|LPiw-5) z42?-Mw>gge*2l35-yF?zzQ9hRkM@zMzM0MvXU>(rDLjO zEQd{vhr{SmWb3K-k;3+lf)8k8N)|EG>E8}*&1yQIY7AaZ_(SLu=a-Cfpkki)%opm{ zf5C}hE>JC5ip+veY@jUOI9s;`GxeSwnks|d_HQ6}ALjr8Wklzi6qNRsR_E8@EG`TO zr+Ekv^uvgrXnumL3HKYYm?8rR3wpz26EM+VKS~@`&y`9Y9I4eT%U64K{K2~+DE+kQ z1(zj({TKXRfm2+fs{MplLt;8TB@_}Lko2mPe&0Jl7>PS>npQ zMP6OivT9k>z6Nou)i9d6Hvw^Yu^96MOHg6V{FF>;N!Gfozv`UbCpT+m1HoG}2YX>aM68_iG--|ERbKiR;n)`sa#)E$tm&T2+x+6%F4? zOq-i)5*r6gfBI2h5UwIiY-}bp=OcXgpJYK6$U#AT(~L_{Nb|nOcUn(?MHF{V*_x;5eL*Q)B#N+QY^M9UU?p zSiJVkKL>43#J-tYwLPXlWWdO@+Z}S3CuB47x`}lKWOw4ojj3i;^z-r zhqwu)0KE=Q1cJ+an~g-hjgc0vgxfwjFx9`idnp5aMW9A2FHa4 zI)*-J;&PnApa3$VHUP3BwwJV}x4L-^u{?`dUQEJzyXOFqCBT@~6|n0;ww_tQl;|Y> z`mQl?0~c_jr0j10sZk&Xfz`7f_*-@B+fO#2w@8jFbO+Hbx&}QFn)h=>wxx#+e6;e~ z&Q(9)S_2wf&TVEAxkQJXv9Q;^0H}my+<3+i8%M%f6(+1&5b_jQh`3E=3iF-o6iDhZ z%o{p$wHN)@c?q9bd~RmWc^)mIawheROIgSB>C?IP`{$L4-wUn5+~cM98|Yip*9$GR zlmPGt*ZXam;6Fb|8RODlpUg+SOxPdaJ&ro~d2Wf!e2_7q4XgXn+BJUqf{ZM`;V%&C z^{aEx9m3kE50yi+KUF*d>ro(?;G_23nw`e+T~%uf$J$T-o&O-fiR{Sdg)q@MA5r3N zb^|^p-V}oR%9*WxFV{^qetUliuC-yDE=EyPiN#VwyNC5z!`-_~;>oZJ6K$mckOBM3 zTINkPO@kI97&;w*0B5o}Rd^n%$lBfWzI=i zLM_t`f+w0Nk0+c<=LDwm#u*sBSZ8b>$xlAx@2TI>CXt?-#TkgV3sw_v?Rd|l1=TW{ zh_&eG$arqUp4^%0j>ijWbpoN>E`+=vD{@97*}14WIo}?VOX2RJJs~!om2$qN96R<7 z@r3yK3CANuKRJG(xT2ocr=-l5A?1aV2)1MzsWq3<1&(1R`|Z&0O%HS94!X-CMafhv zh&8O83%Z<~!$RN1z<<0aCpAatwD%`_R8pp5`QcaNG@@axf4N_l7;$>T1wu~^s_Q@Q z!jz+#z!{a$?>mNzl;~pIv5(PJ?VHsM78Y|mH?O#f+$<*5Lgk{WT94Y1ZaWzgZl58+XI)iLlF7l;=i)8M%NyV5~uMqiuXeix3{#&J21UwThZ zR?I593T`fl9!^Y6aR9N&?wAuZhI)tTFn!f4Sm;x=?lKJK&6TF_FPN@1OWNdjU9r;fiJ$$3;<<(y-@_~owu(n zWtJhUuxd~yC#J_;ZIbGd)3ylldR6MPk8Ns5%?)S?#y4!NSiLBgzJAR!@ zs8gxnJA#zSXKV9t>XLS)0Ih+<$O2KzWZ^aSR1sUMn@@8zl3YZxw*9_gH?+S?Y_xao zz}?LHX#oDqol4($QgRh>3R*!B{TfF+1mF*wi*_v@d*pxa+nc;rJZx@+w3Nuxt2LR2DvlSSZZ6u}`AHB~(Ha96 zF`=MO?K2rpcLh+Rj|)AtBX zzs=FV@o6b_2)sBo9T^Rc;22rlkfrCWmQCu8cW(a8P3CF8CYnI+ooR#+lazyT>u&Bh)crpdqPf964hHpk zg|)RHH?$nG7I;HAF6&@E_x|y?J^$|!=lkLe`GX)ABOU%`(X-!}=q*sNQ0`@bVDN@--Eu9qd{UJR55orgO`a$s#H7w?`Luzpyk1ztPS}vutRkmACM^q9{ zI?n~jKJq5XK&)eQP9O(HNR5gTJph=0BOqBLdm@i?u)LyXB5s0yt--hl9{+D`xTpPk zn-Ik+#abs}P_jVWpO!lpCe-Vnbm7E)=w*caC{qcP7$oP6r~>}m8tXLk3c4ubrZVta zr^NNbIW$fEljQ}hOg=&28YTcBqscSX7C{RYF5=OBlhG(#{2HU<*^M8ylb3E~)}?ji zvt8f)RpFxD+d#(p#k_|2o(vXCqA)IKd=7(uNe!>i_>`tJ|JGbkM+RIFojdl18O@Sm zh+VXS{W4Zibwg?d!d1JjXEt{$81N^6ZI7GEv6aZ3^=s2#Y-P6E>V3;QPQZq7I@!;S zM2Yfh8B*XwvjgY6nW?^5l~zjYgElAdy!w?ux#81Xc%2s8OYV0R)GJ4kvlCeJLo|7z zy~~7Z9Nh$R!jP+jaAooSQ;XNEql7lGpG*;jM3MRe!O*w4u%$&c-5F2#GVW`t3h|#S zR5fkzCit!U{3{#&=l(p~k^KbkA?Q6mwh5CB^m(8`J-Xlq*ZEs-_7Z9Kl3 zSXK?UDgQA} zG?Z=q%SI3OD6-gjcc{eaS0s$GgYM|azZCT9{b4uS$;N)%i*oC7JIX2OS2*hfk6;89 zSpqaoFL)e6bzGX^j>vU1Tld(++htWTV%CmiRuSjbw7Y^>hHD>|9ZxDkO&9zGnkq*C z_1NGDA{$sbeZQLcgVS9ckV?-PNs#^XFQQ3xBbAR0FNDw2%3T9|z9QZrA!|2sDnWu? z#+!2HQ5#oSq`9(jIf+3_rA2DoCvxW|N-UR8VzPyjgwWHM>ku^aV`H*t<+gilW;bQ~ff|*(hfF6{o zVY&6_=W{fz`jq1$nRt{xr+yNc0}IlSV0wyUASzrDfTh1Z^Vwk;g0x{#+&oB&4nY`I zu8+)W@-NKlbR_D}OnH~`i=E`_)D}&F-w7rbjfI6GFzhy}HfHj9PKUS50ww!7AhE1z zPqaDeUWw63AZYK$$zD&+UpXDl_nKakXE}H4+K}KHC?r7=t97nE!TBq9V`hNsH3wd< zkH`G0dHS6%WaYVIFP_j&Y&?@Eg%?m)CDJYx0_$HccitFi_9lt2$e*8{kgXfc72*+a z5!m!SXv8Gfx~asMbU0sUZ$&Ji%uGz{-hp0l(YWA+MMW2h)}1CLe*hA+ z>D?sZ&&jgIi+h?nw-}cegBu1D(NC5fw4eqD#ihM%Ks&DdMmAj*X&`E>z+mFO`ZVmc zLAiYq$0E}aAat!h)tr$6xyEb~NvP24&RX$!N9`sH@DkaBwlHqu9{yAZAo*a@x&>4{ zs9+!l%RoN$XxG!|3E+Sov0ugT@J5zqYA0O4L8wD5@O#;h{n6sXRu+J@Bo>CY>rOwn zyL(q34iVB?_=wFtjrPJskVf?FF^bogfCnxZlLP9(I{+OM5JrUvUy=`PG{Dt#ybfdO z=ik#dAp#w^5g*~6Wm%R)S09EqNFz%FDswiD>86Lb3a#SFRh@#dKYfvvP}%}o;I1YO zayMRg^}mTF@&~AMJzC}%3tsyP$D4*B^+ z3p7Ukf&22b?P8mTxpEkPyC1mo)^B}YbXjkCJ^nN|oQ>*wFn;WMKl|#dM3Bj0xb?B= z+Mj%0;1xl==4QovFsK$}nunAF0;URB%Z$k>nwfM@f6BXDSMK_tU^#=Bt+riU#<@&4 z-Bqi584_YxSn2ge30+c+W0SWfNrkmap@Ro;*|0!5bre*9D_;I1k`W(|2c`Tn)3DO| zS-GVQj&)0&Lt2S!p zPhb~Q)nAQ`+Ld0bS%DaRwAu6PcHG-NJ)jsP@bSG0*r4$0@HbAMUQINgg)0g(xpJqpZJ~j!9sqY50aSz&JpT z?`Kt3b>8>pmP$BS4Nsf+^pJcu;olBp zizkX09wEOz%QITp%rSK|Zc5IoX#SH!ct%x`@KrntMWF%COz5xLEyZ zoNhgf{95D)l`G%Sgq?;zlyj+ zyCK&7xn(9Tw_u;N>duA;-0PM*Ih_56GG6msd)3!=hh`#yIH1|ZGu`satm&~3%+wWH zlj9}__v0AH16Qf{_Bz$we9-%pQtThZJWN{Ai@aZNbyZwvlz=UP()`(?s>|rC_MzTb zD7v{|kK5%Ju8$esLFSg;@sR^R@c_(|2fu$KeaPE|S#8k%?cHcQ z3lbp4!s2hWLWn0V4_j6n91f~{{aC0=OHzC`W2wR8$Wa`?A$tT$2o-C}Q?z8$d5F|K zGc)!&MW^;tuaux|YE}D+|Cf<{Mr|epSJFjWzqy2T?(;W!;-9x|BD@VaVDJcTtJs#? zlsO6%wtE`b+qwK~fqV`)d)u4jFZJH`+^=;y*fn*>=ZXtF`So@{>t!VvZ+i4_+Z??O zJei`c_~Uzo68S-ox1esh`C3NsFs~T^%3FHrRj}&l2J(rdnW40b^mc>g*GfbS_pvem zcS{Q2H40dXz;SGCXvxHak8_wXYdZaYQzbrsZ6Nc{Y14=hchH!zf6uG-zb1-*mDEeQ z?!A)<1_ghoUH`mA?}G?5V+Eiot@^*9EohKO$=bqz=h4U^lf|3r)-r-*DrFbjD7A3b{1eg~NqyX!|les<-V0+q#N_u;eTy-sWCj^GmX_ot_Tr zNYP6VN^mu{Ruhwgv!)xy_7^Uhvc0i-M|~Zz%`@?dCeJ-Q`wRKt*4{UHT(@JVhvKYT zfqLPpuhXgA&9>+?gsaz!Oy`dRzw|xXaZ0Ovc_#}yo|c(Jd0c|bCSlM4{S2(d@ZZH6%!u?C*f3UKk9R@#PPWzq0-^}IFr!uiM6gcq#Z z9Lxg+tu9dPwOYFjYIZ4G7&x8*DKzZcN*MdQ+41(Gl!b^0K$yOZ7*8Zl<6EvF>_$&Z z3D&)))s6+?G*E$djZp4JSQy#`t@i8u@QliB5!sn%SGguL&W z@#FbJm-Lf;_J`kr1{OslH}pGpeV#FR+8=o;r~`EeMBu>QzuF=PMh<6ynFB@2PWec1 zOz#FeKSqNb5r5zYoUYmdWwiH1k5>}ho5QA5F3S!tut93Wp5Xgj*FaA`$?)-R2I1Fz=Xos9vFNQ6lQ*PMMJ=ED8MObhVoM&Y{E760W)Z zgs{&Z-6CY=^8?zPIJsq3+mOMvP15QjT1I+J#SPELvP7<(p#Ji)GXH`I--*<5-{fjk zXR`4sXEG{;c!WmIH@i&ZG%HT@143*K0)Et ztz;@4$q++C7OGl)rNGuMIqjk;F$Avqs#!%IxA;~Mw<%Dv|2VV!Iux;o0hQ&^l;mov z1S5_06SBN(D10RcDYf8MDc0I7T3r=xC8?p>GP2z4U&YvuAdbSqI~MxPnjGHs)RK9^zRa09-P)zE0si~9xS=Yt9~u_l5OZk&=D zjINe}$8$*)(3a7%k>2>Uk<~z2lJowP-`(QiNiE+U4a=CTDMZi6qESq%n-{j#oU%lG z?ck`;dDC~{Q=}EiEjYx1>!tU$X33XeBUH5&lzQ$@Bo!r{iv>2}H8hUv<1ykE9v+Jj zZ;Vd2;}KHEVO*dYV`0f66@#s{^J#j_EH0+AH1KHUNaNv}5ynSJ)eAXnX&KbZ z*E*|K8WJnU#zoZrAS13+^q=CW3>)rg=cY|vi*i0`2t}$cA=e?0sqpXXd7nN2W z<%FN=|9*e}<+iFIz()-dszic6w7gRP;r6vj99dPHz`Rszap8fktkKl1m56{FA&3X# zwapurv`uO*GIRrMxzG^>%!`FCRa#mCq++F=4CwUXMBgr+F~}v3^5^n@&M(Hiy?4h~ zJdSsU9L(CYNS_AV=+8IGDuYZx9^laGoNTS2HMkT{ZGM`pixgImmO*?b>!etOEu+XV zt<1dSLXwIvOyoL$fa)LaOqv?BbWvU$6boPd+YRUYdF=gE6!w7Ei|^4o5`|-- zQ%=SrHi8XJI8C^39uZC^%@oAFK`+rcXKh@S|3eVZ8W@$EQVr`J;(C6$v2CXFVM56r z04~Q6qoRI?P&PUCwm)% zQg#*$IU?G>?6aV5@_~K3l)Zzd&?s9C(Wxc)lC2n z>T^7{x2NZDqeZAHyl$mYr-`SFq6SWatn^yqyWsKwI@LMkBXNZuj~|eBJs;V20#<2J zAw*Ao4TN6FS`w+;>;80QcA?zco;VpB2^H_90w!?+kDkW{>O3#K|QOZcXx>uAw!T~%MBvi4@CEiOQk4Alfzod4U>gLkjrq`iR@95#b={ zFt^-f(LXlE@d`?9sT0dQbZHscUM`Rbe_Q6qpR|#DyAOg*ls@*cso#me7W(Y?&kD2@ z>6;+oS=7mps{u`!n56oq20RC;^7L6vfI}0bQWL@-);Oo)o`Te-GT7&i2`ItW!zFxj zF@~_<6NXaLX=}1xIaH?k+HPJZ1m>m!-hX~#pHWz+_jE=~7#L^AqW4XJ%Yjc|Gg)(uj5&M(e-f6D$D1{JIi zA263w1FxW$H|6~}!*=qF*pe}9XmIL3A7-q0Je9CqoWZOI!NYUK?*0fA~0(ko$uT5IkVs_8i}O&1Mx#LW5hJ z3;tN2#EnEpFS>%WM6_@g_P83xrJ{3&DcFd8OO`ehMHelu4~ul}8ctt2ta|JA6-&_O ztLP7dWf3EsUB90sfB7g7BI(fI#H-ODtRz=uzMO!sdb* zASDE!=fSwZ4$n)^c>U4{0r%5@O&0;@$hmQcIe+N&ZgF1d6aE9=?C(@qwc^% zttG$FF0W|S|9n!PX9IC>ubJ%p!sfie3sptDakL})-T=j|lcm|qsiU69?N|)V(NCom zKHY^!-J%4H`%Q|rWm2rR+{HV=kG$Sy{o4g_6;ZMRj*6}55*TnE_?<$4+Qg*o*bKeR z0f~-j@35!P7j~82u0a$Coo(SZ-E!}kXlwwp*gkE};NdjY)(~rnNf8ftxZp%?)Hm-x zy-Dka7Hm7G7S05JAoDjnf`U$)T%G!?9g@~G!kPCBXj$%pIgpZ=*Yd0x;mNynkXa-j z7-dxq#Dl&P3Jc4W(0`n33bt_Z*eoS%_)aC_KHj51yB`+Nv~!k1C6lj4^NOp&6AStL zsh8Pbop+2;K9CL;^KR@_^{Wq=2zUx~h&e%c=&wo#XXY;c=&h zy`48HxHpAD?tZ+$?s27ozRiu>umjYdB?l3`@``=hMCM##nFdwwt!q(t3x5d4NN=(d z$*xw+Wfbr`MLjsaw{+WAcQyUn-7Ew}bdy3;OISJ;fkc8pt>gI=j zR0eBOuxBo1V)DYMz3BcxEUVDw_nTzT_Zhz{L7{uk8@2T}rN%?%rN6d9`2wLW+`gQA;b&HJz2CtJa%2 z-MFvYDETknPqZ~_oW0?%e|1HId%@nqtMmdq?~3f|RBA(VdEb&^ zTnt@B`x{o9IA%q!l4cE6oIb%XvvyOnc@(b%k=lKe-{ypKs}7oImx@4fAPC$~s#za1 zSsHbW$_y%dJ=#!_t85>yAKvwSje4P10+^m=G8r3~si642ks_ciL%Ds`0N)mOYfwCF zdOA#s^Vb$~POti*PfX%T#JzH8sg=Ysa_pY;-8Ne0R=U{R!vNO&?RbQ(vpR*LH)>99 zW6(TTi98KN?Q9k^kOik#jn&VhFWoL~@1JHDF5u@|D0K*v27i;sk)hHXw$+&$gUf&U z7J=Ejo>!cGx83GBl~(BppYm<#41McVM0g0XWSFFR?AJ8?Ce!JL9HrW|+VeJFk>>G_ zJ+$r@qP(~@y6u#H_|nUf%C|`rPRmX3q~+%B6l}~%W{F(%QvY9F0yuW09y-2Su1P%%PBjOo!WVA)y>Y+!YqgS>o(s5y_GI7i{{qW2(~UA1^NzqKPC^J#3`ky(XwJ1%ma@t7VHQ@(NV}?XhL=d%~k3@HX{QxaxKo%FaofnNYKB&(N zMf1Bn;^mGges9cua7^&#ED0epgSJ(*c7Su9irQ!a3lbIpJkdLSW1=P0_g zaAlGTWE%z7Y^LpwZ8_uA(lMdth@#N?@=4Hw##M6ofSK)1r_n4NeHzT>?0}8z;gH~R zbd8W7y~=-N*ZsnO4f^t4A}oNHqqm2ihH>?BqeEBH(rmN)3>Mi@o#py1&K;PcWcD#` zk0wH2laZL#9Z%N7iYI?&nxZn(yYJ{k*u<-a1G%Wd%*E-0Qco1T%J&>{^LFVNOGhmq z8OtZ7-gVNVhdIUCB%zGoR8GbWoc1k78q1(;GI_eJSZsyOf^kKvSOyxB%sHJehdjVe zvJ)pJ(7DPF{(ZFoqMJhx&+9i0EPO-op}yUu8-=S@(aA(rVqRx76l8Tk&%4)^5>cgP zo)&jdZdOEJkLjU5&5%JJMS++q0C=Fo<0MD_O;=qLSVeV-CZm-iOwF6 zdjEVJMwJn3f_lKatnAoepdr}en=K1hM-Ux_vspB!K%O47C1yycgXq?pT6g^^8n8XI zf&(jLv6N|<)J?XqwPh@rcO77F>QW*q(e#GD>;j|fDjlK$$+ntQGO7NgKbb5 zSD%X1`rfkTA};)t@ijGw>f?7VgOu!@F_VHww+gj+TlJ^1GtWY9f=i?zQ zbb5A82RreX((L?T09=%#^SEQS;oRV+Il9b1JZK3_$+uTO)cv4swsISNpkwB)3} zYHoe4P9B+lL{Mj;2@NVmoO~8A33;TT36kp}0o+``X0KU`oTsW%*Lr#2k)zbk4?%sG zY`Q9dfP5D7ElA2Q!8|f_S)Kv80B}P7UdC(`$>?i30>=dxc<2ZgYr=R}D$e`(MwfN& zEaJXVvh0kK``m^dY9vq(=78FwT0fh}1FiAAk>4x<7Wm@j@Ft5u&E=@{xry?PB0z5z zrWO8PVR8wa_*%cz5L$Jm$Tiam)TOqj|H44pk`WpP$DJCyv>br~HIt}l>n^s8%gseN z0)P~x+ES#Le{sO>D8|V(rijSQbxO~fyVbteFbzL+JyiYINBZsSUr+VV&8{gJadK#i zn<<|yBq5Qrir~7P8QZIg4Y+Sv5rejlU`U0e>PDfUO6mXLdv%zkcji)v`+mlSjvTi%Y z*Z^{$fHcGK|a+ zbTlX=z6sd`|A+UK01yJgM47EION|wrmL{qj>&%x%M;_%i=4tPocp4`V{A9vM0#rbj zFah2oARCfv(VH$BhCE=qm`&8()8A4SMA+=(yO4XjZyPV5tMJ&Yjv+Da1W=pIB@-YN zSVqdBH*uX8olyd$L*WSo!?P}rZ6`Q5FYX-la?7)@1^&gv()CLjbE?f|9$B|Nc?`TN z6yxU7&B&7H=N=GehYAI+Nydz6HyV1cB1K)TK_pF6UrhQi{2yna7jVQV5TzSUPpm?j#V zZM46MSqNiICr%$|sv6({2cs0__bS^ca;~`B&bD)~+YGj-(2S~NI`pz=1srVc{P#9L zSOa=;Xi<~V9mwUmeVf~53MeF&m;gnBWSV5|i6+{@i^+&qkpM{Y+;8y`t)^Jphf<4_ zB4!$+2UV^yBJnl(t!PUZF@FaCeUau30+4&*Q>A1(NAyexN;r+AyZPV?p*DOwBe3-_ zN5Nfbw7;t4LyviyQU7&&v}7xMR!a)}`Da;_Tc_wP(?Xz5f(_ya=c~K%`Fg6{Tb1_$ zBR4voS2MRx^)$nr|7cC8{|icAjGM=y!YP|;fGQeGz`e(3QWnb3MTPX zWTk|xFol5{Lf6AF^5z9%Js{N*NE%4g^a8t7AuI#r(#2IQsP)QQ%SK=Kkm?n6EraNo zLsTD_z(vBU`e4XdLTIG>ZB%3} zHXq;~l8E*}W0)fN>R6ZjJ(WBxMoo<_lWqwF7rgEtIX=W^MXO!zS1%TLFkVCf$)KV?>b;n$V|-^?+(@i9vh5k4y|x6e&{8HhBheP zgJ%;yW{nRIT6jsRlISR91^4Ochg5SPn{^9G9URJxZO*|%h;rMxp~NaHo*vGPqlP@^ z%RKC8o^?^AyaEVC@~X+_A$QiG1M^%%G|Q1|qUd9F&f&joX?JK(cC6MeDXodm-MViZ zja8eTSiY>rYSv=-vx6(zvt)lVn%;vxI#&`7JL5V<^`MI!q!1Z+)6*Jza%>U0zYZ(Xy_88hEM9+n z4T=f@M?4u+7T0}1 z%=-AiSph1pg;(YkJ=TS08H*Pcd@2M@aNx_5&8#>w5VMu99Gt014wX@gUjZ4--VTN# zUVYo~REP}YCA)(+*2UWt$QXpfhjHf0?gCc>Ow~mEV+A+c%D#04*m4hc(-OTbZ6Dq8 z&s*lHO<1I6Mn3F7ukHPY*4v95gXg{e!SwH`Ld5>w8-%YH{iRFs{yU@yxfzXSCC6P<6>NZ_?NO`h> zFk%YIvzs0r3$1FPEDoOQJl~}&Jf9Y`G+GmC5Hg|Qn3aOXokZdP_gs0M8I0rm$8WRvITC-eWljuRy*JS;`LAm1`|;)>BnI z{|%uD0jPF6LTmECt013~*n#MaY%?|v)4TZG(31i&1}CVRo%ghh|Ew$v&#msk42~gQZ@|g^8wqDH=U;{NrPQy$ zKJhowKTwvBzG2b7FlZdZaocx5Pq)|VpoY>5N__Vv4YW;Cyu@^nf-rhdd-QO9&v<_U zrPhQ9_J8qojp21hTl2)WZQC{)v$5?HHFjesjT@)2ZJgM)Z98f7^||-C-@o_&e)sG( zYt5PgN&{-rD;1Tebz$47e$ghOf)8d+NK_!YaPy{Jl&i%||SQC3)IG)tTzfnCxCm(qZQ(8m^bH&t7G*QEB(Xq|v_#gAW{ zZviZ0v$Y@E|GJGB?tXKl$srEL@>8Vz!z`#D#jMkX?s>s1nwxRj2yuc^JB5!=jveAW zu`9+YC@8j#r)+b}!Cuv)+o^$n#uW$nar2@~cg7yrudGlA>%+qTn-Rs@LjUX=sfwMO zC-QKC8+Jb`L%$Aj{9Oj7=wDOqMNJ*mb?~Yf>HWZQ3}&M)Nl&k}Vx8Qg?K)yKT1Up; zjj)11?o6t8za=`wvGVr#7Gk8uXI49Ae7IR;Gblij0 zs{H)^Sk-gQRrnP}5JXQGwIDbCiYxspL-DE>bp-v4+|u99b*?i89!>Svx=+d=!7Nf@ z8~H3oG%jv|)cV}_hcF@mu!JK-Uhuh@+X{nH#1$YnO1`Q9UwPxuQd}GnRfL`eIo{CS zrA6=z)7B;7kO{ZWo=hq>9Mi6->GT74-yHq?UQw6s4FUNMkv3NNsbF6Xvf5Rdcnepm9wT&zE=Rv79s=X%5F?VDcpz**T zxqknQJ(WM-!?L@%hsiGR^GW2fv%{rPRmU(KB3dvL1Ea-BNm|9+u~~@@ve7A#TjC_l z->RYCs;)iOi34?-yoji)&XxW7z;19eC%qpx=RilywSKIgeZuKAkYmaCZL_8R-*|{H zQ(6m_&`pD#kR}fklfZ9&WfS0Zj0#fZO zPm0B5z;HueRsvj_STjnbC39U~it!i~q*P;_1Q0__W_9|$DodAWliTR&k;m{kcqLJZH5dJv#ZO|x>F%zl*5PRL-70to z{tcr>ox{Ufmh(Hpf%8L)f@`t`Dv<7kXBS8z{4=8{!lYQF4d~onzH{ueOL5axEXFv3 zD^jNftemK!;la!VJa^e@4h`VjSpyr9onDJ!h2$yh85FV-s~=3-+Bc^Nh7vzwRi{q-6a}R1fWnzP^?%;Xv_@!}Q9h@cPS zAASzIZ@S6(v5~YcR;a;jp0PA_rA`;{OV<}_`P*pAs-2N)#6;dJ&7tc?B z4tw*fe6qT%m%?^MC`p5DkA*d5;;Hpbr0(O;b3F-09Z}4T)p9(^F;u1S3 zuv&Ww#<84Wz8yu`5^;9&DAWYY@I>&m_r;^ONmLRsgQ_cBi;1yPh(E=DNBecHf@|Os}1r&6LbhLsze)G?1(go_Fn(I>~fE zeFE?wD*j*4!jcHS^;*vPuMsB`{i>6h)wh3j(b9AAFbSa zT_G$vqP~ej7(ezA>Lu*JD;Kp#Wf|~)x8pNQ9Cng|c|hM!i=pPyzSl!7Xldl)H|Y}n znEHo!?C>=-HDUCSqE=(7GN$R`|GJDnUsWy7K|M5rT3MD)IZ*s?Yp2ZwXx*= zoc+V2U2FX^-(mchyDRxr(U&v{ywSxHhR6dZEmz5PDFb-my@> z@Uh?Y>h$W{YC^4Da9cVmNM%cJ1}#$Myp0iyJdkm7A_(hAF(_5@d?00GJ&hg*8-?}& zJc6GWHwwIuQ>CS2$X~C#BM<5QHNo7?6;TfsdIAC?sQbHs-I#o&dTzpM^`^T{$yOAM z47h-fQyl=^(#S?5_U-kqh!YyeinO{YBwKuA&VUP=t?k&5v+4oPaDW+F@EtzV`oAc{Puriq9U<5H` zeK}Dubvf7Mw6BQ~FPM5+R0=@uAs^`!@BLNWghd5`SzSnSa;;IM)e|BLoOo)b7K_0~ zL+!dz8yP;Hw}4|LE!<<&X=Q@956mSaz61SV^-@V$2v}f5`uFK+{Di58@&w`AVh6bc zax&Pr0^3~p!`?>$0wC$aD!6m%e;%+IB_0)(QJlxul&?EO*)o@|oiOEa3Cfd{{vBy; zeQ07YbexH@q%#+&s{gD|P54)3A!Eki{A0N*(n(n|#k8A-q5GQ?jL~*<194nvve3ej zL$k~DumKi)k-4-iNE)4f)pf9U=zP*!!b(pKjOJ4lv7ycns3zvB5qdL}@_`g=*yy(` zCzq;p5*P+3COq$?;N)i^(CnG_lEgN9-E!RylgIy@bO*5S;t1;rlDkWKCgTWU*AKmt z-TBb~Ro}hBQKUTiP7XvLHK|7H-jh$EPKkB78DkaW#8T4IiT42AW!bcklR)R~RaYhk zFeW*GWIeJhdJZQGK;}FY-7k_QIDz3eyl5Zy!s2+{vVqhH9OD37$x#(}W5tzl^3~~6A#YaIEhj}$*=3stB)MukRy#}w2dD$>VO{Ra zzTtwbA$0%@xO1({;f?jAb60+$aTP)25B^X^fC}<>s1A8OC9k0FH~&p-+8AW_KNGGI zN0{2nm42`J9Ojn{jWn}{t%-gXIe%%2Ey+4rYI706yc;`i&q3n*qB-i$8`z+n)?v4$ zAXxrOqc|3cyf`e#v36uI0yc!J(^GOm3!V+|>?`v&5SeN>puiP^H_uB{p0*zEupVYm zP+kDLz!}8QMoy+I`U@FTi>`nwd3vzTYn(E5Lzn{q%f`? zsXX|}aL9<;C}Mb=fUyj*mZ@{v0PE)V+^CZ*Y<;aItLDD$6g?M|+c<84sR)J$?3mQ= zJ|Eyz6|l5~3!ea+ulw`oBJ%JjL_Cq)nOmP%m_Yj_uI5^mAc;eusSc#k&W$27U%2#} zN;*MpY6HEsw*4QBAQ3~+uFXr?C z<1E)6Brfc{(I$r2@a%4(=L2^Vq^ygNw?QiN4tK-V-4V(&R$J#bIPEwO@Tj!`Wp0yP z`;i!*09ii4}CHpEV$w+kmM>@ABc9?+7A))ru459gv-B9z~7A~ZiAy$F-1 zWI|=tFpmHLwobB^f`8Mk?YtI;CLr8uN8Zp;ueiDcfW#`>kkKMcfc`U*>Cs19FH6*j*fQH+zG4!>xbMKyBp{Ew{7( z0zD+ObA2=oL%a$!3e8PGvX3C+j;@DCv3GF%3-Bw<*A#vNLDagh2W6D?{rJ8WdC%!g zMca%MI9Ve8sPh4m*cE=q!1LLH$2j+uNOixbv!rynCi|6joPGDJ28&DyI(LxN;{7GD zPeEko%cE*vFZN}yGCFrOgD8P`i=MO z85IR!ID_%Z6PEsNIs2S3CXHpt-q&&ln)Q_buT0BF;G=*+c|$aY*WW;UL*m97;cY7e z$yq0s8W*r~=>wHA-e`@&(bU0@J5 z6KP&KiEsTxv}P*I!Wex!c$`>Cm%__f5~n01*M@4su8@jW7zd>e&BR-XCnEy}_|*4rPt zxeda%)SHHK-5r9&8MqV(>8jJ>)wj1puUBJ_*H2VC@}Peil|gTmU`rL!N{K})Pf_Z5 zq9Z>xFxUy#D(liUL=mdO`EOK4M!A(51yq>LU4#|WSFo6xb)U5%bX9;bJ6E{Uk(c}5 zjfTg(P%(yKLdmHSuDYuIxTsWs>X3tVIIbUwy-HSMWx<8iU_@(QGH8&V=~l!lkt0*s`*?2j7TDsa96HWHWNy)rww9gJKX6%+>?mzYJst-PDb|U)S;BmUrchld5 zH5bmc@&R}^4b%uayR5>v^>cF|Hb~)3jA|gdG+nfLcIP;~{I=Tf2x!}dn9F4nAig^r za)LFty@H?A|DIku7;wuZby3a<{(cID5Up(s$P)7R9SI_bxG5RI;fFyDe2sUtIz9dk zisrl`SO%-FR+2vDiSlF&%4sx-&%uRM=(YL~lWnYmLoLTSF9tFiasx(>td1kAc^&I` ztL1!INV&jn-1k;+vFQLN0K(u4n>00qKudlnNK^nR{Qbou$G0S>TK#T*3%W|-&PlE} z#Vs*)!E^Gpnu*{Jw4kG6(F|(PoaKg193e48f=s^zIBM@_&tCg>h}%M7X87gOIus1D zs62fJxOR&0ndO%y$AfQK_NDeVY~k*rwJhTr!#^(_s+D%-=5?NK=aKHa0e~i2x(IgH2yqvhWB%CBr)C#l=4FH~7!T^GeT#7v z?B-+t>x9^>lLpCR$m^dfwubzH6m_Q-KKqwY0)9D3-WM-iudOB(w8C<2NbHecFViG- zHGTvOvGe!bDyL{8oM4ZaYegYlZ%@g7{E1YMG)qud3+?)l&lL(-dM1lc$vyZ;%-d>S zWZz1Xp6-pNFtRCN6D>xRgjY?!C=jLzQ>ic0soZzaDfSrRxzhPP!T1@FqN-u&gaX{R zm=)cFFY2|$%pY<;#=l(-rg1P1v_7GRRdfhgLq3DnLR>MA5wxxXifkBdqZYTq?mid( zIZjt;g=M=%iC0@XkM77v4ATa@W{V?M(3LOC3hl z1x3^pRx{kMk>Fm-$+s?3_JS<1hDf>P^mYJtNw}IDUMcFFnRI${jhSSoPIggORk%ounBu9+ z0+o9o2`NkO?`1&{*D7L~=r(JVpBL{ym{29ye=vH*B6ya%aNYCbxBd*t7{9I(j* z`wGXeSug{Mb4)zwiLvxyhGGO!L=eTWSoIaOrYUSf!E_W}arll@ z4w2vEAX@cl8U@H;j85>YTwXhcqTjSXGjH<^5b7v3*#Nj?G8d~27Np;qcq_;&t@-e- zC1q2a>M<4R5*QxZ*yHqyHg{B*^Cc5WT9Q~!eChT_27-LfXcX!A{L+#N3ibhF-Q%I!%_?BByua>2E zy4$L~mVm=CUUmb^>PNQeosj%VzmGur3pX;y#(W5hC4lGrK$y{zAO=T+_QSwQbWZlA zSzdKSOe0D~EcOQSQf;xEX%%HOZv3HMOLBJOMv0`5y_e??f*pCJN+5 zjeyrFJ(54L0kziGzUhF61oqAkF?FwskoxT0@w+)!N15l9seSt0N)m28pZ#zyl`$T} zT#!}Ml%aR?cpOOxDW*q=`zMxafmIF5`e|7u6rU{b!nXOpx5!*9{?QkXFCKmKApGlE zBhx#7JBNQ&jCUoENO(nhOy4EM~ zlJY$t1`A5LI*rdFx-QscXL${My9;!KdmmpPmlk@*l;?KS?iggnvta`dlbM>I@mj*! zEwbVl)X_-)1ow>G={ZHa6stBF^eZ$-_wVn7AFF^_=u+@Mu0os1ku(_&B3$w2Td!>U zO|5`TFZT&Ue|$i~KPna>Ks4$yb~o&|AQY5*ebN>6tc1uPDylE7V}t$uL+tV#9*rx z(bg-rRtSs~tznv4^wO^5T3+_;lBH1 z)uReQ4C7_GMDIii@2O>%JI#w<_Di#?=i+=U8Mp)4^??4*nwIOyW_TQxguW&Sb}1%3 z3k%CN%C$scn9#DfU2@&E800|B* z>iOW@%_WoN%|^^$O>ZsaA2`;DprU*nkF%T{*d-dirzj{^NKCUMpuiHRR39pf^IXml zy5u@BkFxEOn-31vwHqV-id^cUlpb9`>}}fO#8hF4oSQryj?p^werum+Re}+F*~53A zd5u=_umg}JhPO6w{$OCM^voRE|Y9&TuHDVj~&=ig$O*Rwc>h?&wy1MEpTkUy{ zqs)U-1BJ_tov@HfCwF|~k^IfS&O(lPU4ok^?fRv|WNFW1)bsU+ z{L3edW9R38&Y8dN;uHBbKfNHEC2RoDPs=4X-Y3 z1+3dIc0nr_2%q~RgLi;-?Ps7c(GHG;?b}P2Ow7(vT1N~NQ-5PWD39g#!s3{qwV2~3 zJBLrBtU%xM?j=iXHoHk4nKOeJAcGjAMGkkxLD$^=-Q;}dutR~HnKB3-ZSrc6U#Fcu zwQ^pgyn5*WKIEM#sM(N{9X2QL zV_Nugn}IRvR8NSR>r&Ths)sC%52^e4B_ZVYUbA_GDq^{=I>d~)&WF_22l{ZR%lh0; z+Q^&k@x%;9tYi*mb+INjHw3Cw3DL<6YO{Lo8fJzqz`xo*9u{+5+{(w+i5Ix7+^F<$ zjL(m1Qwuw&FArbNGbACCx@I;ArJh*b|35=z0jv8btf6>m!JrGF;*JKdL#0Tz&Y*0p zkI`&VkjwDwjoM(ibM1;Qv?8R3~&{;Uv&9B(d&SL(tc)x9jKt^ zTgRYA!$^l||FPIyvz0&%7^>Y;K!7dXI!t-SZLgu_(JT1_)NwfZJ4Go0Lo~)vRhQ~h zGNSi=WhZZOI!nhy<>sC~)%l+(H_>Y>T!Az6Wee$4JC2B--MCr})5n9r62P5N0%nX=hAe&B~by8M(O%gd$B_ii=I z>Sno_rpsl|bj9byh+REYIxEvgL7tyg6lVg+j{QBB}qQBEGg=IvEvKU(Lp$cNX- z2en?uuZv#(^>2Huk?hL5!qAj46RA@X9;7Oo06McS9BiJ7JAWQdjbUFD>^`pXtV@~o$7UTqLjFf&Y>HHkdQ(2JpZ+F8ZQ1%=EVwx+pOB`zGvAm^@Dx}qy(K8_YDH?S0g2&2MDL)2 zm(sq}dJQi~&7mInJvgeZ%0HslYqLOGLNd`NQEK5<<~y*Q^QTSySmZ>;^Ra_1yVMJp zf(cedc35$$mZ+1PuJ|9F$tj5LQ};&+mR32{zf2%m(&Vv(fz5QX`CZAGq^TgRL23h8g0sC4qaYmsP+#9d`8;aAf|b3`kFc zH=$%$FQ01=NMbeQBdi1Ye(=8v2Bj2IJI`Ev3pw9XKoz{vkj3mQXQ)qA-f5DD7blo@ zjBMl^6!C+&;p$k9D111%%gJHG}^HY;!a7O8?>h&ff=oY%j>C+$4c z{2H^ng{SFT-X&65h&ZcZSOvbs#uUCEszh-=OZ?J%&3(e=p}wR|c~Jv|`rp=62hlPE zz$GArTCc-+v!_f>GmmORBxr{8Rn^Uz^0@q9<#$}jc(8l!qr%h=uRFW10~&_IIVi<4 zwZc2}SC%y^3C+25Da)k=QuzrcIuNT#7+Qt-K8&~5^FB5%9g4@M7IG4RYdK@BUiFwe zrG-L{79(i)Pn5BGcgw}zjvTgcAMYA;Z(%G~Pv96ed(~MMpUk~M1+{H1B5SGK0-;LK zo>0JDt|(c(14&gAQ<{>qj2Z^!kn$H+OoMN;7H4^PaQ#8*!|4ZF#dXN@0u?cWz>0&X z&r&Oq3RrHT8ALUCt?TjkLz zlB@YAk}($PeXI=z?1BpJ(Y^wl?v9{Lpyx{S_SL70rQZf-{O&X^6rKBX1uQ92S4gSE zZeFY zU}PGw_+#sXKI6?RKY8R&JiWWmouRZH?bRvyEI(|;*;1?#_&FlQF3YV=a z9pR?i6eSdW;?K&(c=AX2IKw^^OpLCIH0x;QQtOne*znI3SBJMIuevR^QlmETiWcCK zo4LE@9mcc-{YmUedF+bWCv*7x})yhUaf{nC8l1x*kFTV;OPGm)g?2v4tItsIJ zwhxQADv-hb-*V+`>){u{q}1ueA}w z>%4L-yqOALUd8v~ErzTb0v6z$w$GdXQyrliyr&ELTo{qDD2(G@y~FcxMsj@5DNYI% z$RCUHSatM&#wTjdBKKTux?OsJU6Th`K1l=_Nk1}404U_Kp(`GV5=&uGtLkokhs|eN zk^O^mO5c=#D+m^_ zXMZQ0af`)nw|m>e&#`N0LveP|g>AW%?Jc90Pp^(w1}g7oFS!l~s`B&h6jJ@IsSDW^@niyg0n)m1n3muyB=YMoE)B@7Z3+{xn|*`{2n^-*dknjc!`f7EFq!kW$& zxpY1y`NND$NopZ(d`1dv|IVXav^eJ0O%LH%hg&T+tbcsE{r3ldL4Wb3+DSI_-Rc0) zkxOz}molKS3t1q@Ys2$e*jT-FO4TsUDZ&0l|#^>FFg0@ z`*>`I_VYm$g$E{GSsaW=p1}XS00_joQ3L5toGNp`g?I&^M^q*8JZu}QFp0!Rrw*Rf zCW&3@*ke8tmoAsFPGQjkj&g=Rh6%`*E!}S z0Ve!lhoK3U`Jj7uh2*CHaDx1E5lcw(O(Kba#mXkGqMk<++{5Vx%F~Wqvh=T3-@DEZ z;U8&YqGUK&b0rfUCS-(AA?fvE_}E{b+_+kv7T=U(bGtLgtD6r~Js>_%?qiVh&$*(llNzEwN~IPKcux zy4(3rm8)w^dJ`${5m)e6v;`{=gm`_Yd%9AKjulYM zDR@qtE1|Kj-fvg8h6G;iYA$PZn*SQzN3VByYB{ual>>9$nE$%A__eOTId0W;1^BdF zo($yPD(74@;-K_bPf72a>AQa(A%>KPbkFsvF`TZ_R~KLQy~bZyDN6Ov|3lXsI{^`4 zD;xcQCy114jhcYTe-pa@K=qRZ_*zhno_r>G&JWY3*%&v5)UuF($+4avJcp=IR4AT_ zN0hEyN#^&;l*xP}-|93kLNOF%OKznq1u;;s1|tz`YgZh?BbZZz0c!B^`kGgso2Ew8 z1@d$XcOESH$#%*OZaaO3NK*B|v}F0DXcI3=O9*Psf}#TgD=Gqx0$|3KZLo|Cn#=3r z5!yP4ob%7*Szxq4T7PoZOG>#AQAp-R1&nz=@GeM zFbeHc$TsZ0v%$9Yiy^5F=dWfv216oh8y}rhl~+`cLvOR z``OyL-_KUxtDdn%<=}xJZ6}E5M?S_ZbZzh|9gGi^X-He!tW+}_(RfIcn0;>k4YNya zPjk|+M`EuXgbhu8QgR{?yxe|0W_16zQY+QKCCgZk$6gqoD>+}3<4LNC2d3|GgG*>NEVljE1g5I;=Pvq3}@%T%ehJB6z%T#+=EAQ)Y62h{#gmHYn%JVxc7(PsQ4BM+fj%Xftw~#rdDi@(MqBP}><5)xmz zQ|8PWUF+3e^U$gXWM~i`oin+xtH@wMjX3@R`9c zyNW>APINBs2#c{h0>e1ptalH8@L(g*UTCwQ)NUmz7dT<3N0*1n=lZC1Xhs~N(davw z)Dp3lV?~#k(B2*qiIUBTW5d$KA&ZYO_bp%@aiEzvk>NOjK@MyvuA=8hyutY~$b+>- zSFz^c@jCy8V-s+9f(1c3LG)_mA=T`U1X=OZ1S0sAR+B{_=!6r2qHK{ji?=2hi3x~) z>Zd|fyUEBprX2jrrYV=lrt9 zA=j$F;4X!2K<|dxgvwhf&RW)1Iza?fC~X}0Hs>7Ul=lpfrR0o73V$(#Gt6_>a#E-)8JgKImNU16a zCPw54_5W;GF{kUxH0-IqDb`!UX*mn$7|nr3SFak`UFglvTS z*r(yYJfuJy$ygz+U0*cjM|k z{k*sC=G1I;A$S!nP!yBS{*>B~^Tn($2uAIZk}bczWzGGT2>K2gqNy+|QCV`Hz2QEK+H6#G2#I{G5O-f{Vn4h?q7^Py zyRc#WRvk9Ob`YKta)gRh5>0@gg!~&N6gyNBUrVHIWkue~Ys2{*NqA5g(HtLfQv9AInL z;-6CNmRLwOO3{aKKFz#tb@#bvr(yIO<54P!N^IFTnkKg7b>@O?F4qBuB;UQDIr|LXXi*}SV5izqN|RljeP;TR zSP*m+&Da|KSb%U|ZG8F?LSm~%fjUF_va-SiEITPWxLs*Mol`C{?2k2pmIP2a_%iD6 zrl>vj8Jqj6v98$bruY;aUvEA$zSQF@nTUC3Nzv`aFhsxHY>M)A@PS&TeA8@ZEP!{a zgD+u8U@Y1B5IU)NNEY`U0w#KGZ6hQdh53P>c7T0eX?4M_4I;znW6*mPb{%=!Y%f+@ z(1nVffO)<-L-Mizg&Ci=a_8{uPkXgeYr#JpqRhq=f#qrlL90# zycR7NGxZId9;F%m$(d09NX{ zW2iKD`1_ZTkjt)m`!bN1$t4&Juz=JD&Y21>oTTkOsNU+sN2Qntw(J#N7^$)Xc7i>y zNiWl30Kp|2h=&R8ox$fv)SZjCzjIL4z3reTwhsSi+q)W$FVmoW*jA=6PXll4_3=U$ z8*RhMo8Ou2=L0v5mPnLW1@I2=LRoRPeVo)qMh#ReyTf7afRPj9b99k2fJ>lF z8%2*3vLI7hV%xdt+cwp3reUvIg~uxNzsptl!hw^hA+p8zSa#H@Ed=Aij_{<|F^TR} z5u}v@Aa_ID=orQCz>^hWQei-;oA9QoBsZ{&=0_m`f)VdcC#7l<8apWuTL7(;JEhg> z9;r}Hm0Rv}bOD6*(r7`=VPsk6JxmCYiw2T58Y9L~&okSLvKq3tZdsTQN@LZ@$DFgy z3n%uKsml8lD zqr>#QU|K9Eu(X^wK`BvRJfwVZYP?C+Ro$1p{(WuwAei8dZZf>I@6Ztdt-B9o<>1&?n36~zk=J2rOY%9B z9<8X*yBjM~p|jnCTiFhoi+&qAc!`;086fk3+{mwy5{)DTB0>4f&!!Dfay03{TQR3K z+bz4Gl9>tt{uW@kw-t>1q&fyAcMIE71pTdYmPzEEoA{?}1q$(H?pzHhb95vp9%?z}wOP4IljQ45{UAs__t zHG%#Qx?D96IgSCA^^!Go0CD?x$~}!T?$WFUmp&co$pTKE`(wOw%^)O6dWttbTu+vUTfdYFH!=2`&jfg4E5ZxdLpensXL^`EQ5K^ zxj*VI>Cih>$SWcKLL>R!aFit)O9|w&i3qjY(NNvaCWu-CtTe-`kOE`{85Q8hSki`q zvtS-FMlJ09v7fPYfPmr=cF8-`p3tKU_~|u%O|;DCl=b@U9&@TBr4q_^mu+jSSFe?` z59mZa@m7FT=go>Y33x3v7~FMeb|?z);+b|^%*#9R_N4V|Gs^?R^ZDBea{0^N*3XLv z)@23pjus(fF4tF_>rhB-^AzrI>G_Pb*M5$Q+sK3TAqT?+6t`k}n+D7wi@{tY4e?u% zzyIB5AWIV^Dv4&w%Bwyv#3T7C;{zeVvNg$fR6NSRCBBgpv>DN+Lo$=>edcM>Maf;! zhzL?u7Pz<70AKR`Qa;-tz6iRz7NKg8q6izrNAwmex+@II*L83%ctd+MB3s_N&XN$6 z@R?&3+P=29_0FGwe#1+UP~1sJIWb8~&F=C)?OFf~SuSO9TN+;r-lK4&!9u{*5fcxz z1cOwBff3MNDF(XQ3qR>xGJ-cal$t&pabSZFn#ThYQY972sLEIQ{N!;`NivS6EA0ax zj}9f+G`s%WOQw*(7@Q~dIB6xT3+;QgB>>=<#q|Z`jxWn>wscM$Iqdu=Oz&G%?rIUy z>Uxr?!uXn+99Ht$eI&i6pFV@v|_n|lTBVlhdxfh`<5k_W6 z$?Z2lL9PqqWm~!B7ogrw)SZ2hUVYVm6Kpl8g_U%=L)W}H>Oo{P402-(^g>ICVY!pib$w>uFOqwcetGiGizd@=Bph7$EN+q-71J}E#q4=9*&PlIs!@?JARo}bdIIK zoO^H_{F0FDJ+*hBZimj7+KosckS4ssYFi!2&zFNo(cI_J`_sGX3}_y{U1RKv1-8X> zAwC?%f{Ql;OaHcJ>~96E*aq8;YPtedAD8?x@!CA5TO7B3Tno1zM=~{5eixQwndb#i zaWC5e)X2lTaQ?BetI+Syy3~%DNXa+7iJIqUfrGziwL@bpO!*Pam}T}2$6tRPRYi{m)<+xJH9dY-{;4(wbq_%&bc06(P925HdBBzGd&<9{;|d)o0F=oBjFBm zr|I%DFSr%kdyL0Wl|0`^^)eh|@DE9K$r32rNM4yIxpCvnS~&@9NZ|W~{s@l$r-tYc zs}8{mO*7wfIKJuIDcEAvxWMY#^#?p3rCmzzQFu-PiqZco+aIwnc*J-$!sMpMEQ(|y zd)MD4CdA;A5yFr7e~>mCU-{lr*;&GKRZ#crz2vVwZx2-t?`s*u_IUK?42UUOkMdzKy=@CS6Wa^3= zQ6mlU*yF4REq$<eMi*cRCMbMwqn8&XM4Uq5Lnj33$BKG3D6jS&Qp5%A0! zeZ2X4PQ)N_tVmYt)#`P!+jjG0I~df6#oUw9{HZo;JN9DO7?=tEUBtaeWaA_dlgYdN z`|2(BUjgW!)ae>cR)3iHgY0rNHSeTuBY8{EfEm0v;z?rtTU}lA6U5a^L+I{&ro1h< zPgroPxRyMvw)KoSm9z+DD-!%K;m6@reV9ibuWPD2b&DsY=N!((&joJ{vsD!)de0^Y zvuLVPQ)tmLX!hy((yeuW?Bi9P>P%F6dIA`#(pCV_VfS>`O|G_w6L{w>K#Y6~8}vg( z**G*4I=}C$FaibIf;7RlhHqq*U&gybkInIPZ|WjPb!D(OLY6*w&TQ^`qC<-XJ@GgNWB*G8A2Hn0DD(PZE?^zexUpB7 zDO1nLRItpCQz7$zI3>IHL_>K3XII-O6m){w)R@$GbrOk7?C;k;!@UC4_9seA*ZS5K z>v~N@p~<_o<@%djZLD?fg$h&hcV0lz$fmq-Gj_2Fk#6CyB)P_P0~bjz`NrM}kY{kx0ki}n6w z8Ff(Hz5i$d$FQRxL5<~-OoEsx9JU***k-GhMe>E-eZZ11J z8l|1Eu2vcgJHC#y8wWl^Gp|qNNj}h?Z0fwxkM6mrx*?6>Q!~305hGwD z{MZ@CL-N>{Gd!=7*m9{X{IQR-?TW6Kb>KBBVVNHTR~`BI*N1DFxkuKCbML=EldT z$~uQNjI|#`zJ4#as~Hh7+L0bVtK6T)voI8J%hT0h(KA+l^!^Xc)rGLpVPH;trWWYCaVT<4naD7|PNy z0*jVLg_S{t0Z|xDHvl%vt5=svrf5?uCNc+!&Z39a@y=NP2;l45i;nJO)h0GCoMfmQ z4+>Ejz?P00U8q(W7XpS3$(J{EL}?#y~#lc9HqWDxkxBNbF;QlYO-?7PJzMc`?Fb9N16@ z&SDU3S5#}ZT2eX-T64wZAkZUgUJ8-XJJSjPtuDb@8Rvy>gDgRtwx$=a_k_39ByUQ% zi-#q7pPhjH_&rFCM+dWXIumM8nTxEUTlPkeLN1njYwjDvvwm;J2(JFx#)}K!(D=yL zefcYBS%*}6YO+w6Hwf*e;rp=Ipp(XsG~6(ou-g6LJ7Bp~pQ}!9t*{?~l4UuaS%<%| zJvGS!rUH$%IyLrI_rHN-TXx$&!O!!}vhx=SB>R_&nwT$_daJ)lv=kPz<>`Z8mY}*z zUOuH?Oy*VYyy!%E-*)c0bN_w190=uQXM`%!R;uBqb#kX3naltuw))lEyg4;3Zk==y zdh0#05R}`&VfL0Cz1gYlS_R3IN%ON-sYbX4k6Iy1@9{Lw z`>otXYbudhwLxDp(zyXzdqcBM^<#YMenp+wys`V$cj)5QISEv^7J>5WDamsloCAsUd zfn00reO2TA7A(LkKuDPdEbXN$0t(@B8^fhNVhc^53Fg)`Z|XFlGXG*Y0+NG;$L-w= zdz?RXFB(2qA%UOj>eC;&McqRpv zB|_+h&gPL9M!Gj>YryVx)N4 z)ARYCZy?X9hvh;)iVR){J99I%v>9W5*tQE;3Y~_8AUXVUuEYrqD?W=<@P@@j`g(CZ z7iwGGNK$pj4xaVb$t={}tqcnI9x4qRsIl3qhM#p;JtmTBOg^{&-NDQ?P=G^CjjQ(d z%u0BDid)hvE=wS))y;68b5b5vXv#S}$s#-@(GZ{dr2f)~{O5t+=q_=-OsY+GC` zXLG7J+1LQ4uFK?5c*{KjT*=0{le$oWr$oH*{9letZ>g?}6a7$ayf#H+V3Pk-Y8tvP z;3M3p$l2pFJs>n%rsC8pAoHvSE-wBs9j^rr?pCCb*NNtE>haqk7ZzGCt_2&eF8!M7 zT(&(5r^XOWtYIjvW=Vaji1aD zJI~al(JXx6w@%Nl2t|_IK4WjeXM@@mA=~K~qHusGrNy`BEBJ8Y*$w@ol@QoI7cU0m z3qYgxlht5~M%gW3M2eS~FnXEZ4{^9Q2W}@LVH~*HS|KfazzOti`2+JDusHLjAyMz7 zQN4;ugW;QP!R7W1R%SOy6& zAa==57xaXLb3V==#)`fJD0iG1kYqabV8-gD4lRdf6HoYdM#&&Xu$0kGarOln!$4XG z-voCe#LQ+EdTPAHQV>z2%u`3T0d(+zgtR`6{7p_yB}c0%9A>JgL3D#^0SBfj$ADOh7vKGZg^6jCK8A2eKb&c5U)B5U89y7(5 z`87#f-Dcm9LT=d|gcmf%vIl3lgAyVX&h~rmTnavhP_apm$F8Pb5dEB6C^^|n;1x-| zE#HPk1tIm@;UDvt11&@jSR*r&HP;ua7uQch$*oimET_Oyt;9D7#?xh+jriA%dK&g4e*krgTaTLqu4x;gGP(>Xi~Cc{I0F2{i8 zY@W?uBt98+YzU1C88eQxQqzKuSle1=V);2~VQW)90@h215gZ;h{R;U~zR^G5-)9s& zAzYJN2ft)0Y!88b1j(`)W{ViFOoJ(k>ew#`Jeh4yX2~wAG#oSVcEN@YCbn23MTwo4 z8_xLLP)B??Y-+&FU#6?ydA~?g+>RLAFd3bc7i4$i)+4I3rc9(P%b|U`L?0%rFJ2s& zwqI<|C`1n1AGNeurQ)b@|Kap2&XV7m{r;`p0@fqLYG0`R-kELX{Pp(%JuXT&uRR$) zA>0a@JBNN_SCH%oIjMBc&)i=z1}H=qb*04C%`QE^kG&?Vv}KkRYn{>|d))5m`#}>w zvt4ch757Nnivd&35eHF270G5Qsd zw=Lao?OkpJ?wZi9iqCflJ|5;lFGhfF(xKbg()$~61KhGv1bU=l!|u<^UtrhHzr(9>zs>mnI`HtH7;$gM#Y2-k3Ygnt1!+F9~#it@X+v*a|U zw~$AwAV#|s(B`^(&c2`84(%8Sok*P7@L}%Fd-kt>EZFl3%o_HGdYt365HiVEx6Flj zy3Ziz*(4r7AuX~3BP3?$sx zwR*m30X2;%mZ_@kJUI;y3d}2slKmV($;08FmoDt%H(E|o5OG9<&$(ME5&yb^Q?$hR zK%xsieFoRB;(L~arhsX|SXC)s)5PKec+VHtIS{8{Mx-K636T`3*|O~`qpZS*op z$FxZ-pMXBiFc^WMc;=VXv8LMP%I0?MR5Y`_`NukW?Ll#g6kIWx6W&GJYGGZ?SSlsD zlv>oy-1<>7ya5OC+8$Qdv;y`-4%ETd-+y!>SGu3{_72=TFV}e&IgL-0{x-p0k=N;r zVQaU$a#WFn1b{yKE_-m=Bq=@@=TRTc|Gh=me?Vxq8<)FwFR^Guj1@HZWMoZ=vN6$1 z84&pVCIbicZ{uu0UVyS~Noo!kIx3k;tz-DD82(=SL2harbxGq~KVY*Dt#t3p>bw5i zD3^7uwp(FYbvzrV;?&|6x0++%Wcf|hQbGsB0g>=D@FK)cbR=b=1mL@p;`?TZ{d<10 z0d9mvR_a*a#r;O~rS0!`$*~b>wFVRN;9Zjq^UXfJ*gUWLgZPon&6u$v14SzVR8Y0l zBM!dBP*>4fBZn6obMTqHhQbIAMnXMuqXOKRjh5BOD@x24fmyfLGhvNy)G_Viy&Ot0 z$!Cu8D$KL0qjENc)_1nJA`8F7*_3gfaICC_VsfgDFlY36;Nv5j5$I9CP(BP1@m}t{ zCVm;cEjqRgb~*eG6la4ShF4Y);>?JD+lvb$#<#4MKulh_s*)Vs+XIRv5pATH1+Z(CTa-iW^-j_UG(%estFm2b z#TavtgS?#;s3XeyI_#>j@rmE9?JSDTSR!#-%iX`xd8AM!>Onuu&*5d>mBn6)E$w7i)TBYeIE~m6tie3NHFE>5!*W3 z{vE?_XeD5IMC#rQ==_wDH>sv$ZSILXo4%}XorbO!b^5393mn(0^=6x&z272e=u*3$ zRbOtk4b!_ev#REU;ugru#N07+H6fW+9cXQ6abFZ;9gT?mMjR=B)HiQw=_nQ>CtLn5 zWKCHm*`#JVY3ND2!L$VPxC-tPw$9rU#l-eZ#`P5({HYC; z)QA?LFR<|@;femitw59O>f_MZeCWZh!f@z9hwt4wx^&|^J}i(Aq1xZ}+ep6vm>&p( z)Muc?q{N8Ktt;wX9=S!ld?SnVe}{O!*b^;UTw z7z!3j9u4pSE}z6=TdU2O)QkhoI@we>*%^*Q>FoTPr z6Z%Ci2+nnt^6b&>)Bj`&dUWt+-^D^TaGjzkl2_Z67@@L|=scNHonIzLULrfe4y^19 zo$ndY7bmCIw(LigcCUV%Y}#xc)M>5&%d>w>FX+c_!jgdyYMNEjp82ZA2$Ib_4w&4= zIzZp9+iPh$ZOe;a z8!wZmYgrfkk^ktKUSL19fg!8o2%fGF#Z)Q9xKw<}%l{Dy8`mRw=ytFyOJRH8n%8B> zy?3zn2SSy#K)d<|YZUf$DHnX*hpO45E6LJ!aa7n^J@f6KBBRGgW_z=X=%K#YN27zR zarrs`3Ff>tHT3+!*S3e4clK9hob;HPQ8G?7Iqz3?LvK~==m6M3u7gk=91Ky=AJfUhOSvz)eQRMienQq zMjSMH$;M#BXQ-Czk;udq|2jKAZ7eF*J8uA0vAp72b0Aebds*~{NUXs#ubsomrji|X z1gt3#r(%C0Uy6YNYG*mfJ*d~9X+WzO=GMq#;RmV$br5QPS<<4`9K$%V=AY7Auk_o7 zYmB$%f~dhq=}}^%C;Tm`r0eLlty_1-n^Lk~E&msCeH4-MQ-7^&raD7&F{*X{Jx3hu z2sEhFC+YZZl#6j-Rp`Z6g!w`&wU+B%vV~%>;<2*_?fEiMR|{=-U^xgco^k$!1A8$- zsyxy1(-Wh3_q0vk2>f|+#bmrS%s{&Pne@BwVXF@T1;bnNU*&cd9jBs0Sc!fy zXGFtZP1y41h;07$FiV?>L%U>W^!sJ5a4#?Ynhjm|@~s#mi$)X_@M||`>s7p-ouY)t3p?0e zC=Vxdxh0h`O?O1cb=9I1n+y4GcAfVkWvJ2F6f3^ZPv~c#`p%JT^gL?ACCG(8aX+^TlB4PR(8(L(e7;bAb2Q^ZnUhV&xB}!qQfk zv!|xz;O^wn!(7vpR21>KJwrj3c(6Paa)zq%-y0vqsVYonQVMlng5n z@iJ;epE?0&r)EI66oWl%Iq3qY%4EBSSP}xes_aoRUFA0Kp;8!n+R%FBl&ZeBRnl4hY14UnxRVTQG-SW&LmWX*nB2LfZjn>7 z{spr&QLKt;oc9i+K!_szX^i|hcQzLz;V*`@Y$XR~GmsLwD2P$l)m0PS``y9EXJZIO z0*I*_(zx(NOH*oXKrZIm9!!D{%Yy+QoaD5 z@(agcCTQf3w(sv`o;Fz52X+-yrx_Q@DE{Pte2)5KYf{(?nA|>{rf+%;dV3jO-tK<_ z07b+vGP!RRf`S%`L^KeDp_(?iyF4+2qUBqH$BvMo*+iX1;^i97t+a-% z&So+@0;$5CDv=g_Pg{F47-Y%)7qFbj1h zHmEI9R6ZW0G5B?#<7carMy}GjO=Ljdj==3*T<5iMb2O-@qBg76_j#24<%9rHOmI|m zU7UNJ1gUY^_f3$`+;@E`07GlTp<1KPPGbvDe->o+mQ=qQV*N-^-V;# zxz@8c7|=_HJXd&3uygHRml?pcIqya1s)SOHrt(q2!_v>GfyA^}C8-nSOk2Whjo7Fh z^;Gn3(|29B{>?jc2GpJAmOgW)q`w|uL<@7~-0)o9$&SJsG&DeT&YS_L*AjWHN<|D+ zd%ZXd)ppBNdKCr0u$^s>s1D=@O%Ok3g-$#pVWU*kx8!|N@@Kveq4fHPwA+98EauVv zbWE>UdM40vlvFQMOzHmg(J;pIx|`8m>$x?IX1V@;-Ko=&GBn7oFS)IJ7M#i;OQx{gEYI&G#0^;a;DTLowI^IQ zGqV!Q9}PklixKp)n4tzguA8Y=7X}2%#TUmc&&`eN&Xt0BWVcaX&z4Nj8JJe<8jkTT z>eXxa%^0dyOdAXgU7(kAwbjs4*S!vzXc+o?lR$Q>O9;zu&#h!HslFc5L(iFvc(O)c z61J!9798fCkIh2)hkb6sOJVHSBvQ*W>o~U*amB4JzBgVO=Pn}AVGRBL&Vpa-!XSl@ zSK&y)w2Wo^mmunjRP7t=v%TyP)e5iIyc}IDg$`ZvB7?9~*GanHmjriNj7IB9FR2!J z;&+mN0e3#BrxTjfLhVGa<0rfn8LC9UBJ%DQ!h@*CH=FLqqcadem>?#K_hMuYjxz-z zIs?*$oymyc%v^^JFnK-i91x)2J6)tIh7Ccv^5wW&%5%AI`Q93c!w5T8BSz!_Z3_Xz z0OveUvl)RBCVxgS+oU_76M*ysgm3q9OgZUBAE``)s6;2rhOt{$jabaYtVuNiIjrEc zruRAuPHa_SaI6V*G-Nr zH$}f7M$)2>9H%o-EoGLxAbB@Os8f`aY?aK!GqJIu5My?4m{u>?wy}h9S2dk4pwZ@<}PDJW-$3 zK{BhLTCzmC^RE-i+xf#i3dI1@iq!4!65^7_y0hfm3kaNkh~OQJGs%KYCaG~KBOA}& zpI&K)WD9=P%B%)6p+(BsSN2xah~m9^7J1V-F$!>}cdhnlj$hpzoMd6$*jr!sDg8+O zFS76~ynig`9aAXoHwvRYuBA7=jn7O;ivT4CTJW;!^uWB~-SX^if8eaEl zFc45{7%8R23Qp!ARc!cxd{i|oliCDRRV2fm^*pFQ7=}2s}eq&ZK$&+D}Ys16;O;dPX9gM+`w&RqX&x!ofi* z{NM-VRBSENtv;TL{!9#rwaVBp4hq&YluKhg*)T|4{otRbXi*F{sDf&y%=~Lc_fZ@B zl;~jLWr$`3Oa5QBBMbwe?@w5Ea(ilaY zMc5%^@{0xs{p6>33#&tG0wU@m7<^Tw5uUx@baiajaSeqinPd=UaJL%97YX{F0cEAT znM;kxQm%Z7^v#|K(y;EM@Zr@;B9h@`m9d1pVf$Ao{tC!yHby~B?Eq^sUS~=xk{rbq zq*4NeeyXk6cM5cZ0_1qKMHrQ)mb7{#X6tl!I6mc7zs$l$MmbN<^J8H@F!3e*;+C!) z=EBvn{kqM&P?@9Y=e$i)P|{fsu|L&1sgqs`#aZ4p^m9`{ zW0k9tZtCPD|KWEa&&0d9u=H`O)7Vn@21)V%~eC^ZY?`$qG(!SB2eXJSvD!P3pCOQ?BJ_kcP7UO>! zt}2j(2(W5pS9>xATpTK_MK0(sqXSQV#~(H)w9VMVp`ZiO@B_Y}Xyw3Y;>(7vs$Yue z-RXSk3<#(|yMel6cyZ0^$_2mKoI0(jXT9ogcOf+?TwN?nY~7d|#*x~5!$p-<iG-D2CW0L>=2 zCX46gN;SHXw?H(;nX6mC&2j7{^S-#=bs#m}pAFox)? zVXyy>-}eg88Yj)gl@Fig(ji>=B(gsuZC}Nb@cMfha(%PgZLQ6?ezG0RJMxjTPCGnj z_n3s(hsjD|jv|^l%6wrAWLL7#$iDqX*x>cL)9Pg3l)Zb^Kv(Q8o70`F*4JJ%fBos9 zn1;3SsRvCs%fvaf=65|`?**n9Q!;rfSOS}i@q|H`m)!SzPemLT+$vT{?yV=P``lzRk1e(jIVFKUK4 zv--tqS^t;83{P=qvnj*UpjTwC_GhOHhG8iNqEN(O9-i;aQSM1?z5r0Fj3$+Kd4P@C zb+DjvF=Bx$qnxGiR?^8raO;dsdu2Y5pK1cUQHlyaHUk{2%oa{l@GxFcV9k2((O+VY z3f34{yBaR^Wn)7_0dB&~!n{twuz-Y@uoq$oF`S;Yy31efvSo8?(0C2sCD$>8kKq+a%TUPgGY)PjmbDpGg6%aMz=(cxD|wDJdR=tkl_265l!2< z`BY zm0;QlV>|Pc@464?#L@PZ~(t{DBP)OHIZf&ubGVocD+I_N`qKQ zUM#acRjoZH^y(BQk60hov1R?Uzj_ZbH9S{j0G;1QPWP>b zol{sICM7u1Lr0fppm4F~Q$fA-%M5eLIYZDfw-TIvFm0th3)}bffmK!P{Ckc*gB5VB z4;CAazjJt=M;o|{M7#6)%woP+RQt2R;xGHB!US$@3n9ar7hu}PP_vL+Wea|tx`|$V zH34H;rm;Yk#$RW-D5UsiqDGLfLXa;uP|#$ZzAsAleJ! z%bv=DHHD}qFs>vkLvr)IG;-?iU+YcYn#hr0v%$m&c{Z(?1rkFF3ub;LP+6V@(h?;0 zbSa4BRaI$X8J5XniXnifDZ?$uFN;JM=;^cP(1&0hAxwK)xQ7D($%IiK2tUpoJJ22`cjPZGa4Ry?97kA9h=QotmDUkaN$kI ztH$gu^QR(D7khk92c=_dd$Yc#!$y+$toA79)PIEj{FP()TXmLhk88tjND%W8zLZ!} zO}q5i>91547vQ+Am&FQxpN1hAtTkBo)KPbV59vdlw(D8&_in1+vI-n=V(#HijfSf$ zre_0~3Xqzkf-2OB>defLzegubD?aoF6i;=t5~=(RHp{H9YWBIpVz1c!7_D_(5-To2 z|Mytt>%eHalA%V7Sj1X*aR)M1>2i4gO&sU=(BVd@7Ip)&0!*^@GcwlCx1;FXg++quXZ8P|oZ+EVH-bP~o7SW_HL;dn3eSsR zejuwyR6m@HJ75i^i_}nI17ynJo@I`R`#LV0Ip^9*TCAq7+n)TMSK6jjNskts<7Tk@ z&fCH~3t(@^BbBuC_nRA~W*$DriL=TPm>T8R#+!V$Ig`Ik(u()3YGzw&{@8EnyuAo0 zc09wjux-k5*>(dWFzIT4J_|DHrb@P_dQ8Q?^>fZONw|-F5XA%PgvtYNR+8TC)a#kB z&UWH|@!l=_y>SkED)VW`_-zV$n6CQVxvHP%PKjPWk?oA=o`)b+%z03dz2G!_R4_;5 z;`#^Mn};{-Fo%=p>VLB-6~ri_@cnJ^{!6f>Ntt1l#F#tLo{U)HL4~5FK=RYq1e6U!x^S3#BKgvhIY8%j~W&C}&8)1!;jM;jim=db2_EUj8 zngZ4VP}(@H%B;}ZyB9;ZVe-OgjGcVw$J#W9%$5h;UlG^h=xRAq=O6=IjF%f;*FG+y z-u62wnS}1jJ(_E1h%(5yQYjloTyHdMvcHV=botUK3Br% z8k~6_v_4f+lN|-LvE=jjaV=N+imS^f&~tPXGj2;;(^9P>mWCM;&S{p^B1c8}WrKiY z97jLdio;IH0#I238{_B2{iW$_nzdqX;=vS1;?egBqs8_gFYkr=w7pu2tTcjNJTo(5 z?b8~Q3M?8D^r?v!+fxGk4C4jooDB!QJ#T14?vzZ=!u?+4uygAc2w(vy$ zDZYT{Dk89MVU5}ugD4}*9b{8O&eau7e?KYeythwyF&AV$K6Pyfqb~kRQ#cOFRIKAb z7@buT+%F(9q*<;ROi%K@-i+$>4BP>5> zxxkMk;RHv}9FoKb=NC*oUpCy=j;)##hsm43!55&gam8Cr=cNpHaTCBsY z955sQh*o^e7|xFTYtR}UL-C*M$zyQHr{sqzli<`j5A_t(l<2Q=iWac%R;`Ozgw!5 zc&6dkl*Hjk{M`O9z2eWM7@xiC;_M83_?n0C)wX^0K`!&;~d3o|9M9m;6WE)xG-@V+B=Y8OREZ$RsK(-Od-DT`pQ4i$s4PT=o_STfltY@#Cw+J-$czHE7M_(4g14*f`|TSWvS zz^QC*{Gxu>_K9Dz#X;V;I+>V=X16Mbc5^*(*apTh0vBBHQAML4q8kp*Zv#CE+83hw zig$r**PgJ^o=q0~<+;dV!+93(Zdl zknSPJQY(f}tb^h;JA$N{^U3=~GnbdUsQm0T=z8bum1Z^rpPfuz>zye6RM_Eg0fjNJ zA~eBzhkRepnvw2jaupp{E2l$W1P}xI{yk!xtDXDfG5bp2{le5`+1a6MT)^#xYcnEX zSJz*_M)kMeD9uTW#pa;h%>!E=;w1!ZFxuOZwn;sn4Jxv=m22Ke%va)>k!IgOo*BOv zlD+_3(y`?wlkZrqbun7!L&sBVG1DF2pRqK~-^hW^WLMTqEs70@DZ(9FCWk=L7MYE3%2}f+JdIc-< zN}s2r^XKyF;iwwIl7Dl_c_#AELxTU({@G$E3vm%fiwF$eN+4Z)u~;DS($r~u7S>@X zP_kqrnDR;|8VBk!?vZ*;cc+m0441R!uO|x^mRvDDN)raT)FV?0L3|EWQ7}bhC#!jO zQPZglJLLNvJb!cQ?{E_cq(0I9#Z}rX`Y?NLa0j`A zPp%tP{ZES^P0Z8_&+4WK$hR784yq;Q=#j4h?aarNisgv{6FgY}aeuDosPRZ1T4->{ zUU4mhL0*;^A37dpjxxqo^;@z7Z{A(4vd03oJcEv1x31r^QYbIxYG}^R_j!6}y+sKb zfoU#=?Whx{y%Tb;Uju(2F4DU?A~l`4Yab`#r&<8nLQe$8TeGmo;a1K2rKgeBH_Ix=`NiYWi>J{fPhAJe|ENB4Nai`vy(Q2hLr{cgZG&g#GU$lN^#y8QqJbuTn-hF9x#WeJm1Egq* zK?WcrN2F|i)LjSdz}HW6XARxDN%O^Omi1%Jo#+H5K=Y9>M3df8+% zd#&3U`m5&f5Q#3Ei;RBrLAdN0zX0vh*!Rw!_R#QgVDNE0{xp8?i72xM(P+c_a8bBL zqepQz#v+#2%tBu!&7_S}EhR(R3Wv{%pfwg8TJJG=BSu4n8$gPLxa*k{B!_r~1VDud zP4=|QaP&oIw%CvQl(8yB@@SpI2hZYSDpJWER^Uxt9d7p2Iw%6?Eje3z+OS1WUj$B| zKCwn5x|lc4oRM@&yDYVLG$@L^KQm`7bi%0=z3dIXMb;A42!ApEC#He1(HuT6Wnfah za?N<^h6*!_GnsAK&s=3ILV-XQpkZ7q1q&JO^3CF zhWx$mjhufYhmMASD0<2@HycUv%?wq#U-CsdM>XGHxlk_`-T;6(yd08&U{dLuMk953 z#f>Z?gXO}hJ32N{_9j`t@nrRULvv10IIFXS;`Z5fODLt?Xt&>%v6hX|`9#_M?2Q?1 zo>+~2EEEx*&<+BNlkN#(kGfbOdU4On6M3e$iArF52*}BcRbc*mUd2Hc(FSBOlONdD zF`6sjcmK$kQd2y4KKj|-&}b&6&joO5?DH@q!R=cst}AxBF)7L}MWaREsKn71Hf4YE zCXFW?6&uaSwAjSLOt(z3!~D}!icJVRHJhR)%&CUQvd~c3AXmosOg=4qwi|q|xvYic zWAdA!^uP12bPsj?D&Oznf|3H}2zTexF-S4hHBGf8O5HehMKchqugOgA_aZyhEJMV= z;3&0YlM-MWs_EI#M6PO)iHOOJThZ@b+>V(p?zP%oC#xeWG?{IlVuG~EUM9+#kwTSa zi*Z?j{~&_nOXxz*tkeIh18=|_K)-Q|v# z7B!AnB>gtz>Jjg+fEFjf;5g15#?yHF;%g`8v6h7)8C846iM{`vZ4zD)%)($yv4dMz zM_B}`u^My7F*45VJf^}z3+c#x!o5Q7``E5CyRiGExe2`*!WjBq_ytW#5LqEX z(l94@XRKo7DnrxzYlZ0K{p0@Ry|nvTwsJawOnCc<)0~Q8dQz3Xu#W3{A+jLYTlDeA zDym$%4k(P@AogJ6><=1@OtB;EzmEA8x8 zQ_I-#4YO$@x;eflb`vY1Nr4&atw))_M}z0I0bsw~N8O!Hc1p7V(pa6n^a|7Z@H}-+ z6N5iA)USmoS{}!r>))-!yuN%vX#IDj!QfSR!3PdyD2uKx0|>?AK!}~8`_nVnPt_mp zLO!te^&RYR@0X5-b2@up-oSi zy1`_7*2=yQVqS1T5%D0+AHlFME{44hcV`Awgg-ADvPY;Gh!Ck%+H+7BHk5`q@^fXb zH0}$w#g<4fWLGvv$Ii~O=Pa=V^ndJTe=~pUMK`~)i2vA)wb*xt+C(ZOYOKjQwm=O- z2H&do;h^sB#mBBWr! z*Zds+V!iYXP2X$xi<%)-AT2(zdx@5@Gx}D-lql^N+K1ftOsa#SP{`ZrkGYzGLjzg} z>YqmAx7Yzq4=zvp3z7G?jZ3j(m{Tr27#vixaCw)|A44$o%bpw=aoZzVwPhM>BuW5O zH_Q9;76F*u=ZMR(48nk=^!KnF?Bwx25%IMO7dmaJJWV*I^|BQDY+IU3+j28)0XJK~ zuh0?`10IGq?+kD#Y*K2VqtEc|)oB1LKVg#WRf%!I7IXX)6<)Tm1#@Sj`uH2Bb>m+C zH|U>3ioU#bH#2!$R8;l#_E3h=VYM5H@leet`XNSC*`C*;n@ruF2>?ts^B+i+ zmg8oRG@`=X!QlT%1@p$>%kuJsNvL6t4mi7OrI8IKy)I59;P9EuEgNOcXla*h6bq-4 z;@V=UxtC4?2E|3tp3j9{!KVn3b-SXx*|W<|)X1op2wi5T;s__&Yk&7R(n7_H>99l% zRZWqf7a0mu2FY34y|p;HqQ8Af3dF@QnuFu2z8M)~I8+XK4n>#pG_%vd$56n_j*u2n zO_j&C_An!(vwc4ocut3ZS{x^GfU_ZvmNMT8vgRr0h)DveGbxU4b#jw?7utzRSA~Hu z=ge&1jkqiwkB_S7+N2nTdhJ#?O2aZ}|0)%|J)@u7wU&_JhO$moQVBpbulOT=|AXn< z1ViVO>zkqM&_Q3hrg_y;&kM?VwJ->s0IDEZvn~z#R362CRN@lm;Nx{JlNEGf^E5Un zVQ%9f?Vb1&{|-D>x`Ru*`YM`{-0r2r>-C9Y9q?m!Ov_pyM<|sAVg@z;Lp}8UZe9xN zLW_Htsk=NAIiOX_Q89KN`gPZTB}Dh?U{K?A^K$3GpMg$Ol8I6Y8p=g|U8xl(&>zVr zg1QCc_3=J7cif0PZwd0l)Ieu?iIZk-j|F)^)ZV@~BYE>QT5&@$B|!P49opW=cy#}} zB#dUEk6=j(f65#k^TBki?&xk1Ch8v`Lm^~cN0KlH22}olV)j(Ru!FhFV-a_{UhO)| zTWY~9KMNj8Pw0x1MP$Jo+tp25lsrs ze_9(1(8h1J@?oO8>R_jQn0Xfs%T$i^`yJLC1NI0<9NXa0A2>1qD-5fLNN2F%4(`9a z^*oq&r;{765Qf{B#y8z_wYNuxM+{GKwg#j{J%p>76guT$Y#AsJ8Cy4&^0{$^yd4d- zNlcg6kZi;R%JoO0YapC)leAbF>wjVO5d12r5rQ}~3=So5A4wuCkFF*^8y4IYG~qmF z$Bsh27^2&)gcNESulZY-Yk&yvI5RnSLTvv6za74Yhj<~{?I0M-Ydx9@k*t3YWhDLQ zaB&xhKF|PT$Ni-HzSzs@psALx5hCV%Xhnk>{+t=2_zHm+Ac@RYw8F*qqv840-hBef zF7S_xro>Gg?$CkKm$kAFkJv54g}Wy-P>YMd&u!NdQo&X zuIIGzT=g_*9;({SPiV~P+?HQ*wX-WHsydz|bL`poOs#^JgX%lZ)!UJOekcCR=upt6 zkNkdF6NsEHXdt;*vUR~Mn*ZYd<5TixSW7dlIIYXtgvF=kw8jSEs6eq?Vngp!a$MC` zwTiWqj18)d=W1|&4;DqH^HF;nG%i^;w-O&$Z#>z2ox%`FXrug*`9X(VSxy8>_XjIjk$rw4qRs{?#D&aEMf5(Cnu;n- zyp}6Xb+p9kH9p5=vxS{73>0Y?W6vAOJ<)$;yfJ(Y4#hQ)49uFG8l;>?eIOfHoo+jW zvL;+)Gcb<(>1yR@=Fd`4T;Vy+3KfUOdR2)X?cCmdTs^?lg%8zm#f>C96kWuG2d|(w zmdwmFetk#Y? z#rJLByDtrUc^^l)JLX=+jl=qaDQ>x^1+Ow0HBOC=g&*hjVA21tXsIpGCIa7nou@cz`l!z z#%M#N;6Kv=+hNETkUR($^c34uTFXb6J_<$fwDV52_Lt*rjITsVSD}DLAuk7WQ&mD( zb!4QcOzQrFi9G`3HD|jaO{%tsivhfZHdcqs-9mp<_<2*c@T_gkjr|<%Y=U{il#}g& z-}<$<5x1Ho^l4yrd6kD2E!w*u$V1<}y@`umR+ZC{izzF2{~uRx0aR7g?hi|c(%lWx zN_R+iN_Xd>yFt3U1qtaE>F!SH?vQQ?zkTq1@BiL!<_yD`*=Mh{p7=ezcgUef1*2S* zkIa}fYLz#$)d|y+I5+}Lmg>aURx?|@ld5p}P@YKo>!(G_SYX2m$2#F7>c9!+wnWLJ z{4c|i-CS#B?MA>Mv?>%dAksGrG=npbqwp!3pG=gSTrsT z1<4L$Zf;`ZO$d>^;WdC}hG3y121$8d3~h$0Q<1bA^0`tj1Bz)oBUqq6WoJ>M0wtCP z0)4>;lKXygALn^_?yM~6>r)7wd)1t)dRL(-2K`rm_QO0is;+e5hseL@=IHiaMCLX^ zpw-p@4cb9t5r_P(Di(rjen>AGP^Sdro6i>|=6VV0`o4Pj*3V&WLAm0SPN_K5rrsOh zN9EzlVg^y7~%Z|XwF}LB&C%n3eukoKe`Xq4}253(cA?9vq{i)+_jIT=m zebL9$yy}|7a!s{D)CE=tibxA@J-ci|0Y{y$zL%DkpyB|OG$J4&64o14JY3KHu&Ce% z@mJJ^d(j}EUIH1!WUDK&+gH^_{&uxuD`sLSx}6N6EQq)-8fn7;1AwR=R7opwAPaFe z-nCWkF1(&Mb;i-<@v$MY;>R|Vc<&i_@2{U02_eRE zSy_kNwCmp6aF?6A1T2q>NIMWUTlPteK?L9&+6EasgSbjqdu4k?%9nWNPc10X9u1gQ z1Rf0D0Fy~yKMNR;OBjYW(fq<=iNC$TTqErlcX#+C;OVBtr0@CmyRyq=>`Rd!nM5qH zN>C|dQ0CYm7=oxGa3FFj~dJ>I1j zQPsho7HU{6U(CdJN9Z|s*Cxw%2PMt59V{gblV3;I@dr8>hh>sw}hn9*-{*J=xP#osBvy%ofAiDz8xwrVj^?<*{ z)5cj|zcI<4?E=C}i|%PQ4$__w08x~^!Ww1uSN}1~)MortLLN+15+iBmi2)OD7P=bM zMftrypXf}Y2Tqbsdmy-H53v*kU~s=$a$iRl6?L-^$N~YaF50Jd=8bscHV6m9f<$;4 zQ(pn5nJWaoT)fP@Prfnb)Chc-0mE3FE6C|z2~%Fa3FBqy#Qh8bHQ8@Q{ittcPP`f+ z=$53o5|)_ocoO}H+P^1$F3O&nM2@?w5D)5q)jNQP zK2AA(p}Gh-ptov#$#N&K-d$ejr(1vYY+-x2;0w~KI+3ALxjbEdzMR_4jgn(dw+Vf` z<>^MDij;1+`7zk>l)7J7-%qyPK(jk)vVK0U zJw{GD6-JO-fuGr8?Id-D-uDM2h^L+e@p3y z*9r*Xl~n|`hK7HU>1cHqV7uF#J(tTD)J_{SldWjsT1Z%rH|4Yw%gjLGm-UsoL+{ST z;)Ci!rb*pgjTXqa<&ZHSB`b<%$Jg)EpEJg9Pvt*|tWr2%NEvmjHE0(!Cv;qE0{lJ zKV=VCu??D3>d@`n!`b>OHa@OXIn)SXMrNbHg zh36C`13ZVhTCikF>skg)6p#Tzb}uuo|`~>rh`HQu$a< z`^Eu_NO(qR7pb7skKTq4z}_y3+&hnvtp@L9#}7m2_s^G4PA8Y67&lvzG&_;jbz63} zDe5`a33Fzt3+HiR3|*hLK#IOEd&SoZl;Elfa0Szn z%N?3S4T3JWO}dJ+6FGC`hqO;v`Z(aPW%~Ir;9bak z>hI5E`A|AX_8t;aWFj2 zx6j|(LC{Pz*kx?-644X_2mQK28-;Vwt=&TuvLsFRPGPXZF!amz!%s4Tw+w{(?uT*S z_45?^jdckTl)IN>aSQdE7Jhd_W)C!e-pXJ3wP}cMgRlbvFlmz;PAoo0KIg*gpm;jAT7!ZNY$@V=2$D=%R>8KCpI8w)3Dq-pa zG-C0F)tpkn7aYB|cdEOx3}iKd$sEb9GPDaYkLMH!aY8p}ljDiEZP=ezI^jm!DgtuX zk9>|&YR%X?{*&VU0O52dQ65@YSiEwWnW~sAavB>#g)D+_%_75WmQ|T(!cihN9KYSh zfp?gbOya{uKSCRt#kC4;m@g$ycsa~EL6TCmo|(Yep(DPI739#M?MWv8w0TC9oKHlI zFvdJWL!vM;7Es;Gg3Ns2%Q9Wq>pQM);1K=6zrUuE?2(Y`O0UW}T%FXLTYLj_D75!1N#>`aQ5H2Z- zZrE5%nw&gd3UWv3c_TIk$6h>h1bM|ylzrf*0|sIP#sI>=2rUPXYvh2IzKp)(pE7US zyZVU6*m*BrZCIR8FluKu@gC}-iTLRq%&T>6;!8 z#~n@dB&$LsSfRRYEeuYPmO#eau%sk3ZR!|j;#U}Djh$SZ%y{R~wyd3ya!upY?U?Yx zgIArsZaBeRJa3SagV*Zi7!HA9a(s@JOm70N9DSv ze_VXLUE4HSQOh%zdSn(i3sb6L+c#Ha-kJkZ|Mp?VhZ8fBI+B+Fx~-s_?J47W^m866 zwzl{BzAUtYe-_h5Dds{DsflGty`O5d$`{bA6=*(2ZUvWrRqP{*ZwmK#==dult5dxq zxv|LKkv6GO`Fpd0X1E6#v7o5fpSZ##A_9_v8)4Nf1nQ<2SDBwd$XD->rG3 zl!(&AXjC7qnh9PnAPtD1jtkNh1`^h8DeRRn8AhPL1nZkFWzBp=s<=(O%sKknfxANe zjVY8YWOxT!2?mWS`1pkGmaSa9$wD@W^?F>hD&`EVfvji`J9XSmyoBtF&CV|;z93AkH_HYrFC#*0?8MGo(o zu04~tI?4A;#3eG7-nIflH$-y9rY%@ZP(ziRmR8HIq*u{J9|18*e0UQTLf62DB7taA zrY~mFCANntZ*iE1gPn>B=ByD2q2>kSwS72u#}CRsqVzh2ze;2|I(#>w+N-~Ay}H#K zO_BJ$St$l>9-IOc52Bgi=pr0wMg7s89x63I-XSw(8e3bF>Li3NH|mHxQ5I7M5w`Zh?;|OdzrGjR!~G*w z&6YU+csOGy@9y9x6ZgvEdnWBqr#Gt!O%E_b8%#}8jLgBan$dD?ms>LHDSw|Ht7M$A zzgN_b6y|)QjgcRDuHly2ptcJwd;2O-ijY>Hc!M+xenb!~VbCA29ZH;-aLilm73M{I ze)x~bm6GR9ytD57`o$}PLpKNMK)stpE6A&~F;2u)5Gkc(0tJTw9da;UOW!zD=&P7o zN3m%9E!*1>GzuOeMyVbKd%R;2B|`1|-3nbb5*e$eHxN{~U^ET5LaRel!-~iOaXMe+{jG_pXzVq7v~p|gzb zbkzGhY9a<#jr9`-AI$$Gi3nvO>0~KM6*W9mBbGI0F@72@%C z9Xzf$RW5h=i&;HMUm5nERB>-y19%Lc@9dkejUUbJ>l%33()J@rR$V6`ocJ@BnFnHS zhBrlQ^EB}W#9>WLY+yY)+0Wys{pcL-82C^|7uj&*1?*=V6lT2B-{jNPJAnh?0CGrA zb9nM<&8GJ!o&%Pjn)z?*BRc<8Q&brtM(B*`$0o>o^zkv=q#Df+u6nnFyx2Vtt=?JO zq_{AysBE~N2$86D*#58>b_{imd)xmvj&B3s7=v@zo@}eQxrCAo--ds!U);P;MVa&X zEr}DA4i`Igu>?tiSf53wqHewaD3jnz8Smwkoy4xaTQp(cF;`#|kkgVvG5SJyWEpSQ z<5JXroKRBo$bu%`pO#n4VbpC4m_E3i&b0`FMvo@@B3Fw0q8^BK=lwm-{hQP`4es!0 zYt7gz=bnXS`4A5^+m3g)NO+m)2}uq#w2g^X%$?;99zNAe=R!UGx>GB-tmq;pNA84E zNwoG!-}--1Dy~8+D{^2PZY}HX5lOICjZ53LosR@R)3$@rbuT8$#ppp&BBzU8*( zlgG!D?z*8P0^Z5H3ZzCfJLFU5FyW#aL3GRd=<4!}dCYL9JZ)PB$|F8dV+|=9&+xoT z+Ds+}Hero272FpL&f3fcHbgpVN;G(dSfNhEhFJ>w2w&~LxMD;f5b)p9m{tqY=8HsL zrZ1D}!Q)jB)nA^R5htJdRD8}j_Ce)6GF;qDh$nDxsM2W0oDC!a&QzM#`8AxN$wupm zo$);9IG$paNODt)zR0ts_t-T9ehOdGQpGwl`EBwD&+ce2&Th$-y;Q)&=A~*!>(v?@ z3!V-O=f+qi&2RC7=L0m$<5RXzk!!ga-y8}Cn`s(Ci#FbtNT2UP4w>z5x&ks6BqsD| zD+5oLG4^NFW=dLcoK2ZMn!01zQDzFMFS|V`II!Y1NrS#X2KlFP($~?1mPrLeNow)9 z5D)4PjXbOg#}9_7T{dD`?h@gU&blJ}!V=gmapY5`V3cpk%?ETo4^}?#*hi@|s1PCh z?ABrO$ULZ3$fv|7dL=g$Vn^OuW`Rn*Rf>ipRH5Bst47M`A!2Mvn3h5u)%`p;<%Nb_ z7Jr7g-p*+U@H;TLj!;e~1TIGr)re#ev~C3lhglKey{D89W5|}6WP;}?{2F_NRcQ?A zvfX7lMvpL`g<4wxjkC37TN1yY0|W)K*rIeWb! z(4Av83}CJN%6$qdAzLUx&RQcUAxe2;{k@g;ZvA`*HGilUB^M8=zMiK{d#j6nULzh) zb|$+N)`fo-k83aCSs+iP+m3cl2Xl_E2i9RNw$fWT*%8k2A*~2-%|VeJ8e5h}!+C9X zrJ>mT7yP;@eXhl?4Fi#XqU`Gbh7HPuOKNCTwb$hN3a-`hR5t(J7-{i=C?Vt*k!CNe z-IWV`4f>6TAOX7vm^`RIJvVZwobqgg$pHml;$6gGVlilr3W)HOb2fJi~8!FBoP| zA&(@En{iS@Z~RFR+nAp7&*EMsh0usvu(jTfBmG+JZh+-@DO*v{gP^G+Iq1lRghOOP zGO|P(#YMRhTAlZ6*0XDxGG3Hm@iX&Zj16q`Vr9roS_s|{G1gd0BSSnqyri=EN=YK` zJ=IBjE**44`C*H{wkxA(V-^&lF7HS1&+EQ_lm9)4;rm?YX0kDd^{~NtHn`&rABtTz z-uG)@702{mySbpKL1IZO)803;7e`_z+iflJv4_>(IsgVCINHemNgndEg3zNPkIc{9 zLxT$l*aqt~aKFOl(d5NT-@;g+CZszV| zRf9}4fl7My-Urxe*r?`qQbt=JA>VyLUb5))FHscq!_VG0V@E~mN+FFeS@7&%EILr_uTGMyKJJ5TE0!MPF0a>k=gI^}IAQdR`f$oAZ)%lUkk z`X~m*>hAY?*W4+e2%GQLiIQpL=ZBq&jtaKz^PhSILDfbxhJlwe`nMxF&-S7z-S)P^ z8q?`RVczFmKXiT{#_x^8K6H`H4Iam1QX_w?fxi&MQXnh)CW7ztUT3-8QQ1emDm`Qm z|6%xo1EDpdUErwkU22l*5?Q?*$nu<17?tUPS_G;#9LI;5@RQF+{ad3r5sp}-$JQ&{vO=@#*8 z=w2C2v1gyl5T`|F%9r{6OQul*Inf`SWuOIPib%)ZQWc%>Mp-6OTY4So%L%A#lef%N zJL44|7Yv&oA0u!H6uH@Ea!xU0sduNfp-?|=UG{VG6t?^dLJ)@j`=zgYqcd*>NMn&a z<aCNR-~LZpa7Ddd+mM<@I)r!gc1 z$i9rT;Li*2OT92azSKirhTB(KOqKxg^1~|5P5aq=g>8+jr^34DoglCfu##iSs&E zb5v80&$0;TAZWtlza?y$w(*vvV!3>fFrIcZm41@^ScxY* zExCx_*B&}S*v%6vg+d@8rk(d&ROo_K1S3W6! zsxBVvB=o##eSmtqR)JZ;osNq*tRKrvR!Ov_kLjGOQq4A{T8m#it4b2gI2OE9hkH7Q`lU|jXH?_2J7n((=08fj;f(BavRJ1d9_0R0 zJS|3t50Y(} z69z_7o);dliRsq_=^9n<;o|jkyC9=g$Zosa+EGJo!XBFEA4hiKV|l8cce+B8Ws5D3 z5>ir=ea4l}U4tJp9PfC^+OvNV0cW(&CyV=GghgByB`Ye$8EjaA^z$C{cQkGR-8o07 zY~_NI85@~Go{G%Waeia*^ngM!NnJsM zy{Sn5+^UWR28aS-qShA5pzV*ELTYFyze)`U|A^6?L2F8&-WgG~L^$|$HJ{uDG}LvR zmZhsG(?iD2$xO6p;ys+Czx#q3&C@)#eZvP%T$N@DxkM2B@)=w71kgQ{GB;4{Lj)dY zHa}gB1x+pY2Af$U6^9enYbEOqLK2lhFH&Q!vkT{NgZ^1cBn^S7CkNe#lFPdN;I~sx zZij_Xh9I@0452#-NMITbk{TYq1QwmYnuq*vW^79~!hv zxn-BH;|A>RyjOC73i<|WZli;JC6zXyWYuucYyuNTd=#roZ-GAPKf02KMf@zQ<6kuq zM8QoJ;Id+f5Ntb62AZiWEhCaGgyl(j02jpkJ3eI=`;#<6y|@X1uSq$r?2N{ep&4Sm zi1jOzMbYhBlIuKzIdQmwDIw=gqxq$yi%l7?)XxOwLWbLY%lQFD5o0J086gOZ)oJFW zW6>vZsm@ru(|{0@3r$$+C)OwW8Uv*KB;XBxWbHm%ODKYhP~~vbq$zi|QN&HGY=oPe zpQfh|&~k8AU3w=p-igOEnkxMXB}W(cMywxoH^>fP4l{SS**1J|t7A=oA29W#X8PFM zlsn#@UDoLX*blmNU@Ow?p5;IZvD28W+JEp2Uv)NS@S=dL4!YtnbOg~We zK!v0m%`iyifadE=^^OWbEb;AASAp_jV(i~JGSUI9&F&-oKxlOqevg>Asu1LQ^ru_w zZt6{5evoiMUf=$^By=4azLH{F%)l*kuz{BY2Dt*-TWtt|rGeIt_5#-@oH$?RAe72H zrhHJ9dIRP)?Q55?P$Bvtsj-;2h-xV#sh4+G}9$a_tY7VL# zf4n5GRR(^eO>Pj1h-P7tTsiLQu&7qfRn3$wJGj+N$l@_7e6V0anvLZ~N;($JsJxFt zirkwZD=Q}*;XwMcH;4CMX~QNK;N8i^)@%FBn-L@|&bbKuV2!2YU+jG$3m{ca#HMoq z3WRo12X|SF++YeG7q}nb)?YI2bwTiWl2Q?W^ESnroK9+=fS2e}g~}3_nGsoM6s6#6 zUd*u#rx)qP(a4h|n%FC^J?&1ISU4h>R-^@%bBE~v!w|`hP4KjdyDMJ;v}7(KLh;#y z4g5z=pvA(bLY>wi`f!^QE=zo+I;ugP^9l;A*Q&@6E0ct-v4p&yO1@{09nAIhdJf$2 zuCsedgWUx>mxVj(9i9qC@GPniKgqa56=HIHq}T4d2!J;qNqZV9zRXOlr+yJ1 zSeZP^cT}wT4yHX&@C_0g+MjwU#srC3sLwrr^} zQojY1U2bp4gJXvK4=~zfzhUJ3IUeB!?u+s#i<34t`S?}1sO`Gd zIRAT4UpdvP@_i5>=f%#Dht66?;bEfr4nyS9j!X?=rXmEDcf!3Sh|FVy&%8d4yK`aS zAoZ7e2X%IZOQQnlhRL$;Y!a8)bDh!ctipM&T=3sP^U-n}FD#zifpZICp({!mb0;J) z==4XnJS?T!y=#;kjb>Srz(O}p1OrOun=Px(?oW&#f3_^3s#By!jI8XWt+cwx)XFzp zfA!FkClR1z2hn_q7^N07;=LU*o2IX7t!`a($iy5O`^QeWm^Z7+$SYK)L4c&)1_}un zN31sa9@Pw;Y1FJNL}r{5g0HLYK-fY3MuDxHG8B#wPRWX1Y?mT(Qn7X6Ntr5Xr{R&g zilm-~e0XHh>s!4vXhzw}#eCJ3%Rs~C^)Jf`AQ~7LHkbpznEX>%hy zMDtv8o8GFj1x^D}=}I!#UZ5*_p=64Z15Lfeap6s2Syr}jtmd&Y+q>2*4XCu4Y+@BW zD{ItE_uT}S66=0?wnCJN??$3WNCv&^{%Tb!FtC^nbUklYo4#({78tzw865=&E|3W! z3yaNA6P2U!M)(E3 zqmkVA-)8}=U^{Ky!ku46tin)iu}r0Ye(&0OByyHt;*3q(=#(H%xsPQDwZvjq{rL*R z=rt{3@D}0z{CD*TliOzSL)4^1At=^bSJ8GkOD`CejT*i;()s;Eu(F*5U0W6mY6O78 zQUgH<0_+QEfHL$CW8x?i19DxfGWNuUay*sU(jMpSvCwH=C&t$!K|r*7YrouW!d*5f9S+SNW%JzL#HC1z}wHmyi%1u4EV*zNZ* zaVQOE=pPGhWQAI`E=1L^jinC9n`BN`4hBxJgwL+mGDap8Q&tk`NoWGHGMcvW9l#b= z4l)II^P;J+u!1=6i|*D4nUrW=f?VN+ZbPa*14J)6hcojPk*STh>ceH@zd?`<1N0AD z;xaO2&Tb^)y+_m8*FlTUKO?}TC64irAV~91G8v~>EJvyfv)(7J&sozVi94+n*+Mcm z;2C4O?}=Y~&R1PIfB29n`*^z=I>xHX3DF|*B(Q>`O%UZZwDlW^-x;MKw?gDNK2Y|b z%pBf^4eaV-vDTI(QL-YyC;o~~s`%Hrs3FtIC-<_W@WRe>V46)lPuyh(W~vZmKV6T< z&4gIUT5y0ky67At?!J6Z9Le80!Q?Esx+I-jP6!>IhRCg#mv+f=T~my~u%5$IU}*Eu z$~HtnT3MW?-xRh>45LIx^9)@M?b!LxPH%eA4ndXo=autM00y#r^p*gvHIg@knvpWi zuou?)5rDnJHweE8At*px*#z(Rc-@#%M8R8ui}df%tWAp+{oA6k?7u#o(0IKj9oZNJ zG!Fnu9bk(tgsM22^Weiiz3ipataU`03_pC5$!Y4~06ZI#nU-E*gDaJS)O@^y^6!}7 zW6_o?IhG9_le(b0ilfZ7W1SzO10P|gN4-s5`${&L1(LbS2#UXoXXyt#fr=fU9%Kf} zob^LY8Qi^=3lxY>Qr%*tfY^@614s@-pu3wuHg;_K7BT6d)EyXdYpApRa2_nVQjn}z zW}4}_+g1A;#vry04CvV(JCU1~3!?h(!fxRfW^Y}&$6FETF4V(1p{Vc^zlJrG_Wtl6 z!sj5G(`*pIo-+ERe0>9U_HnIK4E!+KQV-&VDwsLdZ=q3fxl>0ZIa1fy>W2Q*m60Z( zrP7evhBoi6l<2{Cd_3&%&<&y4?~R~p?&4?D&(#_%2`lfz`vxO?u0-?Nod(=SQPMw! zAeikw{nZ@EzBvlf0wui@4YyrFh-Ka;a{cw8W$&LGA@Qbxsi=p>H&(^!$p!xC;R6$? zE5dBUaQxS8$Jz$ntxde9%iVpJ23!`%;EHmgch+bt(kEe|+f`+(;`kiN>KiHO;o>HE z>1v}sYQbjzUH=VW6Yg075(3c?)rQhYv|~5SEK&pkicHD?;PCy1f<(?#;c1B-N!(YE zl9Q{uc5WbZ4UzaA4!F-P&sRyoSPFBp@X~g$ZV0=Vilxg&@1@B=ykXu504U=hx+ZL;%mcy$Q1%9yPVFXs+m5joB7{wSl8^M?$6pS`#8eamv`1Pyz3-4ve%f#PVbavFgpLW04Q&Kd^ zra!J(@fw;!q$XtmW2h@v6C+m>S&5S?Us|89a%9#A8Ok|S+ZQaPj1k9a~`UuF%% z2soh0qla*ET4_l9{**+?Gls8rF-Q=g?QpzC9~=OEN>3u{+5n#OO1vSm%j_{_$d|#6 zh@z#I>%`U>mLZ-<2Ft^FBfOBupqUDbfU~ym!ya>Q853>e@*)|FsK}M$)gL*jo~*ob zp>JDab0I>xAcV2l;TwhZ6d8=W9U42|_euqR$(P*9q=+K8!Vy?*x#Gw-#K}D;w#72? zW)h&`mQ;cGOrIX=5$Q!IK_)XkX0Vb1p%aym!*^s z(+K1BpHEPLxj08D>g1%sT39Wn{qeh8)MUXGR0W-cl$wBLmPEPXqO%uKfev5wy%b}6 zDMOrF2u5G9g@8a;g!E=PcYDPy6uCFqZgxRZPVWaPtNRDFy!I}{nhW{Zw239b)Iu;Z z^oW-gr{uz+)l9zZ61r;PrOcL>p(Dgb&|H+`5QH5l{Sf$$_QFE4Qvapm$!-Sf1I5tb z?0uZ<1fv!cBir(z$lkvW)J{Z*2!bctSBm7L`ZpQ|MwF)2m??o{le9{EBy3-@0BQ1E zsDn}xQ9;>|qyk#w^T!SyC&uRKW+&j0HP!<1m*}}uJ9q8>#kA=sLL%38wemSlmS6Js_X^~ zQ|=}F0#&@M@QM(sTv*bgtroGWp4XjqG|8%?NypD9aHI$Ry(VO)g!9tkRSg^XD;F2E z>d5(=5r;#Nwk3M|9ys+um*C$lT!6-xm_mT%@t|P|zK%42j-pyPwslytx(R&1YFkJ} zPCge@PU&6GJ`Q%vdFN_w%qGp#C&*QZBV6#Xz5=S;?Y=k4*yf8Jxo4l{Z#{ual0&W~*OacENLPD!S*5s~p|NN$?`?vd zQCqaI*pS}1=w{OC~-=Y4IWbpX#s-XaYnnV61 zOwr(?&4+SAkELGhTAomkbfExf;|EO&avpmYJ)+17XH5O{Jcpd1aw?Da`+h&c@zWba zgDD@kXPfHQLxClRn=uH!zqh(K8sCV>bJYm4x)#aO7()KTlUrH{4XY(dCl5udLqn&YN=#5!)WW(tI_GhJR zdu~Gcme$)Knu1Ct&MgXr4)WE?w&|ka{1^8BIC%isffQV)Woan% zKo3};NEJv^ZY4R?fyP)Lt1Jge5<=m9kBfii|Gz@vngQe+vZ;qJfghAc_-onpP77$5 zZn$bGuMdW=$LGpOe}1N0(D;9HK^o9T4fy_5;aA?k*5P7=7*3LHEKPgLZ@9@oosL02 z3E)nr>xBPvtXD06`~s}u<4C4~1nh8_3N=_;x-v@}v7Gy<5|_onf^H$?7dEEI_jSt)_S%x&lrN^;HNv-*u2h}O4D}(+HvTpDHtnwASieI>fFt7@M z$wA@$tZTJ%1OlnMDYfg%U4Q;1Sim?2wsnQ*xs6IC>M=Lq;SULDwqlFJMuH5gzBAPZ z%rV~P*wWF`|6Ka-2b~b)fHiodE6V|($i@Y#;u!hYi8SRrL;;C+5Mu0mu>X2^{>eU= z6|1BGnK+AUWr6>X$lth7AUcSws>~|qyI)jlfXdgETWP@adH;J6zIVWpQADB#UU!HV z0E}AFVkpmADumB`4Y8J<5(bBluO$7?-)aiz_n_bK;@E%>qj&<%MpO>CH`-Qg#?lC7 zF^-Q;uiobWTcL9f3;;azr&8eCP$3leiQ5FF5#USBo<&7w9~#J9ZcG0!P6LjgDgdg) z$)w;hGg1iDutK%k!lVytlb;35(E;uKvAR+9&)NSUaS8yKpzA+O4j@u#tbcRi&Tvzq z(CT>;ur=T?-+Wa`n0}`HA3nP#0Y4$?8|ns2V6qUyv3RYzgyvy)(MQgM6y*v*l%JXZ z>w1G!@DWTq8NLD-#shEhVamN`HNmqvZx9Hb0mKK++FVpzD1Nb}U9+OmQRuD!Zi@aNWCi|N zU;-GuOx6GV3f%7k(tvGkrsTEop3t^V+sn~9eE|3G|3Ah79y%LXG@@hRfb#*M*QA5Y zMBbt8J&)fvEkxx0GrLJP9OhsALqF2lbDiWd zx5cDizci-2_-pGuWM8p-WTR>5z)e+UxjNsH3y;j(+Nsm$Wg_m75%4TiFp4igV=%U? zN@f)E`(qu=GpZjnpWgXcim94sQu)uQ{|`~zaluj@vLr%m98~FW+SIdk(Y&))M1hXn zCHnlWXoRE|y~R5XA0n%9lB^>8CbIzvs`HVP#>CM?sWv??euHT~u}>TN2>;pfPYF}_ zfU@J`m68(umy;JtFNFpvpqw9t0&RNzl4U}=VkDkAY z>8EYI@^JBqeGs%&8>%Z||FhV9dK$s*igNYpneqtI`B2FqFbt{Y;UxHfc)1V-=*k%U z$)qdMbpuIh>f4DsX%*|}(I`gg9eJZr>2-y^ot=Yp`Bp7cLniV=6Z~X){^HrLjoAZ8 z*qISr!lT^gYhSNLo;LZ%Tzs#&9iT_*iQ21o+hG{DH@tU8dGYvjsj|F=4d3I<_VnB@ zQu$C_>QEff3WuLY^(v*U(z>aCcg0yj8X&Gw=Jq7#O&5(6g5)Lnx&N)9Kz5HFkX0`i z(+^exp5J@k-LfNh#;e$}@c*Qof`{dWvtg?kLtv)aQTMwkgf2?`=+rK}qGewL9sG1| zU&SODer3RR%hepqE|WWM9pliH zomazD>M^B(e-R~dG^}BFuWkfVWu^G}|Fd&Jov``it6aJ_DTnsUg^%u$HLAEI@1*ah zurKDxZ7Ge22xt4CHANqPM4ReA7C*Q|3vgfUkYPxC)9OWXiI=9HzSm`vMuFzU;{Cbe zdVovAjae1eXz={)BVXzAGUS%Hz^V8Y$av+K4{_yndbWp2hA-k!xaHEZp>(nTB^O=~wIE`f1^# z1Qi+0^i(;3YA(VUx1y&3vgtvz=wHo&On2Qcbt<59T-8(J5LMB8JYE|+m6jSL#1Kaj#|l%cjpS16-v<_ z_8dl$*0SYvWtoSYm&7q`%XTeK2{KMjPbrkyTo2b&+RAyViS6P|0jnGvcS3#yW|T<)1FccFC?tF=q#zEBjhezdx`g}IZLP-}I; zA4_QGS5G1r%^ql%U!=KOq3@w#R+-CXIZ9-jJn5=zIOx%m*duF^Nvsp;Uxa7Ylsmq8 zb0fnu42-*`U4>4<@^_$dGMGH9&b1!r>QwOlIAymVvihWbLwLnX_MzJjr(<38U4ZFL zarAJPi{c$#o1SNOvIHWYR!SgRYo5hOe}Lx=7r!2iIFfJkR9*)XCvNamKSSk=8unOP zpuWP8Zgx!4b(RI{0Glt)NDWd|W`qViL>1fCnNEe(wHvBd)X4DSD6uR!bFNkCHEc)-IrWCnX zc#3hI=I(VC1Kq%G5^8ViNJmqUW8m@dqMVLJ2A(7__Y?z;J|E)6cQY5E!&&Fd`?EQ7 z3dfUeLke8X79nU-)GWW3uq>|FMm&Lf$!bwzEE#7^pQ}2FOi={tFWzw*htYP*{5Wi zjaQnYa>D#$r3s+$9wq$ogw9qTeZQg^FsUE~GG1x;SpWMJRpD^r$9DuJeM zOLFgi&&x}m9lGi;FCVSPyoh7(b>E+?1>vHxs$ur+9$XYTyi|D~C$--6l(9J4&4t1C zJs!F}`|w}YZ#!-V6F+47JqC;_g#N_*z>esU{{x6SK%`&Wu8$0*U_5u0Xha;LPNF4L zjw>@y-7x3$CfYr_;q~dti_gE?sw(ZR=IABTLQ~E?{!e-7zg|RCEWBX@0_oen5?3jM zTYW|pHkAnEpP`1sRZ#lb&%{TWX!U!*L*)0ZQvyDG!;?6|f4b~d_bMc=`<0`A#0kYp zbZ{^V8i=Rn{=0(qFh?R_3p^hDytGev(||K5pqjR*CO2z6FY85<)nM9@$17uJrH=po zKHkH1Hm{?~$fEddly|oJy36m+pr_B2hzF#1LpWaX8P{R5Q4F|f#-7e=n7@{kXa<;x z6C(Bb>0H^4Mo?hqO*1U5Dqupzo7{Xpg>Cjo%hj2ZsrlP^|5jS`Ty7n1T<+ie8 zojm&a&DeV!6&g(a|WG@%s9aYSCTYZbKB~=h{Km! zzmr@~&9^T~Pfjl}r6_+Nd&PV`OyA*z+>tFT6ZW3{eto049HwBt>WQ6UO}#@zK2c*B zt^wn?q0W_rt8~Mz>1^5sA*&+5-VxGkIcm_5LCwDMX&UC+@$uh{K-sOk^R;!oRBjED z2U5{`=Q;d&vicw2s^g3L-2RX22E-x99S~ULOU*}OtOcSX2&^CG6UEOx5J7Y_AGv-B z<;%R~(boOYOk1pp9TP#> zt?rO@I}Po)>`*tNqv)j93+I>R?_@BqT!Du; z@WU9_Ujdmp7c(=ZCfj3<(7SNiX5wY+s1`8?L~Wvj)7iXA zQXb5?-weKu8?DdV^x{u+FGyLwwQr$rDIA|?$eM09^#whXsvGtWvb!|>ozN0b#-RSx$PESrba$zM7Sn(fmEAZ-WK zAcuHH(ia&GH_tWh^%*2CZ%1P&NjSGWZeTP3`(&^avE4H_HSMu}%t|7n%TD-i=e5Ej zeL&9Fd|C`BAB%|VVH^xaj;Pk>hRWt2LCWkA1n}}j!fS*}*~dChXXfskb#aM(pV`lE zk$?Zl`A*da-nT!1;An3p%YWKJtn0m$NxPZVUgUzq;s|J@jLxMuDw>3VEz(pUQADWG}i2nT&9nBG#uuAG~ zxJ)@x{Dj$ONemK(BwqFUTtttEyQ0EOjUhJxlRm~Xj3A2Tof;f^XbJgx>=FNM4DP%c z8PgLy8b3ld_@1DOo8g;>t+1lE&-x_3)MXvbxMt6@$Ra`5aHGk(wUHL>x|P%&LyZo< zWMqhA;&oj9F)b;1gdBF8AStlu6@8v6}ya zQPh2%?!Sv$v!<$&4iGp= z_Z?Ll@JuEY7(s|NcQpt$2{jm~RhJv5kd+qpP>n~sArK9pABE^}b5<^g7RP!v22NAz z_~~669r)$&*gQlXyp*QB=?yCz3iHRX?cX`l{da$W?`i3Tp+%8g_mz9jUpF$1yxoip z0Dmc-@dh-^I`5Q=B10*`e1UU&x=f=U-_ZIcQY4fPEt*@Y$n}1L#1hca>en}NbomS6 zjl+5x>kS+hcXm~z&!3LNLYs!bItWTWRQm9f3pzRswekVbdoyRAQE@*`Mxeu-*1NX6 z#F~0xiqX$_GKHc=zidN%a<)vH1}?sco}Ya1XgJCcwnGZ;hsTT8#}Z6#kfgj{`MqW7 z3T1Zk>Bo#+jHa94Vk=yswaShonWrLOY{!DEs4+IA^XFB|sFf@EDQ!&KsXS!Y6O`7`lJRj-HMNMCN+;yssrpL4qD1#k3d3 zF%eO|=`Pg*uN7XsMR08Drs>Ec&t6M5`g>!lddohck5OKI7Y)67Tkj=>m9&QLj1Ft) z{{JNEf1C`jr)BVmP&wv?^&A2NT3<0w__8*;#CK z@g(<;jZ0+}A?g&BkVL+asX&yfyy+NKOr1*`!;B4KwB(*Y(&Wq!gzZiLK7FMi+a~Q1QSy6%$XS6vB7CT7ViTcY`&t-A7%?F}U-We_a0a zA07Ew{Gm%5%9+6_2lQf;0v5ht_6=^L&~d6v{Q}En#5*}`yn?LOH~S%mw}Jsp_;_SK zte6o)PfgU(w6O|q2?_TjB?cT!d#1~qJ70sNw2!(_D`)sc=bPO1u30cV#_&+7(Yaft z+M@zC*w^3n78c`M3uyU~#X+;d%|ht`V&c=V{v!>lDuCk7TyySQZ5HPph_T^uwUQzS zZ^)e`i_zy;}EV@ShvV^`#soBQtC{i2aa$e*2W=l{1nzk0%TS3deK- za2of-R}?oP4bpXl&_q;c(z4*vfRy<@%QS^-w$!p;X^G z(_d_U-)6tcRixQ#d=_ygdj|FMxovn_nOBfjvxTYNge58;j}7gKnE)lPuBX# zV0MUqXubTB13}t=o&n8KtK%Yy=G~p3grZC2{of!HF>$BKa0Dy?7-@#D@~MZS5I$*i z+>Oc&pm?}XNHjg0g3XgFpFdb|Na-f_QW~`pzn`&w&Y@HgDU6~cQ^RK$1`>F)w7R-w z8P0p@IGLak=|YTij9NC(DF+*sB@Iya)E+V8wIKe2;8b6ej9natV0&3oV3h%xv{d-k zZtdDDzlh_>XiLA8%#WESH^Rm_fDT&BUdb}{*v?eX!tDy|1VK7aP?h$uF3=0db35e7 zmHRLnfkqsi4J5IBjU4ezpVF~iN1xo9bGo$__Fjdu{dmrj7HRp z)WzDfVaop|d7$f=mWsi0QZHFwf7(O?3*$5Khxgql;5Q5;mm?^#(SQQ;-Th}A;a$Mf z78G~iea-!CilZ6l-W&N-*E1?ZD6;eS9D13=)4^{i3-Tvc%u*(?W8Y5CW@gSz3N0)f zTvSq)@*L#mQlz$eO;0}9p*b;`9MP~mH-ZfiL@@iT2=VoZvsVFI*UxZ2LHtQ2W45k` z^mNxfU)L)1dEd{u;(vU!n56}wC_%^=Cdk(0RvoC{dE^!JZ@;%&! zjYbHh;=9<1I&H`8Ch^P|y_Dy6y62mEnV*@6`(Q-76`2e6X76Y+QMZ^Gg5#OWO_$cy zmRDQ%dCXWfxuOGCTc3yR!AP-4_kHt8NTwmx9%HUj5URXP{2yWO+I^7mXsc+5xZH2j zkwoSz*QN*O)y|%!4H<+mVBqyBP=-RL#*A`22T3KTwk%R;IX?-E21ZLZ0!U59N~OSZ z?^L`SpB-r;O#ODOkz8(fXt?+yecb%!zj-Yoo9ZgHC%#52#uhP>E@F6SLfWE8*GZlz zYl{gdK1*!iZLgnvoZGjnY2LftvC{P4U4fmaR76fOvZl^u z3<>{{?@zG!PSZ%i@{TqE$MDug7-SwXYU#m@z3@?8#sz_K(Vs-Y;X4mla5Y}09OpB^ zQ?&)LXNTid0rZ}01_$(e(N%4-!c?1-Tip!VwEaiY9OxpBOnfOmnA8RdKI$%WH#Nyn zT0L9_y`g@m#+0D|T&mCCfD1vs)gcZw4#S@n%Gl7%ecoP0I7h(BkW+~odW`ABR|jqE zA|}K*W8O%oaxpiiZ@mU?0hGZ|*XoccNHC&ajmS}2;8$Lbarb1h5>M>iU}6C$xd91Y zq_u{ROW##M#O7!xa&K4<3m}b!^Q!4dq0(Z!kg&RXZ~E9%7?Fq8^}!-jdW;ZKJjVIM zrTY#Vl5ttL@`*ycd`0zWC|y!7;%A1g-)Rhu-Oo*o0COgc7JNC!s!`1UWZ1Wp1}wU;V$v6So8saI)P z?@w%Qn*Og*e+c~t@foiF%D^r%(GP33i+s`~eOcs%;A#U#&Y^87EDGIqa21vG`NZHB>whj|t@49w6 zB$Jvm7Du*pq>OQqtc?&pn*CCg)KD@k_{b^ty_&gMTzVFmdnEHUsx(E`^v2awARgAE zaKZ0u1dkLVpoB`a}QtV<&zP!*hb|@N-KI2DDr|bu@|S=x9qK8J^+kGKuEr05Y0e##QMj4vwcJ*&2?0apRo2bwny=9O3M>(igqRu^>c&4Yc;k<%^5fo zOLNl`%=0oxh0qK=>H$Ri0E|FYyp(gmZ?}Sx&h+}leHke&eIg>!ZpwKg!%zqjb7Shu z!#V)lbj40PV-DySa1zO?^?Y8^K+zXBQh||lOFu)Y1Oh0CqF+>kC~-Bzb!3~=i=m<{ z*D-g>as!94={Q~-eDg}sRz!)M*4k>84-;4vzx`M@Lv~TwNn0hU+a*JnfD*lwGJ9dJ z3NSJ=%~yC14&O#n6n3BMt-dBK9&4F~+L5f`z?>oAgdrwN>CiZ8juM%M{xYZ2>qFg> zOF6e&&QT$vy3U9@ekCj!lI;GHJ0D{6%3`K+=_bzif5R47MfcNu!;Ab)p^q!JWdxMPSjfWo^IujU|M^ zu+bOP_0(ch`%Ty-fKX z@7;`f#361IMxF#lQ7pnFJe@{SaI*DO2BD)0PaG0YO~AUxH4{lJ)kj(2Brqm(bv_|8 z%VhEQRM)3754}gA_XKQ`d6vFIU2r)hBXYChUY4Q1awID&lKyN8b#1luFe4wZU$$wQ zwlPKOLa7%Lr!V)!l1#WF`ojwkjrIDtbzIkk_tRflU?VtypEU`->$6`SK%BA^FM)kV zs>N%Qh1aQOU>TA#UR$JPt`H+Mw~`BG()gX`!9B_sA6pY48%dqXWb!f^JMC$f`>V!y z-T{@FRi<2Q@pqq9j$3Cs_re$7=U-;a_eb#qDom1h5mNFTb~h$M}Et~lpG?wh9lE*<@C79;z9i_xFezYkMmbhB`z zDc--#z%3{V{J|<*0@k*Prae^L(OG0j^_M>;FFN*)eA4H!5^B49k`hYsz~q5k3Os&B z#}`!rmlfkDs?6U}GEW*~KKMGuSGehXQzN~RFiAw(qfg~d@_=kmiF<9CmK*{yVgBkoyK zkP8 z^Wa;IB9!&n(q`cqk@ffV+Ug|hv3|V^R)q`)VDKt?9`uGqu)W}`roIp>I}hB%d2Xgq z$@7697CBr!KoVOe)j(CSMUensykPDlnj}eG#pj5gDZ7)k8qhVeXfs1fDC6z0WyU()%f8e`^E$`KecrfhE&vWJBAJkO$n4eXsQ-5BJqd+pBCei?gm_`3@$|3adsjou?<(<`wc=1srZzN|v!0#5f1rJq5OV z+;s+@$f}Ang4eWZeIGexbnCOuayMAQ>=Vh*>gm^vlPWWs6CJ!>?liusVX?ce_I0)l zY9S^ayjB}{mlY*Wiz`HbI=Ar*(=sziR_wWgR%t4TbiFA#N`Chf?uCU(zee8nc9KBB z;xOlO~5%S@P0F!S~fKfr7z0kYbAIYjG;gxm^3CtV4Lmswq$lRI>i*PPAOYO~v5h2e$@bbhdtU7gSiV%!m4S^Ite}6%B z;jbT#KP>x2!=5AMJD<#SQi4f7D;q_Ibh{MkwEfU7PZB?Bf&$xn(ZwJy+#3Orx%T6Z zO4-#hE9usyGHm`$ie5 z0`>C5d;@<@apURXl*QzHr&Y^cAy9-KefoVUH+P{i_Sq1_p4jr@=JznON3fNdxVvFl z(FsYn$sXcFen{q`Ubm(PCA8ETF3-H$>Y$~KA)TWw7!Z-Nd(lcfh5ttB52*j2Xd?)< zVh*OdqTY>%K_Y(E7+J|Ztar}2#fmGZ+#?1g5+B~Z7C{WC$Q!kkwiwR17$xez02}c; zbKk{W-PMc$5O0!gu@Q!%@19*P8uIo3;E<9vcN=rfd*ZTLIn$)-mu&0=`j{yaJXVq< zz&iW+d@v&JR691UR0KThQcY_V9V#Ks$%78@`gn8&H)bd$<3@pyOx=B$1PA*3;2yYn zHkyTW68tBxedZ`Ogv3##rf4SJCh6{+cWuu7s;PF2`+xyU1)Q5{m((~&f#-FuaL)s- z>erZrf;P;(4v$^1pg5u5N$K>Npu{hdU!uNw1gg$fu&xfO$6jyeaww!R*T(Lswh9FX zjFK%6CV-_I$jUUWo!pxm##H5@eq6Z+$$oCdv_?_gZbh!#Wb{K=mRANgZB?Oseya}! zP9mZ~x_n~yqea;>{S&_+_sW^f){8eOA5S_x4^7(2Lhl0ulE+-RTG#5FnM{I0O zWN4L0pRcKx2#N!0AcGQ>Ax$IXMn&yhm`Ehe<2gSnK15=V8xesNi4D7n9SREBHg={i ztCI}cT;g#R^-}q1O5|@Fq4Y!b<6SeB4I6p**t1D_{v&d~b-AJvU4hWh&ImT4uR+#U za!GHf79)2r#ny@=6i)YfKL9fa!*6J_(+^tuT4}UpT$y^BgPI7fX|z$bV|t=yeZ>!% zyxZ$G3qkg@4l^d`q;T-2N4btQ75&Im>39?SV}PEGws`C$ZoyA={K7$}FFgyhLTJx7 z+M$^XMbD&eqEJFuDt{o}GJ%&oSEPtE7i&c8&Mdo0s!_bCh|@4X8;4X^N-!m@Y-b;l zNm>|&wAKu`C0_rlW>Ou-JFzbPu&_JOKm|kuD=>6aidPyoZU|ROs8Dmyi+p>e3K8bf zYwFs_cX~JBS!S0Fsedbjl^fHjdNN21KV{%VM3}wTQtGNSFgZ@-PC7Qj1fIp#J;w8x zxiE#7kPMZK4i#E%$ixRibY~Fvy3Ciz2R&HKyWJe&s4Z#8sJTKmt7poib*Tylg~`-L z5A4usLGDn~)h~`%4%SEK87XmPY)ZR8)4TOM=n6KH3&B&jc9PvpQKLElyhqFNjM~!_0;;C}(>!KlaX*oV zNFaAE%W@u^yZf~?kZb?|=@ZUHdPBBBka9m0)c^gUCLIqNsVBQfB@)0rz70L~(uG^=z_Kr>4?~UoZg?Kq)rJ(pyW%?5HI3)f3Rk@MQ z(jRL=A+ch7!mwm(OG5qyQ~$xNFeu4s@%o$Bw<`bjMvWiyFeqJ(sv|Lh1&)0YUNnwd ziZ{v6LkZk-6Mq-WKadB-J{Sot)f>J)U+r{8hMaN?Na1$4Gia!`Dkm#krJ1Id+xu zMR)2v?DC!tMc$1eNcH#X?i|Cnrw^(8G=l~0V!!$b?sHDjn-n3(hL8xHHW3N;Te;^B zGWj`^VN5Dce&+cS>8HpgA6Y7>TWKZKwUemPDlhuCSFad>QroN;ZK(020}!nxnhR5R zt56T>a0{|}=GQ0cfMwPn#6-}KDar$Lq9H-CDoKD_7m3>RyFy5oq5i3G3m{2Yoi?-dZOn@5mAK6p}E2 zWOeZaaq+5mM??2K(Y}rCeToR`7rY~1Ro( zmtR>`{R>62BrIg>bnxNTxUFnez5rOX=55a8vp;m0(&rr_gU`& z{mDO1`1!FoN|33`8YUGit0^!9bbzy7EmP2skCRLmAR;~qz)^-Xu2+NDs1BA>m)?u> zm|z^%4)9Vikl(}4R_CV&&g0mVsQEf-9`O9HVrQJ_=T?74&3v=+$1}p2a-n6ae}fxJzX`?Og48v8O~7*R2WfVyL5nAfd}g(2G2~p^(S1 zjI^7$D(+$T&sD433_}(=+FZy8`l*!IzTET6AsUcw$Ln3HS(ELk^Va za;mmZg>3Qemg9!!qIBRredOx{=?J%Q{}spo!$!dR6)i^%fsu6XhFq?D{1@gFv;j3# z!nnJ&>K1_`$N_9pG_5e_Z4J#88)BYQ|C}L`lH6B~W*dXX1DSF6#Egw?d9n1G4vXud z1N4@j5Ox{mHtpw~>yUt4vA%Z{YE>ZpWdG3WKP>g1Oi(7$`EkrF4K1_VOO(W3o%U$d z{@5yN{3Go7X~z6OkZWYc>c++m#QVLgTeF`!FE3 z;64}L$CG5`<&_pn=2qPRRMetQW5Y@Q@I{9Ahs$4-i(L)m4w<_w5Q1rvCD@F0oCnC| z-(x#x<%IiBX0jIUj0NTt?+;L35bUqMt4hslsbtlnb#h}dW@0$Gj`7oci7wcU^O)5)l2 zvuVE_ENR4fJ9sMduViFH`Ee@M>-CsnL+$)D+p_#R7``CmpD4gD1GXdnj=`R=?d#Ku zgcjryoJBi!gnYB}FyczT-QxL-1dtWRgH8;#EY~?`g=|=k&^=uYudc4vDm?J~zl!?9 zSv7!w$W_{xrS%E`cB8hq1dh0U%0%ljkQ+}SWtB(W4i^}8c$k2StX-{`^BrJ^1`7lO zmID$tPm606NfY$1x>^)KcFmFnJU=3@wzm~DnUj1d!v-A$ zi5S^w{vl2GcH<%+3dP%@?I{?NyyK@j^G4K>ZERXy40q(eBplyqtstnt=uYzqvQY4(da2vbL?-HTHvVZ&Dh53i;ZCeykP%xQObs1*)g0$3ENa(lE1{O&6 zzv@j!y`Hy4X0_Erpmb59)D|0#&Th?KCv=`l3g!U=ZdM-FB-$PVB(N1v>b2wAiBbnM zRY)2+QJFxCjH$M?Y$SeioBr*Rb_stFhP0l82k}JY@R3KUdKI!5K8}?OL@Pc6u@FIU zOJt9{5=qwu>W4T%%Gs4b8>m2#$lHDOAdiorFK+so7gE05SiErbT9P2jY?w-@=-?11 zAN>r$@7*87$eg~@ThO=Z$X z)i(r7q5kJC04jz{)!&P!D%PW)nx6JRWfcliUg98Rm;u{aUV%nGA>>=&BF1Q{wlnc4 zoj9q?7SNUI?eXcEL$w?k<7D1h*s^B0NwbSI8Xny|+KL2IPJ*AbK0F^sju2U4V`BYG zT*jTBea^Gof^%rj@uwkfp+^89l+z=B{fpXcOJ?c6HS-gUe;Ldsy|L>BMd}UHIlwos zP&71tBiabGoj0!3z-6J|Da~lQo1GXm56*?@Xm>#PQcv0}xsEG^No;1rS1LGqaEN8} zotFkDKM>?e?;`!Hwvb3|G@+7682o1RA9`B%;+J{s49PSF}!Uhzhpz?XrcA(`t$4TaRC zQ8rJy|ElZ#aHKb`)RUpa8MYPp*MX@9`#D$VgZFBIFlLt zizIddy>Qs)tmW6MI&Qr9jjNA0c6Q0b#6;vPuweelkY5n9WIGLj7pUq?C#yCH>GBi? zn~1_yQf{q5lvLC?5~9eP8(`uC9~UzAupXOYpO@+iuXaU(Du9HAhi^J8$iV|Ir;ygZ z)O8+iJzP?D$50N)4dJ=^jZE zBEx?ytC||}0ux4(O{JzvNxT*atK7768zdum#OGLfl;!8-8hRTd!_*U2j_hg5YXl6% zaWxt+-!!gPGM$KViXU{J(a{RqOEIN057;4Y8ycR_1U4cmFk9b#5FvhPVuHPs4a;8Y zx-5Y8m9KD7FFsA(_e%Wyt0=v1;V(MZuF(nWrhI=V{Esxu>z9wgaX_bE#ig`f3u-xE zCM2SbH*D_Zxk}%gs|19-&F#2nme1r5x<1W-6gO;@pzbz;8w_< zhbaBthF+qXsDwMzb0EnOiO(JQ+j@Ue;6wztC0S55yC>*9B5k$WidK@ykvnGjn&Qf z!5*W*s2+m$5Q6s+gp2X69!SNFXn_N|ab@1Sp!LoQff^LN!aGA&jUS249*ubLJ2fZ8 ztMFQ!Z%96u!y^wvBORjiosc42rInTI1qsKOn(J?Pymik+sMC{K$&lUB=Wx2`hLEJC zzsiaR78QK_%4L$67?~qE+eoftjxQH}>vml$tVFas66kMCf4PB+QWD?rRt;m_b(VYR z_r15Zzb{sP>3AQ(T;id>EVl^k4hAr(`I@rvWA%6|ctdsEm+4AaT61kxaS~U%1TQtN zxX6lwaz0*$xIIVcZsc>UiDlXH@}cL$c?7Gn)o<~1yoW5*mV()~yFKn@$)8 zv(0eoH5O>~d>5Flkzn+<&f9~J^aasBk?4J&f0GIG;(n`GkNjc#3F7WtNK=9UTdiV1 zJB|IP@hdy;=mp%R-2o1^NZ=aO*_QN)&z+^)(NxH0UH`?9#QD~CPvIu5O=k}Rzo1_p zP@m2vjAkx=AZX`mLlOB&KbwUS*U{gdKbd6bXcw5`$&iVeznfo4 znsYg;dKHA_ZP@1-g?m-4J(adzNZjp&~^JktTBI`-@vHF3L|S9riZ|TNt+A zpMDDrgbXZW;j8#pcwMh=MZIqvo0XR9?K20fV_>EDPmp0|3K;0^RPq2PiLI62hhQsS zE0ra=+&8>m9;aOG_jb%{U2hqqB$D%u{fZ0Z9;TBz!fbs`M`&4=f!3NFo2#!BNU4y< zed~_s%nElssKjpjrUJbJZx;g(4-Z_u`V#KmFmr74gsl8vzVVsN9xx9}95R~Jeq@A% z2L0g@5|x%>P?=h4(nM^xG!(z`|q9X9<3EV?mJ(+_g*v$?WV|kg8y9$OZ;ma?hD+QkSEd&;Kv%SGw zy(!-}FdffVKCKgiAewc*H5k)_GJAA{)tU@4H9pFl#7-jb=J3f{eG&_5X+$i7UK)mX z+=21i&NI6n7;gF4!CO&-funEa{-P>?(80UJAF)UMR2yd zyoRl^q_};=YdC*G=0y<_Vv#U1#rtBKHmsbzzH?oC2wD-V^WgRx3_lQTTii5bTKjj_ zalrrI*dBW_$|3W=-Zok;yYN1A2B^<21%mF4B9iFv@?7!hgdvH+mH?)fyStAFXy-p} zy+{$U(YZr#GBhJ5q{Bodeh=D&iDU#Z#}uQl&la*Zb_-SgR#ZgIF{{-7OrQJefY28} z+J=Ye(5;2n-UXu7%nI1J<7}B&LCe6WVc8pVlVuDo3drUVEyOkxx7K$d*+tx}d9XgB7D_TK@+RW}Y?3Q-u(nlO# z*g!;yt)2!pSFP`4%xuPgaFo&OY89E7B44XeI^G5O#I%FgF4Yz_3&khJHbuI(SV?z} znk-=cM)lD|mAza2q&c)LPlGHS!3+Y=s20$4oDZ9t53`x~_D5b6{Z!1HZL-wO_B1}* z$GRdcG?19vUXdUZhf>60JEI6YUyE-_ra+a;S9v9XU`z1iu!c62;3bul;f5v(yc*bf z+&d^-J8+Lu1Se|J?K%lvMCh=Z#<#JD5guZwa;|)V>o5HkhQ~+bTHLO%9WT2$4+ow0 z4+q)Avqp1PEeIWVFEHx!iv9LfZ^>^3&4V7@xI|jDZk`7pbwlT=kYIbo`m@<5%MxBU z3q!1&DpDVpz(;%H(WqSF-P5X2Zkd0-t)FIM=X4m(jeMmWb*00pg=!*3_Upy*!}IwY z-W`EH8v=PFP)=M?Q75GPXt&=ci$+unk7A14fVPmE9iP?yG&9x#H8DwP_dpKo?dGb| z9a>3Q8M4rNPdUGAg^tZw_t8K;5;~0LF;ZD2*yT+_iUAdKdX3awd3yFtmMdb^LX`QJ zW*e3>+gCt@^Crdmd&R?{r6=PS3?s%6X&Z+XWwGuUa-A$Sr&?IbY+CyVZM@+^inw|I z%&^u5EP%#%8Za2M-<~TM4aI;8O4)Y1HstBVMf@VDn>90AqB*!Bz=kxyT-)p&A)Sj zjRGbs*GuhfeGK6=)uFNN_LcsME)H`T)2q$?h)fN%e&aEeZ%?cE4?Rp^8pmAQ5iTS0 z>J$Zk7h5);L1n0IBr^e|ZHNXjl;kPmIWCVDw7QF7euAj_l=~Cqxa)0>z6=e%_Y+q7=5-q?XX#^t+ZoJ+{%*BJB#R0oVi5`Y zT@L}KNc16ND;e5Cll5nL?Z!afj)Rnn=+#Qm^f8OuXwF zi_idL^LafAnr2arem2>t$X+8D6oZRB9l0;xFLH3k>F2uk{K+!aqROks`yt@H9Tg#?>64m1+#HK&!KArqGBg@2 zyA)ojYNv7$O1h<~8V0wgL}gPxXq5LQ&c$4*D93qeeRa-IL0yR~l%~01tY?9ysen3_ z-i>ZEpq|CF(jAYF;XC`rvhT%!Ebfv_1rRfMDQcUb{hqd{pqQoZDH+ zx}exAw9_3hr@)@8-g-5#`AE9a%7xSbDelL!Vq(=tqk1?-0zVOEX*{4KMr4x|Dk(1p4#)CFjzN>}B~x)pW=22-r{KOlki;`J418YZ$Zl-~w`|P^Ov&Uj zaP>PcVOki7>F%4iUYFb}=?q3EO=GWkp9iS3Ac?onhqo?((K}~`v{ZrymGgc}%1#RD z?Ka}F1I$a<8G!l;@;fHyHObMiA3h%bKl%TU;QV;PJCVb2(Bl|#wtIbE4s;KuCZ7q} z%eCMumZj_ofm7K!>HLn+tDpI2*x9ptw|h71<;k(-_VWSHmmeUUaKaZ#n*zRv05~1s zXM@XIN_)EW+XuYE>r@PNk;4AO2&bF%j_#XJCLnuzM(AZkK%DYhdT&^PM`H#&*vBBL z*9NK!?;Y7pgW^hZo;tCyK?I@Td594%o@wOPtX(ph(Q{RdzpPL@3{r537OyLEhnZOuO7Q^TDG~!3 zh@gHy$3g&yt|yl1FyF(D69g$&wp+8&goOO;|89E!13No2MD;@Z;HtXHB>O=*-48y) zBHV6@TB1PnJ>JwNciQ<1aHr@w@nV`djDd2VqJw$)h!$}r2j(&f+;!Y@%j4T&`*m?3 z<%Wn^gei~Z9lw~jPP?YeO2$HhlOx6t6Ps`IOKoPy`S4>7xx1(k@^E?a8+Z6Z{QHOZ z5&3-)DVaD9Rg%J;(OIwQ_(Ha7JkZc9l@4N8Qnc8;4~>B-gOMBWp~`-HGMwGSPj|p}`~2 znb~wa_)U~G-i<_)I~$|?$JC!tMQ_ zY~t*>TX+}U%1Bg6Vt&@jGGkFoRhXN(Df+)J`k(Qcj}8;79}ck%B-3SBG%w1F?wJVe z8{9R>&K3W;qj5n0G()ccEWrHe65vAXhX z+_|`af*QRxZ^-?cI}AirRlw?F@%;i#Ygoy4xjf20S`9B{TaQv2aR`g6@_kK$1 z{kkXid1-U3_SBUUXO)drq<#b5Os_k8=gbGo}9&SQ=!V=kChG zo(cr+-=Y^pMEdRoqD_CHO>MN4We!qfzt(a%O(4=}{hX8Qh(*y9c(EVoGCn`D2 zO!H(T(hTiLQS6~{N`J*se-%OGFkMjyZ;UJfJCg-{(e5eMQs%cfdbdtCq>{21=|MOj zr4d&9PZMBe5iC)41+fCEWwoz^BMv~?O-du4kDb_XL`Lq)ixL`$lq(u9y?WW2xj3w? zdT2X5Bk4@eU~ZS}(82NGAz7VX`CA+K)cl>3j_Ky^uA2iXlikOGF6ugM6ky+~Rd(|* zWk~O5HKi;~>6@A?%FC9t`1NdFm4{wInlCNw#WCq=(Tn1kTi5J8u*55b#S5-bGgcDW zM&V0p+VO9){yq%`1VfS6gR^r9TKW8K@b~s6vZ{l;f2qO2>iF<^bz^#dk12s7Xf9H9W0WqcPnC+cV6mIyJJ~4T6xcbyr>}?;pFuaxx zqSI1J>dLO|dg3lP{C({1spG~C4BYc?&(S*0E;z$YzVK&RrF@8~qmSMV*Ma_^JX-KD zTT@cNM`D0Cwx%~(pgTOPwHxgF<+?9Q(4z}_zjU{F%-tYF#g@S9n1Ip-=H5Gkwl>u{ z4O~&yUpBwe{D;VFbWSQ}86igu@2_;&UVU)wxTl*z3%qRbz0bNViQ*R`6(@<#=9_ou zJ*cYj`Zyt!yZ*+UI2%vMB()uyO%#Vju(o^+?sKt?F*VB~*I3`yYK@e z^BuX~T0J=shnaO9LL$j)S+|Mzj`O;OuLLw`wf1~g))s7Cw zE?`+z6@6oQT_!p+DOOIT$4VMt+oYul0dz`I$8k|Q7kG71gt%fsuscEq0Y#=yG= zy6rhmP9w>B@8N6QxuuvhQRcfe&Dr-e;qxG(msMY`fJpsfiLFBi7V?$_CQgEo22?pY zI!dShDfgl{&{NW!Dzonz9r-3L3ttc2{|6QRV}kRNA6<7#FxM6i6hnq}mB7SZnn`7J zVf)Y|@nQh>ynT2gM;A(*y(m?BV7LB4hK=giZ(Rv${`FVN!L&o#s+aEjJ+aGpsKzJw zCteRsrPkWux~@2P_}swkODK}cQOm@sK1t*$c2>8lYA%AQGotO3=;r*kow!zS1{@u1 z_(HVXh#>V@GZBr@2opv=<3t}445MD{;8_!quL(Fb-@~F0T)R!OLnev$^s6)!bq@O- z>S1;iawh5MO&s{vK%Pg*!X)~u3xrEcWpip5ELuT!}_$xggSEEtB}>3&c%cUaZnTrY^Lxs3>2|wR&R@b8yuq)&`}yK4bCuYF?;f_KN$f=nd;cxNov|}npyS8Ra8`nB5@RYoqXf>(nD`)8G z2a=p}A*8G)G)nR~=ItlATd%Qu=aq-gNU^-LtzWVt#JR?in9PmmUn3?SzSX2k^TX>K zQjqwN*@TlIMQjK!OP%nz;Vbo1hH^w|Y*{mTX5{^)BjrCjqN1d)Mlc-2^zIQIwm&0z}X%hZiQey*#WR%@-rp$vfO7~8z6?d z=r;hOiDs>kf%#Ea!F5c>z%F)As1&1cs$3wr;@zq>JPCL-ZvUXP=J#*%HU_l_6p`@6 z=%I#krJuI_B*))Oqmquow-q%QgJ~84luTGjd4;1zgoc9ySe6dr5X9&UlMBt*C8@`H zq0e?N3+BM5e8P(@Ag+t`UJ4VwsZ-Xia6ycOO|=ixi>xHL5~;byz@tbArXjt26g8jB zEqIDyD%N_{RA^s6Kju(RJyd<1yzIV4uGBjfk?2!gEpn`IXNn0yE>e<(X>jt?S*orb zys|ZM)b{YwiAiZ5lmL?^Vb(~j1HLjHRbQVL0j~nGn{@SDAZFS$Gk6!>sh&ukj4bRh4jQ$?lSzi5l3tBRUhDM&(!F15BQoIvtELY=dt@+bfsK zZG-%hS<@w0BJBg+fT&=aKCF~$p#E6s)ibGcIV&*u_jT-Jp06^=&O=g`Oj7!mwbKQ6 z`1L)xZ`LqdQc~gjybF$Xru^4`!7CYI!FNzCWT4tnU;*ekr`jC*G~P;tA|YTa%tAFG zNzbbh0}rD`Z;U})&YMq~PhM1nKV85Rye%LX78$8W9QG#|oCL-8rsb5PT2%G4aC_Ph zUn|HY23=u=cSOUneQc?I(%b|Uov-1E{p9g1erCMbf&)z~b}Wa5H)-C3mPswJUuV%? za4#a@_1&CCZ|KnD7yRLEkt~W!Iw`;0I5~F-2q6iT(!G(!+KVQ~s~|h}Cj%8>Bl>Wa zcSV8y-P6>;fSKIp99$c6!Ssvg$z?~ZBu|f&PfWe#y?N=Dg5UAztrqIx>Ws-QwE2S# zDaMI0Bc}(4?B5K?Stqz020DIH671&7$E8gIg=F+;$_w)-&Ho|mt%KU^+U?;MC>q>@yF10DxE5`3cPU;Vc+udlEe?f3 zad!*uTBKNTch@h^`R2^;ectnDW-^n^z4yKMTGzGKy1e=)ZDqICM?Fown$cqF*>N>^ z`GB(4+TZd}up5Tn8`=4y%-GoM)Ei`A#<5^_RCBfr)dr*=kGk`Ts$yd~UrZcgI z3)L=yl49bK%=T*9y0PbZO1!;)O*krKHI>kY+u5a`qy(yN*`79zF*z9t*nW%XWRjQZ z)S}$3cw%Zb^3GIQ#R9%d2S%u);uoKHueRF=uSG;)CGA_1VGzbZEk|5lpE1p5zQ1Q= zVgA62^FjMjAvy#NT9}aRa2gJgSJ-wHd1^NN#ZnL5N_Ymn7Qhq5hS~B?b``!=S6_=} z$N`c5tROOaIgfLGg1gkK!sRNBeli6BP~0=PXKJmI4@*EOoa3FAbPcPuxFquxvhKRX zztbkap*`3*du*(~+`2rB3SI%?eh44Q3UC_!MD%D;s;Y4pyf9Qo^*)Dd0fS>0LT%Wi zL32qpMDlE9Q1~jCeyT~kD;~zWD5s0s(hdJh19L7x_3=io{PkV)ccE zwtCbN{isQ4sGJDbQwL`|81d})GyEP2!34eAL3F^;Xzg@O3*e(Z>g1@$sCs1eIp@+} z*|Y8rv9DK!%sYiZx(sknC_YPMm4l{WpA5euTDjF44O9RT30}a(41t1z+|+DlKlA-Y zg65)Hcx&TlGcWj1ibxHkND@~BCaoB?Svz6aTy^V#sZ}yQd~c0S;;c9nwd1DKZtuEJ z3oc=g%Y?ONkR=>eZla5wI5-t3^p!r`Q z{Og%gI7iKBa9xZsBLhi0PL=cof za1e8`EyC3NNq7E}4yW||x0lG1>F%5;#q%9vFQ~>wW$ou;p%`%e7af_>WT<=~zB=JYvi$?ljh(TfRUV$nvbl)(= zc`=cG6x}Djz?4v&p5jYr0cpRoGLFF%8Hn|v=&kT+*nke?6dig~K=@l+I%?N?FMOgDtFKq(&Sp2`@<+`f=kPvfJK62L ziG~aJT?L@^laIWkq~T|=PB&DQy*3}82cxcvH9cy5=@lNM_tRFcfZ4TnN)qop0-#>L z_lpeBYB?9sE4lC0IhA+0vfAuo(Bnxv;qQ}{9LEQhub#Ii&R3L@>WYN6Qbq<-Blb4Y zgg&-l*{ONIh*c&ov7GN`PnR1&YJjnzQe4!~Ii*wx9Iu|O=Y*ZT*6>NMlDQ4#w;OZZ zrdeF+SG9B$z`mc_abHo)wrt@-duxIbJK&hp)QjZf%Se%fuG?kV<5HNfrsN*lY$uzrChjH5}lpM=@DBOJuc&JBnT^{^ou$iF0%| zHcc^6Kkdv``sWeFvstP4HWh_$0}3%I$Vv0(KlUPjh(YhODR(miWd^+=8D03;kd{d~ z=dP^v_Y~6VbiMvX8+k-46`JtKOuV5H^4O4Ux(4NnB>5_*NMXglFfIcvj5Y$uVO*P@ zN`wUnW`az#-}6MF~wFA-4@7`?K>a;#6Mv4O~5 zr+NErCB9*ndDFuD1VU4r-FDE9>0S*@QNjnFzMle@3kEhMJqbzX$kJ>8bCwV0&2yl- z!P}`+r-7xI&!B?@p-=dFlm6aVFkM{STkoeY%LbuHr%XJOrmJPAKERI$fp!Mz8+(0d z=8Wk8({F2F%1+E42gFz6n5+L(g2OJRyDJo!y9M{QYx%SY>Uwi#s;Xoa zpIbomed3_vPvBSVxYMPu~(kI6;-aOL!K4UQ-P-AE@rL&^rc_B>dU>}vfHgkrUlVN^D4F*k^z7nn+w%z z02Zxeg{vNoiNP(0%vM8sPqs4}7BpjXOZ3v&DJW~6p#U^T3A<4fP#{U4*_~0_))0Tm z#Rad%a?Q&i({%hg@4%A!BZK+v`iI@wKtL0Qy?y&aO&-zdbQL*ISmBm(!v2T$8B0?zwK@Y#Lwk28^WI7O!T<@RzsB$fL~arWEsVoYqf)qvk*0nfo0b+^65 zDi)A8ZVtY?EMv-rdSNk#k&_D5+rGxp^L=x`eBN9JHl2iM;(y86c*^bi>NNpgl&$up50*Jt&p>u^+XT7mrq#hbvn+f|XS5B%sc2lecj z>e+p#1M{E;^5Dg%$4N1}&NkxZ26<6!x7m7`G*4D?SzV z`n19$0OFJ9U_e{idp;9?YDHgI`1B3ww7lyv=WZR1o(T9Uu>3cgn#C@;uQPFF$COMQ zGlk@qhLPx?Jy+zKk0~*bxTelt2}Q;5AWvSRlFBIdcmU~Kn-I~t+8)kNO1-F49wq1m zj*#5D?(N#s0czPV5A)|14ZKrg$sFC?D}(Kp1dd-xM(h-A?$~Pq^|%8QNFR}-el&~d zeHWFVhS-XH*}hJS`-o?9Fmg<^PqulQo&<6~Wt3e0+bB*HvQqmF(~(W`1#Ux|yfYqt zMa=hsFaRnRAdm>Tr={is z8Yw65VbO6hqy z*9I;QxW5AKnqs$_Y zo7SXB=iJ-anVAjvB6d{8EacwbDBSH;cLC5x2cX>B&X*eR1;%{8WX|{1O5JVU3GA^3 z`O*`S9gq#2C(!`xe@V}k`tmkTQgVDX`DR2*43+O8f^{oFhuQ#9VyjgIZxC$;spYBM zGhTbCdTj^RwYw3$se68VPK5YA9k=myOy;9PFrNYk+BrR=b^0jnCdqg<1q3|c<)?w? zJPGOM-zo+};?Ki=T_{6RaC#zaNRe(ZxeFsrsg;{_jh%|;5#=^sXqhx zNw3@h@%KJw62f*l*@ynK@eZml`uc-a-<2ntDRA+!eMj}Fsfk;yUZYS?hF3B=e*YJ- z!TAS};q2|3;vgfzeSL5J0tak0v+1L0Dw}jB@E9*L4RJy#k4h>8Et_O@&0Xk+0 zxHYfQX4XwpCiN4fDu@O&pqZQFUR^PoVSvqmWB1NeUF@tERj47s&tX%2B6z02JhNZn zLy7!DYSEj=Wmec`uG3#M?YxWlA2L|yPCW8U>ffqxEwJ5#Zhmw|F?1@9#M$E(jE_ds zeNj@3T(@vUa>D)%{)C_ITCEX7<1XK$RfB8)T_bi1mz#pk727O4l8XPedv#w_-DtZn z4E^Uqb2(i3*p(2Ym6xFlk*O56OdB4O#fhWV#`@QL-xj&^j=h5)x$$&x;aeO~@MsR_ za2qlWp7w?Us+O{tUatj!TE!xjazYmDyO)p&EPJ8yoZ7F04-jVws_KywII%n-K#F8k zTMz)JyWnP!dvZ-=;&CdXva%N2NyNJmA6R1`Dg5brM^p{=yZMTk{*@<;8C7TzoW6-e zUG3*X=i$gHkt{cThb{nPVe_iB-tFZ_RntsD-YYJ}aecCmp0D?%{pGNXA`Vf@Z{s7ipxTZo z(YGLTCFl&s!(a00vFP&-rRk6_JODOF5$@KC&HT{+Q;CAsh;Vt$ds4-ShA<=ueNEYNY|9 zT^i`w+rrBMWg-5(^u%GN*OWPu--z5jUYdHlil&&w?y1&@(79G=b{}2k-$f7JaVBw2 zb7mfl`hLB9fzI|ik9by7BQ<}#Q1MGVOyB5sMslOg_?vGH2jBL(I=AA~_GVP!BF{Ou z3On-7_DvMm2`37BnzusFGIV@EbE0menL)QZKaw1Sw^WXiU0zbLy1iWMdqzf#GMYAb z-zb%tGArZfkKCuu56c(|>_8mVcQ;hBb_qXJn<|vGFQ^Z!Z4GhtslHlF@lFXAQ?6(u zBncZY4b`XF*{iIJbLSknw)N{|Th=SaEx$41C{c?fdW^2AbLiif7E5IsU_wT)elLHx&MJGQm`q!W?aZwfzSBz@-6-b- zsq7!~JD(3IX1@QRGiAcY&OmT&Q8fz0i^M59h#pM^z7wS$OeN=Y&FW9b;)QK|F&?l1 zAxcApdTw$DsRxpQK_OGd$Qr!xiE-H4>mSrIyTRgL#6?8-P|uuYPz7j9{>P|?Ga9$% z(AOM)i*2GE>x@FI)XQ~Jm_-;TnOkq@iug?ZXapx@>sEvHgA-Rq06|aYv*FASYORP- zZofk50ut_pE6V={0EPdc>6o;j1!)3r)uwhMphPcY0Oax`EK7qs;6uY(VISoC0`WPM z8-`|M)oDh)&2yE?aNLrcncZQ-KeIke1q#YSf@=$Wb(g*2iCA%q<~xg9>=$tTU>)Yg zKas?Vh`g^nMo2T7O&2_|JZtg>Zx*Nv%>`=XS z4d!&t!mSGzyLG*Lbs{*JIxU(i=i_t}Iv0Jf0m)*)8IPChc!G;X_6*Wmvie>2zV!qA z_>KPxT#hBI); zkq!CD16gQj28;mF)U+XIcsp!N))5Q49Sf0&scGo1BVMFd8Y(DA8D7rWZmU1MWGl4$ zS;EO_OAcAw`oFGaSocWXK(I{4lV_i1L<%#$eD_+{yUVn=r+D2COXm39rQO*C7_ld1 zofrAWzuFQ4FP8zfq;_>>Q-Wvn8B0-`Maa<-$F)m>~u6o>VaBiNQTeRH!J<^oJiJ82dQGJFTeE7puKSgZ{`V7#P3dRj`?Ru~IrLlwUYh zKAU`H?YgE*r=1z&45l&=2uN*~=p_@!e~G^k!%9jh!Z{67s!`yI*0gG0epWH5`i&+E zU!e2%Q&gBG8>92Kc?cAs&?$5h>C!Ie!+z87;Y78reNd zGREjC)PU-6wd^O)MiC-cn!B}Eoxg|4lfZKEbWVM(bd|k9HO$5LOIGyEtHPlv08KXy z1*9RRM$Ex zLK8)Qzw_wqrBrP>f(lHmNdB3rD^$J%;*}=6V=QCmkBn4OXAeS+DG-2ATeKDZNs-0l zVt>x?s3o^mq#-)5jxMDAP>5}$6CI`jY&J-a<}iy{o=agS-c`x$?v=)R_qlwb!-Wl9 zc|1wBbNM+nhc-r4&YNB4UFawerIu$u(U$yj)ENjri)0 zvhWSHqK?g-EO9oL$%0J0WXO3cdb z{2n8f$MOV&9zI18e-qDJmg&>vOO{?f+GPiPx1_D1 zd@C{)?^Ha_sb8R?aQ@hw!@ZU*ej|*>I376!h&d?$&4n8b1|1C6?cQ+zo_S}ic=(BF z0evJ&ZPYni0rd-Yjn|;-`;3<6fdZ+w0Cm>C-SXgc5}{;-8}ho zsKOk5b&u+8Y!LMOt20>9~k#s&w4J- zpy&!az7>y^^K_I!QA)@b_=<5%$iZVux3bFcOmtv7Fw}sy&{X>N&~rJC!Gofo#mU!1 zQOYr3?{cBtji*gnGQ*D_=1@R+eRH}|I~^30qL5l?GT2QJ&Anw#Yu4TGk)|y=3ll$$U0AwBZD6VVCSh%B|N$E92{jO*-_duwh z@xrqGp!P)TE2pB5D$W>GK)WkDM%KRXAN8y4bm<<1RW`Cb*Q8+BUt>tUuL<5w`p#u< zGx%=$#PFAsVVwI2iOYsBe-g9GE^%|L1D{#SmQ6Shg^X7yq5XVXt`Be6cn7kZuRzs# zg{#Qz5%($}-)W&jY%@|y4R8a=i7?bol zNt;-eYWxgkoJ#+f62zoWS9g7sM_2t`uAXGy4-7^JuzQ=MHk+hfs1uY)Ds6o<*kww1 zsqa7F_?jY6>{!c_?YGYo7QX%8EP%~N0^rVZS^V@0VbS^cb@}fu+#K_o>BfgWZ0`Hl z+S?ro*VWyuwZ@74ll|sXALq3<5^Y63b~tZR>f(W@-5s=FcUcUKD;Z zyL>LKSzK{lR2klOr&fw}*PxbBZ*#)wRag%025{caiTbT+cTAifBYGq9yg@{e#{&6J zD|>dHKDLTEVMb2e`eA%ooQf?bKlmWp_bqYg*))c-nP!?bi-k@~c%GkY(GH&4f?VlM zOu3QB^(V~i4gbDh>=&TEQG99YfG9j%PF*auQJ{bd6r||7}OZ!BtCPS+tr%)-@G4InGAyk}qq>sGc?m1a9;^!vS zklg~w>m1IY-C*x@=VY_N$G0K-OjF_uA(i5P!S2V(cO+5JGcNiI3l;SH*1?NMYPj&m z3_3ks^xa-i*pTL>)rp)y+NYL%#~tzRM3y4B9U*>3sOXdlsWq6UDL^jkK3nwBfM+_XEZI0sM!1+MCBWGvI?d$)C ziuND#Hw1>K&xsTC1UY+?s}nJd_Dg;ZHBwUHfA;?L@Jut zyyjoq(liHlw+o+Dz8(d1b;zmEm|so}u10)>H`K`#ioq1~r`Tn%`WXA>kAE(RGX|cb zJ+57t-|RNb(KjbW-s8w03x(cux!H%m<-7fTZ@MYVXL1Y-v54#(vVn|*OW&F{jI7|l z=gYS*2=Jbwft-CYF+ce7D#r$jk9Y?yj(?xkPUWhMs&1}#(~M?JMu=v<{+{qhBJmVe zhUXjDij2Bje0`=kKY-SzQ&9A%8iTM`%F&gXn@L_TR9{8Oy?xW0S@V6(R4c<`J+7{< z^63e??K_QnTQ#VAL?D&OZ+ck4Q!`-agC_*}74(!0>& z`GS&8l&EvKk*Dc`pTz_i{lU?$PpYvp2_`B4`?2k}cYX3anZI)2Ae|3sj+vHoi4P4z zM@xSIIay(M)n1vvNDVyGbg5=Q*|lNKL)1VB$eKv+w@Lh9LB_cZ>BHB+Rbs&VeaEhu ziI%Cxig!^F)QEh%W}2$#0~`TLBl2XUP?rM>Ec07lQ#V!7mos7g>fH*)c2!ioK)dQ} zY8f;stzKbCN2%+pi;jp#&`Gm9=;j=NVjw* z9{<*F=I4;Ow#JdwXt{7wHvZ=ROnsr8%=(wrvP*Y1|ECx6l`w}}89|0udYyO0V-pwU zkhi|h0^tJfx`jC7qoFds&Ws;U3skPY*mTeDFV?u|lZaX}?oHxak05HDLZ5~G<#BTQ znZ_s0gI{aLYu8E=h=gpf#P9Yf5BB|d#BwBQ`U*ah&?SRcg=!de?e8%a_P(3DW`2zQ z@kIG&;B!D!IDRoBDEjtv=J;cir#)N8_*Ucd;SX%ns|CbJyJt3oWM#F$rUM&$SPAj; zg6wx4^=TvRhx!h-lmhS5GVQbpc5+BBo3{N|?wfG7(Dn$@r`)*sIgLv1`8OiF2NccqBqx zliS@LK3)_SnE)jWOg8SX1q9KnoXrLnUK;&Zy-?e>LE7Bct$lWH!uxZR*0pev3s24o zW`4P*27*YsEOb^Lr75Y787t2x{D?wqC=h9Hd#WcVam(5{d@XW})9-Yhb@kqv0Fs0! zy2Tg@K!M708A#vYn~MP!=ll9k1pUQFv+o;esfY;`6vd%b+Xl6|${ZGhwFH==qrSWd zyIV#@<49+5;$;1Snq@Z9+0^V7iMCHS{JW;R&psD{9y=+&`r2>RiIT6Ygg$29o=ye| zKHa75y7&iv))Xk%`Wx}i90Z*=AJsG)s6el8Iy}KRTKClJKf{IrQ zw2KV)s9SQp3%ix>5q!~)hjzXLY;yCTY&bHfWoTpT_Wj-)jd`C3g=y^7 zHF7H6S@0=LB^!_%1NVvN_k7_`Gc;{)DPY>CwWaPzQL#%u_G%IL^jCJ3G4^z|0y^Vi z5^m^r@InUKujUebLqo0_Ma@0a=3`3{j?xjWKI9c%c`X=Un zJr{lzfYuy3&0L_4i!#2RbZZR8RamZfW6>iyOfXl88FDMuoiZbJSn>PiZt0v#MVd;* z_P}R-$h3;Uu&+C5YA`l4ggl-l7?@XWdj%ku%Hjb-OT6f34IXA2YV5sQ$nyyY zp>eBL#KUi-7+Z85XCH>Qd0aBT1Jcz{yw0*QsxJorR_5bjnla$wdU(`z>u;Loj{y3z zv8g`}R8Cv$5`1 zr(yGl+pBQ z8BS#)buU6=L=8O*L7f*FQA5B(Bs|HQCS0i_tkfyCOnpa%2Y1`Pk}bFVH@WCBIjWd) zzEDmt3b0mARW5_FZaAF7N!gVQkcF|n+d0aa$I{8RB{DLJTXe zqfghS{WyUlE|kuwi31r|q1zwB4Fh}W12c-YdlxNqL-H7LMmCb-ib~)ts?0UXo|Ikn z@~fzN`UJ=MNk+K`LUM+jkBNj8B%Z6DNg)0!29^hDcs@pc%OY0Yhw zReD{XdZ}dxHp5*4f@C@_1tY(JF_fv=v3lX!X>`zUsI5y(ctvq~lsIB~#%g+!-tH7} z2^TuczdgO15)9K+=Pf+L&K;a;?09?lXs0fPPXkogSawFHAO&byn0NK=L}R1+JDiaO;u9 zGVS;;6{<1T+ae^!l#bWu(|=fwRXu78mTwq66-IrBUeX74DR?~*>}Z(_;{LYJt<$Rs zyA8^WgPA0C{j}Plbt32yaBeuPUUnP|HfK#t;Q}@mJGO7Pe;ziuS#VJT8~~%{JD^XW(sOir`|SnZJCZRx6}W@W&lq zL&Tb#Lik`Q{uKxXEUA2uUUWWq$n>S`OWj%KOkBYE>5JUcrIUDQgj8qu>p5Y7R6)`z z0X?CNCA~e${H1;yLMAy$j6P-zsQFYmcc^&Xls-B-;uqa*`oqTr)fKw;p+`eAe6CmvNt-{E z6oqgc=n95raO?JkscxDJYD&np5u=h8Fkd6yySA6nPOt8Sfl)s6{g!S+mmFoGHi9cN z`y!1dHp_2Bma@N{gM9CZ64j50iU<%)JfFFONvrK8n47{Y!6OzTKfzFQicP22oyzl#LkjAQ?T0jo0pw1*E%{Xo z=2d#UQ+*xDsj|b8;ae5J9>eH-gnM}se@3Ub4%+c?gT={cy!c(;`+|0lF(;>|UF%1# z+y3P~VN>k#j`ojYKhZKuT@aH2V(S9=@geHH?=Ay2KRai*_agnZwO2CBycEAvx{4oE zV~nSV3*J|jqE!lBg&9f>yjaC{`HE{x1lTj<(qAdl{1g95Bzg|xYPtoImf2b1UzH6i zbWU+T>N1d7zWv$7j5WCZXH`5fB1cx#_G^JTScWXp6~YviT>#jW z%x>yqHT`;gu}4Zc`Pt$V@hrsOa_DBIhHr)+S?4hdI@t^>K{8u+?a1IuWW+^n*8s`M76=8ew{m!^@R{pAz7Qkm%_9 zTbc37wu;h`F@4>jvd`(`uH!=&nbZhFE~e%k81n+F7v~(0qa5JMym!x{hRRw865owT zc405w)udP0ntF1+v)c@CF?44F8pCfS!zN?a45t1PlPO{!f`NAM@rNPOze{U5 zcQqcN{v#Evrvu!sX*v2Yx&TfE6&;r|9sd`*9K*T|+1QS#PJ#Ly^0yv9FG1j6%OdSV z-^?r69o8t~9(r$U?qpwPh7->(Rn%3oWVI^OuKQ~lUrx^vO$EZX}rT&rhFG`e;#>f zFgQ8MT&Mv^A%^U^FsP8nO`Wj}pc+`d^%CRSjT)Ovg!DZrUcI94jD=hGaH?QNz%@B|Y6>!3o^O-VRW8$Ykr-cBNzGhA-tg7F zTu-~;KZPvLt=KSsUAgC{3%J2xPY1a zYWw>Z&i^P`Eps8vTIg+-dvJ3VCu`0YA^eg2Ao9MVPv86}S7qaxqWM18e|-D@x5xjJ z$tueK2c*5?$X|O-7|&jVS2{b`cCUN+r>W&txPvhuQy~h)`kyD=(sExg@VK%p@KTKI9>iz>T0&|?~d#~|Rni~t{Nht5%?Rsl)P(@!OT$fB)+{4cIbnD!I3IeCu1H1>})N znvl;MuavP>w}C(1>68p%HQa+*mRYGr zW5gNZ(y&PbQ}kbH&;JwpaA)?<0odpKdNIZ<+jfu5<8@6R#{1Dp4BFTYt(h7LKK&xI zl~F)r%%}mtf=VKQ58_i3KOf94OmO>0_#Hc6{>>=<@qx=2W=;COITDI3jP7{D&LQ7p zvoP@y6Mj5tteQf2_&zevsN;;MGg*2r-cN%z{y?xsOIL6QujOsz{l1mA)57m*>c8@sV1&5o9jt0w{pUyi%?f_Ry`ACS(N%syIpRlj z_PaLLEF~rJj6rj*#Qv)-bjI9ZDm+mbUCYbjK;h)5TAPJ?-0nN; z#O9yCv9@dKFQVsfX|O6AOu`h@dkt!#{X2$$`#-e zX$$vU%k1mUEJ5aPP4VPo*}6=7T^`QtPQBjGB)vG?$RG;gN|f7uNy$(z|@&DB9o060T;;u+s3Pu3yZpcgy*l-@zXf zS)AZ-uuO#S%6^|mV(K}11rfl==6cW9#B8D?x2d1`$Z-QP108(fa-MUW%Tt2UVUY{< zzwr;59PjLo25S=)oY}+RNjJCWtvT_>XMRH>Ufg5umNZ2dTFc*#p*wD}Y2-5~(I)qB z#a>Q3(Q|VD;K_SWFf|e|0vz*8yB>^zow@%i$^7qjbU|B9)^||YaE~8SW0l`dD3Uax z=GM}qt<>*qCca&siYDTx){EyQ<>c5}glyt3FQ3d%Aw0z2pJf*8Gl`Zb zzpV)G$4qWZMUWE@;XM|iUWuGd3-`n=0lREDs7SLQ7T*vB2jb)7Q$55zPHX~O(;X-+j7-ADEkSm^)Ys)tEBrF~Un{SMv{NDaY=N>RB1aqxoG}z)denrzD{` ze7=j{^Tk{g34S_bu#i&$UAa87iE&xpOAZh7sn8P)!pN`Y30Sz5orpj7w{bF5Hw;fn zzo?V6JRY3&ZnlHMBsG27;i1l`Qx@1p-haLPNG6Y+cW8c7 zsJ*EKd9mKI=$7P=|K9`|-&L5t<*qFvpk${YVvH7u4eUq47&mbojoF7{;ou2rU9IOr zbBf-$?pVC3g^BT_`>-v3y~BTdb;WNoe?lPQtj$C2Q$tv=8$^_oBbVq=Pc-^&CkSh^ zIjl!IJV1W{~PgMu7cVS*&k zeLWYc0C8yNV%%;HNmsk@kF(jCU;!`se$E7B90L^@0iDD0`1cLB4eMU9w_DE+&NSep zobipx>NjEIQP$zXrdw!R4mM zRrckP!+A~TGagoJUy-0jjJ_rY76v)Xn0F^!N+*WF=r+;T&e50tUj@QH)P)m-?R+VS z=Mhel4ih;TJfrfC@O`{D;%z~_+Dq^Mdv%bmJD8tfHo2*azTVyX{jA){vFq*=suOvn z8Z8&_lci8n6pd8i{#A(=2u;C)1}}WW3v%LpZ%Ase_P>cc{~M|V^Bev%!@`ks@~^!B zDl+fhZV~kzm;z>aX$-mMUAr)8`chfv9T&hIqe(HTWJVtfY5{TWhMejk7bGcMO`@64 zo1nXWxr2JyzeS;6FXKIr3?Gv_8%dKrANF}0f=fp#N&<%LS{X&Lf1QSyvOqpyWEIL| z?<}Om`m%BHZgwGU-aY0RbxD8ACW-Yb{4)AFwF4=tKs;L3i%Z(wlt)A@TDvCNqb~Zg zHWOy3PXcwrb50F=od^&N^27+i`luGO?xh_A55_>6lp{p5!?Jo^*>JCJ#vs2D1UUm= z?=ICd$(4Te7FhRdTtzd&q<#Az?Dfe`mbBtjW91}7ZA+F+ZiZ{xZm46Ab9&aEE%4;R zaIXsAE|Vj9KR!8gT7;=E@8!O6T@yXFDXBN#x+8^Uq|{mvShHg^JE5gVE~ex51sguc zEVQ;`gH`%CRsH8`;z9~~Y4F7Sc_KZHEC9+xxeBa!rTPE~xO{~Y zO>APx-YerUdwu91mm9>l`SM$iqum0r#cr_e+kOVZ!FONKnS}T|iu12j0Y0fihQv!e z>yVwd^p2L?vu|+ohV_2G!-x=1e3U`LpZU_Dl%i8c^PvBqoaldS=g#*3%tiRqgxUDS zoSN!rXxpq|R2PCl57&O$fg$1=ARO}`H2cU}V0_^bZXK4EW1FJMn41Pqqrh$pxI)fN z5aS^!7(hZluJJcB?^L7gE2Z}G_-zXJkwJ>BY^zA5uOH3JCCCVIM!kjWjHj4ufO`rL z4$4Y<49-yyd@k!`CPyKh!|Q1OL*Fbxnhn&fE=&#TXJQXfJ-~bthn|9#3~eHJW1a~?-ml(j=a_4wiWC%ehg7h_TvgcGlQhvL z+SNn+SQ>Pw-33*PS>8Q{z0TcBFvq#d{1pCqp`mgfKqIJFh{C6!!A$36pW!>ViQ66d z?A7K?;aZLgl$7{Cu)a~~pOfKQ_=--~I6{!B&AtAvzp-(>b!|_AM2ebVkB&=Jh6Atz zWt@z^nT{#|N3iSbAkNiUrq)F#m}et#wXhWTlB@2zjiPjOEtG^&zda7vG^gxu;+orU zNhl6dAB>`;d_mI42{FROQ`%5&85#t72QJu7x*1@LmBkh{B6DA8+HR0R8Kd5$n5Sq9 z_hB=P)YSAa&nH{H#HJ`VYE|s8fbk`|AywGe+_V%5VjK#x79AHD&HWk^gN~(f2ww4T3Oz_)T`VXb_#5$|G(zg-cBUHTN#x<4A zrZqGED(e`fzTaGewPER&w?E%7K2|)H`SBkAmsk5A@bC|zG9Y1SKVU|nwS>g3IKUFe zF{*TsZvq5j*E$3v;2HA6d!ys(s(MJ>YxT%2YzOou0UKnvlXQWlCoC{RL;L%Z~E8VR!CR&DZkd8&*A7G`b zC8GurbB$fpXo7;(Sri2sMCs97gx*b?&oYKhm@ki^NGEc;U0rwXx;@ep_CUD5DKk7m zUoHF{{x3d-%{S1Rl9aq?Y-98lrDa62u9dKUOpkWB|a0mW{WT-NeBCxYgunnZyFa&KauQreNCu$ z@r@{7aNby8@;{Gp8Xb5mzS^wgznnN`fo|f7%ve}ZJY+gN$}R^>Pa|0$)qsFUL4uU* z`d-XjA`zoHR++U&)BF3qpq0scJPbA}-ty2D<=MdMpD?6Ni)Cd+>0z8{sn2-3h_42^ z@^#NZEips<(@j&E*pFFCv@U~S7mdg^#-t>maX-}cWYX<9$2Eqi=_0^>vepR2-(W9A z+2&aWTWd28gN&Bje=YXoScb>u?=8`a)$b^URe{I8r%By(S_z40NKO?_ERdB1;d}57 z#?;(SPrSZ8{{Hm`$-teweQnW%5H~0Vt@#76S~a$IH2nAyz|O=ic`glrtyRrQq(}jD z6NQE@|Hhz@4e1Nck6OA2#@9B>g$^kdOB}DK(P&s+1fpW4qtT!n6E7sw(G>_zHa75| z>>rj7_%RJE?H5MC%3v|J)Ts2W9%oO=?*Oi8)kXcya~0%l98&pfFe4b7sD!3r0(6dQqGSbImRD$E z&D`0;>0l6}KG54@q{8Ukyq74HpbIOnWwj7rwK{Rz%4xIr{8(%ty|*t&DR1_5F}mcl zyh{uoOgMxjmd1X(+pTwiyk{H=|E*w9z}3K7SIMjU0uq=@J2!H_frcB~NbXbcvryr0 z*Z&(VjPP zBSJ-%+$dPM_~eLUG?Irl1R{!vk6`U#uQ4$qM2oq!$7F%UAfU3764U&A<*2?Udmw&9 z3@4n^)qaAq-`YUnb9X}~%95ORXX)h5VBcR=D(8IX_X!_VdfxDhCt4k>j;zy*F5iCp zoqHpR7M8U(u~<_cKcfH(&EM^flE8G(I4r-QfeDXyw7HQsq(@Uo2+(m(xvk9njGBpd z!mNVB6yxh!oW6eJ-iGM&l@$a_du`w%C_Wf9C33F0Hlurj@~&Zhum$h@@<|kt;TpRM zqB~@D*Q`LRp`6K-R*C!SgUnzY*WY2PF)DBjXspNwF7B-?*90-z`u(E&x1aN&djXbM z?q>&`dQ=mLWF)S2Om^UG6}|WSdmE~W&`^DR+GuuaZ%@_=@}a9c0inoKg-ZD8!n~FS zRC@&n32n%m^L#HN!4#tmtqa8Rx?klmW~!2$*IXM)uXcDjIWqZa6g|!U;f<`En{8;c zPIl>092~B+8}+l@L7teA91)&^>Ao16ti8mpI2l5uyUavU6KT>iRie#gWF2mlv6 zgF*CQ27ptNqOTi#O+$qII7e%%Ul+zMd?fj7CU&jrb#x+IRS0X?_61?W*A(e?Wj;nb zd|)A6;#=`z%$!BqW<4HgV}^bcoo=L)iQonx3^I;)mIN^7mqkhe(`@vlz#IDcM&!0X z=%Zlq-GojQT<*^(b%%Eilncv#0k$ocsNtTYN?{jUhOv1c2s`z4kET{m_s~*Y*|SZ3 zsREre6rH%|P5lz!u)ZQM8igg=ycKPa9Y~lU-?%JDFlHiLD&tc=PY3AtW}N}oLlU4G zSt)1Liyk8@l#nd|kG@f(1E76hOsE%syQKxIieKa+Q{LIR$5iViFxr5PIHsyFR1 zb%3U3RHNC1irCso=Dsw2=qc}ep+1vQ=R9w>Iqj|uZZSSBf#z>%zSU(Pu8YK7$P8UP z_sYOOC4{E)_b_0M;1l>hkK^;e(a5phww(oYM0$TL-zr#&;G`;T?ctsL7hWz@{7@$O{130Lh+GiVN z*L&)=`%!UqzeuNAFs!~7i38U@Ecz3wWjP}LRPo-IgmS!S)40k9GX;qpYuCkENs~Zc z>0cU){~Vg;WY)u@2{&<-IHG7usZ5KKBpa@mtDNL%7Afy&y@>-dcw6%~=0L(_)*dh^LI!K+~ z_8>%yq`Tu|Bk8%9AR4OhEQ=I?*!?-U+2cV=_al^5Bq2eAMkKYjASQ->bc_aMED$E? z-6Zof$>x*jbgf0>xTZgEY{*$7h9Qt*aJrI<;2!a1!zA-XP4xnAbto) zO(4g~;8MaWoNH2sn(_%Z%>u8fyXH$yatDIp+pA(^*RPOZ9uyW#My(2w;3GZF9(4wt zwz{L;Y|?e;U#BFa6KIFBM&pudcE0)cY~7BCayDano`zQw;XNDxrBG_$!xX$&5H_P* zB!mGcg;?x+Dfa928eaC2=t%nVVF5gi9crh0bOI9&<93^0S{P<5%}hl(!^7{2SURDfH%NIoliHV# z6EPd|_h!wO3bX~5w9M9GX%R$N&|;PlAPeroHb;>^VE204J84O;#Wu<)%is5=`dhRG zISGy=A|OZxHRfAHob0IStqop+T(rS|Ud#kDj2L+S(TyTIyth%dDGi%p6a zk1nrlzTZ-+0_x9D21xSvP8=g4r!E zz1oc0;khPwlwFP#f4=IuTALrKb82pn(T-!8^kjp*n%akbPC!ybk$G>w;w?)ZTK<@Y zx;b7(7sDCGyKUpK)v!hSg&7F&5!c_>+Zi4~!|}g`xEFtuxE4d*o*6OGRSE_%zd-B` z;Ab(Bqg(t$AZf{z4#Ix|9(DSX&;wajtZnAxzCCD51Tr$KgDH$}!suu|2nIaDzivbr zH`)SJhpQlaqLd`dc%jARg51fBZk zA~=Kf*Z8LV-ae&39Gz=Y8cE07^!qS{F(AC7-U|=Or`Eh#$y?Pk!Hk}AfygFAOgF;4 zAeoFN(%ka98t2E)r05Q(Ql0%f^m;Gw8^7%}J=X;GIi?FTC0mJz!5)#0p48jOUJJ75a#LdK=wWfeYr*I-f`x{E9P=zDm!OGg0Zk zCvpo*#brEVH$g(0kb6zZ%JT17s%V%CK?$ip_dbT7=wlln=FMo$o?+RSyOT-ySIUzv zXgMh`ny_I@zs=Z(p?epU@0bS@@M!4RU3FuCd_p>q`)h|FJ9i@MGMC%#Gru|6(uyPv zg4cRE%6*Szi*lx3Cu4Q|M%W!>WUbt2J&nZJUi5;$2i|K|KrIAHG0*FxdxR<>XnxJ{(f8~cibiS1q`E~Rwt%bT_A^84W7t`HaK=H?1^G3Oo7PXLLt-1eV z+Lkl_`dy3iIq!x$Z!DSdrBp@NV&{Qtr{+;`^>*;gi)0i4=TdSzTJhM&3VqGHgg71q z@7Ts2x7JE3!Q^&QpkV&3zI91E;``i@*r$m&fWPqB^)scdap^q6zsf)bEr)?e(6%*& zt9kiq@d@CwD)rIuhTa#UV$#OHLIT~S@@op)l5D~~^PM7H5ZWWbxDf(9d)Sa6L&t)W zszfwIizvK`$ zMH0Hu<3jkfFSIFg;h@WN>aC`B<8>;jwezRYn)C!}|HRz)I!Rl&D8M7gEYSAyaQ^$I zOGw!rl~v8t(58Tqz)U|UwmP_gLb$dzlp3FDt8-qmtGz4diAuL>KGG+=;ir_;%y+|# z+>9<&%vyR&PsGof^n>62up9nNaIfcGp3XpiTXKWF`0mPY(9seAyCP-znve?C+s-gW zGm>Tx3{n+wxL?fEbfo+g;y#g(i^MZXM@0czeK9BCE(X~=#Q0LB`D~+*M&k5JM__3O zFuU?ZV%Bz?y3Sm>3>e5VzVC8g>C5sqPKOWgtz3Ttowwteljuz0IIUk+QB(fp8S}Rr zbRni#iEQ86)G>b{IlVgGppVVX2#edG9x@}z=w_fmrp3%!+xT8Mz7_a!3wME*sMw@a zwDMQR#z&@Nip$1@i6ghpt?%Sn8+v9G6rnS+uUv?TL?v=+tb|xeBI8YCg5Ms8+vKR< zmQbwVC-pW5ft>7G#!v_)ahq1Tq63_VH$I#NVey`d_M#+NR6H;xg_ABaO-VII;zf6) ztwA}DbCk-{=t>y0vp|oNVI4WY{6}^D|9MTVAn;f+icEcJj zoa|ab$xz3|GQ}X`s|&2nz}~cGi#@pLTyu{G5Ptt=vZg5PJcZpK;$^q=GZsa#9-BK_ zD?MgoaDyz~rJZi?D_2eT&nl3N1Y~JXkTl6br$_@_4=pZeQx9^=tUk!!`c38`u=B7F z3eBycp)ZP~6c@Cv1+5*8=X2*~EZ>30tn(=4yKd{s9F#PLA5N<_s5;0d!;DJn@?mmX zC8p)}yXjpT-?tx4Nh4;U-D?T~dlE|MK*+x0Ws}Mnc`3%H)wTwdW$xL+^0_Eafw+ws zQD9i~{!w+YcVa)>6CNuT`i*2JybLuZ`*pQ#XZVdX>5Em>mLSzcp9mtY60FnqJq6@w zahH6#5l_uiJM%IAb(gG)&GIeZk7l}T&ik69D#eAvqog5~l{}*)^UEJEq~jYa>T~x( zLz(i}F|DrvyT$3)77yX{G#A`1Z`8=Jo+4Rff|tseGXznY9w_IpA&-C>7W#+$#k zo(;cquns+0-h~Zj3pAFEC7deARPbPmJf~V|drqSaA-^KcB<^2F@ZeP|D9!5T^ zvzN@M`LdRK-ryuI|LHF|yqwk!m^1DVtP_VcwPxd<0!-XxeNg$eg%E4^kKV`oZX2b- zv0Lk<7%C<;XI&%$K875=dJXUh%z%rn(!KNLc^WXNSZhOESs#+gfWR%z;CZ}(Ytw_| zOv0xyCW=o|h=@BGEqqmJ{K%=;Ov9KP*@u--WgY zq;gl1Ej9Y=O|@rVl~_|kn-xXQ$)27wGcnolwo%~ph$$0cp>w z2)(o%c!IFZm5;+`X7K_&Z!xncbk9T$Bi1}c7wk0_-*2@U6~Qo8^wJ>H9lL&iP(I4P z6Q#3s){KM@;wK(hGzR>7{&I9|EfS!Fa+sn1V`LJ;n9KmH_1MJ4St-lIb#v-znRRkU z(uyV+tB1{up3d&)kHC0EygQbomW41=*4Cb*zVX!)Z1$zeWu1^tAU5q{^?pUZG>~$x z+Em-H|2b3@wUHWkkTV(&mDc^_q|-Fv)@Wi*>c`xNeO`>Nd)H(@I2Iu{cYaGLYJ%|3 zi6^`se(3@!)(nD#O;7zO+uFjf4X7`AjH~ZhIkI|P$!tThE}jQ_Ikb@XzJ%f{!+-8c zL31-&Zq_L(K*%PFq7=F48+uq8YW_NIoE+9nut@JPl=m2d-f)0g4@buK$5bwGLOEFfdYZ?Td7OyQq(&|nC`&g)`|FyI z$Iq99rCliGB8@gr}jVwy^zCtQjzOL0*%!KDQ<0254z*!#Oqj? zL|k8!xsQIvl0n4J8h1dB7kv%#dd|2p+YX~l?j0)R z@JzX)Nf++vLP?`bRv6vhH#RO^r;cGRD6EFy=VJR1<|{;#yVlB|K!7Obt`U520>+iO z35_cCCSia7_zokCDIxLh=ciufLa0L8LYZAN&;`z4C$i2@V&Gf_|Bj;JywC{^vPn=r zh47PXb~qJ^x=zpKwce#ZlcV!%=Mxssxpxi;;pi6;7D%{CC4@|Tf*4bG^03z+*yH8> z;=90Y3oVgg1ZGBsZsFi9(dTQtLeD!ZX!>Y6@#{v=ocH9^T+D41pWW(;%mu~p3L&<_ zeTN*Q#T6J*jC4N~qo!ph1WzV`(HWJa2zbo4y}N}aD!mi)W$xfQLs=T42Fz{knZmoQ zD2BUy``(nnE#7TyQ)4Sl`N+?776~=bEwh|`?T|MQixn`ghMlejCZN!yn5l*l2;+6r zebo5IKUMn$4Q(fl$432ox8`XKQx^Xb=&nktMu#b$D5HPv*D<7&k4kF6kL4Q6axRgAP_ zEifLYrQuyc+s}Bc2uRO^`7O__H+|TrhC~81yBz0rfMJi0xv^}D)%(5?HTVQs#Se7- zWx(Qct%~KTvF+OHTUl^H3k8{$M!>iCCV!^)FuiVMCBs&`@HxuY9} zP!QqEgWM&drr4T4zoeWOVb)PNfRJsmZD;2k`Ma;!p3kK%A5_!<;V0)lnmJXEVt&ZuURy-j)+_9?~{CK-eKznAt~h!IdB96*ZWEj_LFGv;N0ae&|D zneo5*5lkm`clD5ayH0j~Y((>>$QG=RbgHs^@+NI=KAKe4gjyzAg*St+t??($Hu7hV zSLTcf@<)8DV8Dt419&_}PvxE_4)i-Dgf4~^DO5Gc zD0Nf15#tQ!+z;vdv!=rb8gn+Kk>pWIS^ESt%g5arQABks2{W=ojA!icwahwH75e&K zyy-5@%K9s^k9y-dd$OG$Adi6pEiOuoC8m-<)xfA?XY7Vc8FmTT%kK-v@`CCWZXY!# zuJAf?^~xk$9ufbZxD&~JJdD59$K6uB=wr$;P zzR3|9!b>5cmsnS(=>PN?MFm587Z>vy+o)hzZmZUcE~;_+v1T^?8CwBcu!0C@Cx*v> zB3okOXB@_xHzd5W5~AvXKPmca(nPKG_Ar6$fT3x8Jhr|t9R{S$picN?YWu|jYTIO_ zlVj{W8Fs9}b?^x~8js}Lw+pvC5~vVx;@~_PdCl?kioAYb!jNAQ8*ofHDv43N;H)2a zx69 zJUN?ZC1z3Kg2_keCOJKNr92cz{=f#TN{k^M!@gYTcn)XToFxy@bOU zYG;}N7~h8tt`G4{rI9yaY0 zIQkBkk=xfNScFB8eea6u$aXeBND8wbB$lx|ty*P``fphNKlKwsz$ZhGe!upEmZICh zF%J(w0!oKqf@a3T)ed(FXwxpcU$_rWr}%{saPIi(ir0M0H4SfAMFxs8F>0arRVS!1 zk!i7lZb@fV_m+X2=ERbU7E);fh9blDkfz1cTW|}KTGhr(9ieG8(mEKBiYw;aYLKMh^G6fOoAm#1e zWlc&(M3h1tz?eC2rAL$d2`s&0;9WZ;@DS{2&8i+sE_Bw;6-?SD5TTW+7PVPhbYb$D zyjv2nMq`boX|!4Alt}lX?-BIin3RXw#vOE38nPhfWD3$3oSQ+iKw|ugeC=I(7G$vH zhLs05%pXBHn6}sEOC?zFr|?b!d%DL5yNW2=CM{kFeuO zkNeOw$&)jipEIuG@d;y8LLOVdY)2zS4{HVsBfM#Qa&5EkR^Ps?+Krrtptnm2ul6X( zjcH;j_|q$eFLD4uMx=>K@@MDV4`e*>9!$EsO7)$pBsl{WSi3|lEY2@ol0*C|61s&* zC&*#7ixkOny_Z79`!f7J{=UdpwbXCXDcGqFBry>!<9N0#yJyBpG?;7EuvxodT)ck# z$ZP39eRmz0zpL)BJ=%*Ovw_^BhiGLX^novJ-kb`pM^vJnRVP}zp&qz9xZYN~{FyOX z%eIEO4l|;zu3{1IlOT{M2IxL@RV48BLsdOTgp3t={9T6hwzvk+sdnq}E%CkO+FBs3 z7OZBsIjj~}!>$BE>?HZvrQQzPwd5Z`S@210$Xg9pZk+>jox|4@W+v343WcV z4SfZyu{+YxKv=9TMp*vNX)4$T(<{GSuxeS$^Rs{2nsymaBIj)t4FF6HhZDwU`{_ zBFxeB#QHZ(N=F>V92RKd7){P-1kJ76bkJVBQj}QLbC>>uFAd$=Y2M?5m1U0QqKe#2A}a21QqT>9IGRGIHImx zcD)Q3Bx8&%S{x5HcnFP>pXrDN{z&5%!bb$s`hp%#AZ zNqUlphFnu*6w-#KU$Hl^9X-ekkUL`|IXi@#v)V~Ygy9gP9Ak?sm*Ay)P#Pw1rOAKF zHEo(1!r!&PYU~`Qivq$m1BfHxzT%TcP5FpnV~;!)71yJ_To-`Uc!pHc4@@7l_`c@# z9?}T<-7NUvwW-n#f1pE_pv#M$pl&*a7kc1~{e+EqD=-;y7E60ECoNjEk8<_HC8RM1 zN6DsrOSB1C5w^Wdm*0IXCYV#*#U{A=O`TtgCYfur5g zhLdn&Yw?O{WWx~gATmxRTA!r9^S#9Aae^ePCur-f zl~)8%iYRvLQ^UaI)NZ%t9ayl_l549y0xsP#BnRUdD_bc)YSw@`JTlUt z^Q8|D%QNcAym4ZW)Oz62{?q+T7jF2MqOM4iaGWM>#d-VThn!bd6D^IWMwy!|4sfos zVsfUWme@~M_k3VfJlWJL&NGUt8v#s}BJN{+Dx`6hnXcloU0E1Iq&M^{BTVY!6iY&u zLzcG&3sXB)5a%DTqLO5qo~DIf9IF^_)m4{}{0H~_KS{(uaGG+mx(kJzjGSaD4B!7U z#RVPe<){9bl^MG{OIQ?8KpZVpJ9fIIYk4Wq4Ou*$D2k&4>V@U=H)y_h>%B?z&<9d% ztjYtgsDML+Y;&2REJvly6iQLx`&O3E8gIozEhs(rX6Rt&-{r*=NJYUuvZkn$2y%wt z8RYic$qc8dEA%%|d>>T=V@yDSkkOvF*lhiEMae+*>)@R+MWt8_z*+8fGwZTVPX-o* zhVl@_#1;~VO6#u+rfDR%bkeK=pjNBIen=;;c?EPBqO44_49$Zx&tMzi1)fgi_n5pTD)P8 zk!3=dqU^p5fxqs44H-MP!ufE`s?mYS6!Q0eY^d~RwHe{>tWy_Z50lIANi_5ONbLhHLTj+;k`lRVntQs zH0e0J$X9L>37;HQj2`9UglTHRWw?1q7RjxJVlGa~Sgd^Sq;ichMad&wYZVP#%k7@p zA_v0u35RW|uZe4a`x}Jy2AodKHw+<^63M3TpMX900HQvi#?6*^N3hv!)e>1)9&B`i zFlnzC8q-JFl{~^dr{#d!+JWl)8Kn{ZYaIZIw<(ca-0T6cso?~-p9;C9qWvlki8xb7 zV4JRSa$_hs6xuJRd3&RouU$Pm>1$YXd$F&~WK>6Y#>RcgteYu)pSyVCiF4S)+w`c9 zqNy`7Okv!5=%d6U_AaH4~8<*kF`wwUmz44UffXXMe3|L_8zU zF}o9Ezhuq^;usU_b-J#?)RCbTS|4 z_FZqex2o)K%G^>x**R1j@Gz9@hQX<}6YQauNe_|**CI~Jd5JXn)D(I6Xc+zm%y#K9 z+k6H&H1q23<}Zg1g(PVdQx$qCwsGZ^-^i!ewK*blQS5e56*$n!4zK@)>@cLlvfgP-M-vb-FxvFl zNyD$DBB0nX%~$|0<1$Y>C$(~n>QX&heJ>fUzQ7@&z(Oa(+crTr8tB0x)+CKxO4*1M z9&ZpJVnT}G@GEdp3-)AbS8wisPuM@lMSl;o{%;-t9e5W|b=O~WU4GN}BOQGmdB{gojPO zPe)MPB7Cv3{w%5x7xNPXCYv9t)0&3x1@wzZ%7WbpHkO}gVX5QmlK3A-gCO06fAaCP zn?e(OX=#kV08fWIAF&eG5$We2H(FA7uF8qkun>we<~Kh>!muQ&mhDZzUVJel;-wit zuJs;xzbeRV*nQ#=+O2CO6x0BYXb&mbPR^Z%t@Wt33J3|~4K%r^Fs0it>-cTowmdXb z{u|v2vIHxpna14-W?2>h5s6f9RbAtY5zrVy^k+F)3_W)e1Ba~|?ijxWurBUiU|s!) zO&1Q4Wud+c$0?|J91p93SKz2PX5%I2eYZGoZJ9h_Yu@p=(9lCrzRms)T>1)zMl)5N zz?^9lL?tVG;$Cj{->}O*zpJ{&-LXwLV1zhn=EZTn~skY*qz6xog zDC#VZn~zp@mgYWP6EzkqtE`Voa!5|Bs^7BrZ}XM3SA<&`xux$8|NG0)c_IZ~SnqzS z$VcYUiN-8#Rc)x9GuS5OK=XRLZ>JN@Tpns!pF0~m#$9m9fGG*!qt(*iIHZ4Q+DDYX zO&7$7duiohm=HmFkND`rzd`qOx5sWBoAZE8>hBCch25jM|GuU*HQK8Y(0o3)m0+CL zgc~8`jaDkn%sL^_hE$xT+ zIMUaf?$mnGodCMrM+n_I!0AJgDyYc}!@3i=M1I|Gia39r&^@0IxI^O+VviHRqFA{g zXJDk9FZ>HK_xouYzn%4GD-Gcd5FZ9&>_)w2K-h*_1Z$%)f-G^wpG(lbs zK-Vq^yaRw>X}d;juQP=s@qO0LCIa-|uY7?I#i}9TPGm%`na=b66Vm%npE`+w>!=fE zUVa`wH=HR1go6xUo+H3YEPDa{NFDx2DOVV3CtEsF6;6ww+d+RKeiz*MUH=uIvo`!= zYwlDbjfq*Ox0FZk{%aRb1%Bh=?gUx#6Iob;tRP^@tB2extwsBMD7l2Alu(HW#OOlo zTW(DT(r&D-V<^W`rIQffK4eq9P0h{Dcp4TQoxc8?xAr@dwVVcCm4<_r^*tKH>kFmQ ztZe)dk5yohLn}@Qaix*ukI$ENA6dqCE(@B93G6H1TJ0sQ9hD433=@7#nWp?NFAFL~ zpUfsSoc!d@YoFfC8aowbeZ0sQ30BZFx(XLUR(MO1HC_ujvg5@q2i%?dy5ax)vw=j? zr7a>u)`jPMN#64)r7*Gx2`J_5mCIt~!&mtybnGAdoQMOzb}r#zG1j6M4Hp)wQFspF zlo>AZr?!1k{J=FA%nS8!Ji}9UwYtTrr4AG&fd`^T{=@x^BvJQE?ArkEw8d-l`t-ivTm7`zk<*l^I2XB>@b=iWkh9cZUihC^U(V>X5uuaIFWjuZkaUpR`Rsaz`^!+kX8T933M31)fj?tl>4Fv^mf6ii}e4;Lg1MV@QR{d9#gNkq3}$ z;xxVX-wc8FH!Cuxb@_Vb{Lv3IV_Vp(oMOTy?-)DV13Vt>VRLzf_vdsD+@ROvsYh-Z zgNf*I!cp0dSt%O-8;bM$bGnP!c(EDIgI4i@Wpnp*OP+^MEqr>hpuX}aJkg>$dXx+_ zFM>+aYQ=UaxkxyI`@jjIDZE^=f)o$=7U+WZ(v59O2!K%7-0Q14~aA|6J%Kp+4nPt?- z*9LH5=l_1-Bj)?U@23j)J!?;}OIb&8jZT*-^XJ35q$cFqdD0QPtBve#f`3N)fA^(< zGKdgNKZ*}@n9I3bgnWdZH(eFMvmxdM#%A~IKU@v6^OjNJ>6hbxK@W5F1Z$6T9+PXc zCd^(V-vblwNJ|{~!|$HlKz-Hg`E;+^8pQPn;{&6YD>xBxnM%BN;Z z-}^UL_#nl2*VHk4oXfUgshQXc0Q&RCcDa5n$TB+kx0tF82N}FEl=|Nm|7m-lB4|z? zx_KW0ZBHdrC7i#Q%Ce0mQ$a}g?v4Gs0L=Lx!q+)M83NTw4L35NQp7De z+58nLdnf@Nt}17(@5)G)6*qO)Vt#-M*fdu&1H7AAy(CE$fOK94KPq*FZLN!o8XZ>U zp1)1aRlHmKayKBPz9wRnDqvszTB)sjabagW@VdRLK)Bo`&JO*rF%x+cWJ)2@IMo#s z-7V2mDl}=SS$%LhV2T)=efc25pIYZ`Ti<^e^R4cNN_AtK-p_ld4u+yFGow9!xntD& zt6ptufr5zfn2r)M>e2LqHp(rI9jRQ=vhYh@#-f+~;zg~yjNQ@)-}pC>@MMAixrk^Y zp*y&qd;53`q&8^0o{kJ{KcgR;W9Eb*M}-k*Eum5#^-S@VoinAE3Fywm zId-U$pIMvw>F*HFb8Nj^)@Bl+zmL*L!*%0cne1t@Ud=F6b(?o1bNj-jGcn(_#rF3I zQ~w^}qe~`WWRHHO5dG4=h0D|n`}fC!DGy3>94S*f?9b|Y*2qo+?d|QF;eG>$scC0N zBP>GmQDTZ&N-^HgW@uK8CBK_cHb!gZ&N+9(CI6W|-(cfSi+9|m?3 zV`VMOecY9-Ng`kh`~Q~NZ)=UO7byYX^95rdDU1*ov=Go6#Z~vKVI$smN9^CL2W((? zkQw2GRd!}CRC)pM0KImRUDQ8p5CR%iiR=p0^KNweuiL>7lMAHUEGx=@`};1*K+u-5 z7Jc-8EbIUNlcrveFt+kzr{G@*z0H*l8yEPq+hmEKM5@#o$^(omlb@VM#HorIEpRA;! KM3tCP@c#k#S+1`D literal 142886 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 H%!B_A?I9ur From de719d56df5234afdcaee925e01df7f3d0a18708 Mon Sep 17 00:00:00 2001 From: John Papa Date: Sun, 30 Nov 2014 11:04:58 -0500 Subject: [PATCH 054/567] updated modularity to reflect reusable modules across applications --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 53433f42..0318a647 100644 --- a/README.md +++ b/README.md @@ -2122,7 +2122,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see *Why?*: The main app module contains a quickly identifiable manifest of the application's features. - *Why?*: Each feature area contains a manifest of what it depends on, so it can be pulled in as a dependency and still work. + *Why?*: Each feature area contains a manifest of what it depends on, so it can be pulled in as a dependency in other applications and still work. *Why?*: Intra-App features such as shared data services become easy to locate and share from within `app.core` (choose your favorite name for this module). From 50a11a752cb2e22435da66213f911e4c835c977f Mon Sep 17 00:00:00 2001 From: Aleksandar Bogatinov Date: Sun, 30 Nov 2014 17:23:20 +0100 Subject: [PATCH 055/567] Updated to latest version --- i18n/mk-MK.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/i18n/mk-MK.md b/i18n/mk-MK.md index 72aaeb3a..2987336d 100644 --- a/i18n/mk-MK.md +++ b/i18n/mk-MK.md @@ -2061,13 +2061,13 @@ ### Зависности на модули ###### [Style [Y165](#style-Y165)] - - Корен модулот на апликацијата зависи од функционалностите и нејзините модули, функционалните модули немаат директни зависности додека модулите потребни низ многу апликации зависат од генеричките модули. + - Корен модулот на апликацијата зависи од функционалните модули на апликацијата како и било кои заеднички или реискористливи модули. ![Модуларност и Зависности](https://raw.githubusercontent.com/johnpapa/angularjs-styleguide/master/assets/modularity-1.png) *Зошто?*: Главниот модул на апликацијата содржи манифест од брзо идентифицирани функционалности на апликацијата. - *Зошто?*: Модулите потребни низ повеќе апликации полесно се споделуваат. Функционалностите генерално зависат на истите генерички модули, кои се вметнати во еден модул. (`app.core` во сликата). + *Зошто?*: Секоја функционалност е во околина која содржи манифест од сите нејзини зависности, која може да биде поставена како зависност во други апликации и да работи. *Зошто?*: Интра-Апликациски функционалности како податочни сервиси кои се споделени се лесни за лоцирање и споделување во `app.core` (изберете го вашето омилено име за овој модул). @@ -2075,6 +2075,8 @@ > Моите структури се разликуваат малку низ проекти, но сите ги запазуваат правилата за структура и модуларност. Имплементацијата може да се разликува во зависност од функционалностите и тимот. Со други зборови, не се засегајте на буквалната структура се додека ја оправдува вашата структура за конзистентност, одржливост и ефикасност. + > Во мали апликации можете да ги поставите сите заеднички зависности во апликацискиот модул каде функционалните зависности немаат директни зависности. Ова овозможува полесно одржување кај мали апликации, но станува потешко да се реискористуват тие модули надвор од оваа апликација. + **[Назад кон содржината](#table-of-contents)** ## Startup Logic From 4c9a948665d09d1b37c0eb511a152d438464117f Mon Sep 17 00:00:00 2001 From: John Papa Date: Sun, 30 Nov 2014 12:16:04 -0500 Subject: [PATCH 056/567] translation link fixes --- README.md | 2 +- i18n/it-IT.md | 2 +- i18n/mk-MK.md | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 0318a647..4c3dfaa9 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,7 @@ Many of my styles have been from the many pair programming sessions [Ward Bell]( While this guide explains the *what*, *why* and *how*, I find it helpful to see them in practice. This guide is accompanied by a sample application that follows these styles and patterns. You can find the [sample application (named modular) here](https://github.com/johnpapa/ng-demos) in the `modular` folder. Feel free to grab it, clone it, or fork it. [Instructions on running it are in its readme](https://github.com/johnpapa/ng-demos/tree/master/modular). ##Translations -[Translations of this Angular style guide](./i18n) are maintained by the community and can be found here. +[Translations of this Angular style guide](https://github.com/johnpapa/angularjs-styleguide/tree/master/i18n) are maintained by the community and can be found here. ## Table of Contents diff --git a/i18n/it-IT.md b/i18n/it-IT.md index 8982953c..48dc622d 100644 --- a/i18n/it-IT.md +++ b/i18n/it-IT.md @@ -21,7 +21,7 @@ Molti dei mie stili sono frutto di parecchie sessioni di pair programming che [W Nonostante questa guida spieghi i *cosa*, *come* e *perché*, trovo che sia di aiuto vederle in pratica. Questa guida è accompagnata da una applicazione di esempio che segue questi stili e schemi. Troverai l'[applicazione di esempio (chiamata modular) qui](https://github.com/johnpapa/ng-demos) nella cartella `modular`. Prendila, clonala o fanne un fork liberamente. [Le istruzioni su come eseguirla sono nel proprio readme](https://github.com/johnpapa/ng-demos/tree/master/modular). ##Traduzioni -[Traduzioni di questa guida stilistica ad AngularJS](./i18n) sono gestite dalla comunità e possono essere trovate qui. +[Traduzioni di questa guida stilistica ad AngularJS](https://github.com/johnpapa/angularjs-styleguide/tree/master/i18n) sono gestite dalla comunità e possono essere trovate qui. ## Tavola dei contenuti diff --git a/i18n/mk-MK.md b/i18n/mk-MK.md index 2987336d..74c58b07 100644 --- a/i18n/mk-MK.md +++ b/i18n/mk-MK.md @@ -23,7 +23,7 @@ ##Преводи -[Преводи од овој AngularJS водич на кодирање](./i18n) се одржувани од заедницата и можете да ги најдете тука. +[Преводи од овој AngularJS водич на кодирање](https://github.com/johnpapa/angularjs-styleguide/tree/master/i18n) се одржувани од заедницата и можете да ги најдете тука. ## Содржина From cbef44372766aefc68eb34b60ab62d61772ad666 Mon Sep 17 00:00:00 2001 From: angelochiello Date: Mon, 1 Dec 2014 09:24:03 +0100 Subject: [PATCH 057/567] [it-IT] PR #160 Updated as PR #160 "reusable modules across apps" --- i18n/it-IT.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/i18n/it-IT.md b/i18n/it-IT.md index 8982953c..c66836d2 100644 --- a/i18n/it-IT.md +++ b/i18n/it-IT.md @@ -2127,19 +2127,21 @@ Nonostante questa guida spieghi i *cosa*, *come* e *perché*, trovo che sia di a ### Dipendenze dei Moduli ###### [Stile [Y165](#stile-y165)] - - Il modulo principale dell'applicazione dipende dai moduli di funzionalità specifiche dell'app, i moduli delle funzionalità non hanno dipendenze dirette, moduli trans-applicazione dipendono da moduli generici. + - Il modulo principale dell'applicazione dipende dai moduli di funzionalità specifiche dell'app e da qualunque altro modulo che sia condiviso o riusabile. ![Modularità e Dipendenze](https://raw.githubusercontent.com/johnpapa/angularjs-styleguide/master/assets/modularity-1.png) *Perché?*: Il modulo principale dell'app contiene un manifesto che sia facilmente identificabile con le funzionalità dell'applicazione. - *Perché?*: Funzionalità trans-applicazione diventano semplici da condividere. Le funzionalità generalmente dipendono dagli stessi moduli tras-applicazione, che sono consolidati in in singolo modulo (`app.core` nell'immagine). + *Perché?*: Ogni area di funzionalità contiene un manifesto di ciò da cui dipende, in modo tale da poter essere usato come dipendenza in altre applicazioni e continuare a funzionare. *Perché?*: Funzionalità intra-app come servizio ai dati condiviso diventano facilmente localizzabili da dentro `app.core` (questi il nome che più di piaccia per questo modulo). Nota: Questa è una strategia per la consistenza. Ci sono diverse buone opzioni in questo caso. Scegline una che sia consistente, segua le regole delle dipendenze di AngularJS e sia facile da manutenere e scalabile. > La mia struttura varia leggermente tra progetti ma tutti seguono queste linee guida per la strutturazione e modularità. L'implementazione può variare in relazione alle funzionalità ed al team. In altre parole, non ti bloccare su una struttura che sia esattamente uguale ma giustifica la tua struttura tenendo a mente l'uso di consistenza, manutenibilità ed efficienza. + + > In una applicazione piccola, si può considerare di mettere tutte le dipendenze condivise nel modulo dell'app dove i moduli delle funzionalità non hanno dipendenze dirette. Ciò rende più semplice mantenere l'applicazione più piccola ma rende più difficile riutilizzare i moduli fuori dell'applicazione stessa. **[Torna all'inizio](#tavola-dei-contenuti)** From e49e94de98d43b3e8543db097353172eda1a76e3 Mon Sep 17 00:00:00 2001 From: robertd Date: Wed, 3 Dec 2014 12:04:07 -0700 Subject: [PATCH 058/567] Fix space and commas --- README.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 4c3dfaa9..07c386a1 100644 --- a/README.md +++ b/README.md @@ -62,8 +62,8 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see /* avoid */ angular .module('app', ['ngRoute']) - .controller('SomeController' , SomeController) - .factory('someFactory' , someFactory); + .controller('SomeController', SomeController) + .factory('someFactory', someFactory); function SomeController() { } @@ -86,7 +86,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see // someController.js angular .module('app') - .controller('SomeController' , SomeController); + .controller('SomeController', SomeController); function SomeController() { } ``` @@ -97,7 +97,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see // someFactory.js angular .module('app') - .factory('someFactory' , someFactory); + .factory('someFactory', someFactory); function someFactory() { } ``` @@ -219,7 +219,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see ```javascript /* avoid */ var app = angular.module('app'); - app.controller('SomeController' , SomeController); + app.controller('SomeController', SomeController); function SomeController() { } ``` @@ -228,7 +228,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see /* recommended */ angular .module('app') - .controller('SomeController' , SomeController); + .controller('SomeController', SomeController); function SomeController() { } ``` From 981a0b627438026f4230353b258ae6a8fd299c07 Mon Sep 17 00:00:00 2001 From: natee Date: Thu, 4 Dec 2014 12:17:08 +0800 Subject: [PATCH 059/567] sync change --- i18n/zh-CN.md | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/i18n/zh-CN.md b/i18n/zh-CN.md index 65d20ee1..1ab7e992 100644 --- a/i18n/zh-CN.md +++ b/i18n/zh-CN.md @@ -20,6 +20,8 @@ ## 在示例App中了解这些风格 看示例代码有助于你更好地理解,你可以在`modular`文件夹下找到[命名为modular的示例应用程序](https://github.com/johnpapa/ng-demos),随便克隆。 +##翻译 +[AngularJS风格指南翻译版本](https://github.com/johnpapa/angularjs-styleguide/tree/master/i18n)。 ##目录 @@ -64,8 +66,8 @@ /* avoid */ angular .module('app', ['ngRoute']) - .controller('SomeController' , SomeController) - .factory('someFactory' , someFactory); + .controller('SomeController', SomeController) + .factory('someFactory', someFactory); function SomeController() { } @@ -88,7 +90,7 @@ // someController.js angular .module('app') - .controller('SomeController' , SomeController); + .controller('SomeController', SomeController); function SomeController() { } ``` @@ -99,7 +101,7 @@ // someFactory.js angular .module('app') - .factory('someFactory' , someFactory); + .factory('someFactory', someFactory); function someFactory() { } ``` @@ -220,7 +222,7 @@ ```javascript /* avoid */ var app = angular.module('app'); - app.controller('SomeController' , SomeController); + app.controller('SomeController', SomeController); function SomeController() { } ``` @@ -229,7 +231,7 @@ /* recommended */ angular .module('app') - .controller('SomeController' , SomeController); + .controller('SomeController', SomeController); function SomeController() { } ``` @@ -2097,13 +2099,13 @@ ###模块依赖 ###### [Style [Y165](#style-y165)] - - 应用程序根模块依赖于应用程序特定的功能模块,功能模块没有直接的依赖关系,跨应用的模块取决于所有通用模块。 + - 应用程序根模块依赖于应用程序特定的功能模块、共享的和可复用的模块。 ![模块化和依赖](https://raw.githubusercontent.com/johnpapa/angularjs-styleguide/master/assets/modularity-1.png) *为什么?*:主程序模块包含一个能快速识别应用程序功能的清单。 - *为什么?*:跨应用程序的功能变得更加容易分享。功能一般都是依靠于相同的跨应用模块,这些模块都被合并到一个单独的模块当中(图中所示的`app.core`)。 + *为什么?*:每个功能区都包含一个它依赖了哪些模块的列表,因此其它应用可以把它当作一个依赖引入进来。 *为什么?*:程序内部的功能,如共享数据的服务变得容易定位,并且从`app.core`中共享。 From d10b4052b7dc6cd4e7bde20162677602911da884 Mon Sep 17 00:00:00 2001 From: angelochiello Date: Thu, 4 Dec 2014 08:45:43 +0100 Subject: [PATCH 060/567] [it-IT] PR #166 Updated as PR #166 --- i18n/it-IT.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/i18n/it-IT.md b/i18n/it-IT.md index c66836d2..9d5e531c 100644 --- a/i18n/it-IT.md +++ b/i18n/it-IT.md @@ -66,8 +66,8 @@ Nonostante questa guida spieghi i *cosa*, *come* e *perché*, trovo che sia di a /* evitare */ angular .module('app', ['ngRoute']) - .controller('SomeController' , SomeController) - .factory('someFactory' , someFactory); + .controller('SomeController', SomeController) + .factory('someFactory', someFactory); function SomeController() { } @@ -90,7 +90,7 @@ Nonostante questa guida spieghi i *cosa*, *come* e *perché*, trovo che sia di a // someController.js angular .module('app') - .controller('SomeController' , SomeController); + .controller('SomeController', SomeController); function SomeController() { } ``` @@ -101,7 +101,7 @@ Nonostante questa guida spieghi i *cosa*, *come* e *perché*, trovo che sia di a // someFactory.js angular .module('app') - .factory('someFactory' , someFactory); + .factory('someFactory', someFactory); function someFactory() { } ``` @@ -222,7 +222,7 @@ Nonostante questa guida spieghi i *cosa*, *come* e *perché*, trovo che sia di a ```javascript /* evitare */ var app = angular.module('app'); - app.controller('SomeController' , SomeController); + app.controller('SomeController', SomeController); function SomeController() { } ``` @@ -231,7 +231,7 @@ Nonostante questa guida spieghi i *cosa*, *come* e *perché*, trovo che sia di a /* consigliato */ angular .module('app') - .controller('SomeController' , SomeController); + .controller('SomeController', SomeController); function SomeController() { } ``` From 878c48b59d1952a9a622062afc69886bea0da51a Mon Sep 17 00:00:00 2001 From: Chris Schmitz Date: Wed, 3 Dec 2014 16:45:33 -0600 Subject: [PATCH 061/567] Fix a syntax error in Y190 --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 07c386a1..f60e6b93 100644 --- a/README.md +++ b/README.md @@ -2227,11 +2227,11 @@ Unit testing helps maintain clean code, as such I included some of my recommenda //TODO }); - it('should have 10 Avengers', function() {} + it('should have 10 Avengers', function() { //TODO (mock data?) }); - it('should return Avengers via XHR', function() {} + it('should return Avengers via XHR', function() { //TODO ($httpBackend?) }); From 03d8004f5b1d8f88071416126ece42e1503b9c43 Mon Sep 17 00:00:00 2001 From: angelochiello Date: Fri, 5 Dec 2014 09:42:48 +0100 Subject: [PATCH 062/567] [it-IT] PR #167 Updated as PR #167 --- i18n/it-IT.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/i18n/it-IT.md b/i18n/it-IT.md index 9d5e531c..53a10d7d 100644 --- a/i18n/it-IT.md +++ b/i18n/it-IT.md @@ -2238,11 +2238,11 @@ Gli unit test aiutano a mantenere il codice più chiaro, perciò ho incluso alcu //TODO }); - it('dovrebbe avere 10 Avenger', function() {} + it('dovrebbe avere 10 Avenger', function() { //TODO (fare un mock dei dati?) }); - it('dovrebbe ritornare Avenger via XHR', function() {} + it('dovrebbe ritornare Avenger via XHR', function() { //TODO ($httpBackend?) }); From d601af45bc90b8d4f07f7edefce1f1a225d20635 Mon Sep 17 00:00:00 2001 From: gaboesquivel Date: Tue, 9 Dec 2014 14:54:46 -0600 Subject: [PATCH 063/567] link to raw files for download --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index f60e6b93..ef9d2257 100644 --- a/README.md +++ b/README.md @@ -2495,7 +2495,7 @@ Use file templates or snippets to help follow consistent styles and patterns. He - AngularJS snippets that follow these styles and guidelines. - - Download the [Sublime Angular snippets](assets/sublime-angular-snippets.zip) + - Download the [Sublime Angular snippets](assets/sublime-angular-snippets.zip?raw=true) - Place it in your Packages folder - Restart Sublime - In a JavaScript file type these commands followed by a `TAB` @@ -2521,7 +2521,7 @@ Use file templates or snippets to help follow consistent styles and patterns. He - AngularJS snippets and file templates that follow these styles and guidelines. You can import them into your WebStorm settings: - - Download the [WebStorm AngularJS file templates and snippets](assets/webstorm-angular-file-template.settings.jar) + - Download the [WebStorm AngularJS file templates and snippets](assets/webstorm-angular-file-template.settings.jar?raw=true) - Open WebStorm and go to the `File` menu - Choose the `Import Settings` menu option - Select the file and click `OK` From b937860cb2a04ef4bf24b62493f513ee2fa29d8e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=B5=B5=E5=8F=AF?= Date: Wed, 10 Dec 2014 14:47:11 +0800 Subject: [PATCH 064/567] merge #173 --- i18n/zh-CN.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/i18n/zh-CN.md b/i18n/zh-CN.md index 1ab7e992..cd172046 100644 --- a/i18n/zh-CN.md +++ b/i18n/zh-CN.md @@ -2210,11 +2210,11 @@ //TODO }); - it('should have 10 Avengers', function() {} + it('should have 10 Avengers', function() { //TODO (mock data?) }); - it('should return Avengers via XHR', function() {} + it('should return Avengers via XHR', function() { //TODO ($httpBackend?) }); @@ -2484,7 +2484,7 @@ - AngularJS片段遵循这些风格指南。 - - 下载[Sublime Angular snippets](assets/sublime-angular-snippets.zip) + - 下载[Sublime Angular snippets](assets/sublime-angular-snippets.zip?raw=true) - 把它放到Packages文件夹中 - 重启Sublime - 在JavaScript文件中输入下面的命令然后按下`TAB`键即可: @@ -2508,7 +2508,7 @@ - 你可以把它们导入到WebStorm设置中: - - 下载[WebStorm AngularJS file templates and snippets](assets/webstorm-angular-file-template.settings.jar) + - 下载[WebStorm AngularJS file templates and snippets](assets/webstorm-angular-file-template.settings.jar?raw=true) - 打开WebStorm点击`File`菜单 - 选择`Import Settings`菜单选项 - 选择文件点击`OK` From 033099f0e551c1a551d4ed5ced8d3a6dd967f30f Mon Sep 17 00:00:00 2001 From: angelochiello Date: Wed, 10 Dec 2014 11:19:09 +0100 Subject: [PATCH 065/567] [it-IT] PR #173 Updated as PR #173 --- i18n/it-IT.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/i18n/it-IT.md b/i18n/it-IT.md index 53a10d7d..cdf77880 100644 --- a/i18n/it-IT.md +++ b/i18n/it-IT.md @@ -2506,7 +2506,7 @@ Usa file template o snippet che ti aiutino a seguire stili e schemi consistentem - Snippet di AngularJS che seguono questi stili e linee guida. - - Scarica gli [snippet di Angular per Sublime](assets/sublime-angular-snippets.zip) + - Scarica gli [snippet di Angular per Sublime](assets/sublime-angular-snippets.zip?raw=true) - Mettili nella tua cartella Packages - Riavvia Sublime - In un file JavaScript digita questi comandi seguiti da `TAB` @@ -2532,7 +2532,7 @@ Usa file template o snippet che ti aiutino a seguire stili e schemi consistentem - Snippet di Angular JS e file di template che seguono queste linee guida. Le puoi importare dentro i tuoi settaggi di WebStorm: - - Scarica i [file dei template e gli snippet diAngularJS per WebStorm](assets/webstorm-angular-file-template.settings.jar) + - Scarica i [file dei template e gli snippet diAngularJS per WebStorm](assets/webstorm-angular-file-template.settings.jar?raw=true) - Apri WebStorm e vai al menù `File` - Scegli la voce di menù `Import Settings` - Seleziona il file e clicca `OK` From 75007d995e7253b756f004a5638c0924b5b42ef3 Mon Sep 17 00:00:00 2001 From: angelochiello Date: Mon, 1 Dec 2014 09:24:03 +0100 Subject: [PATCH 066/567] [it-IT] PR #160 Updated as PR #160 "reusable modules across apps" --- i18n/it-IT.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/i18n/it-IT.md b/i18n/it-IT.md index 48dc622d..3e241dea 100644 --- a/i18n/it-IT.md +++ b/i18n/it-IT.md @@ -2127,19 +2127,21 @@ Nonostante questa guida spieghi i *cosa*, *come* e *perché*, trovo che sia di a ### Dipendenze dei Moduli ###### [Stile [Y165](#stile-y165)] - - Il modulo principale dell'applicazione dipende dai moduli di funzionalità specifiche dell'app, i moduli delle funzionalità non hanno dipendenze dirette, moduli trans-applicazione dipendono da moduli generici. + - Il modulo principale dell'applicazione dipende dai moduli di funzionalità specifiche dell'app e da qualunque altro modulo che sia condiviso o riusabile. ![Modularità e Dipendenze](https://raw.githubusercontent.com/johnpapa/angularjs-styleguide/master/assets/modularity-1.png) *Perché?*: Il modulo principale dell'app contiene un manifesto che sia facilmente identificabile con le funzionalità dell'applicazione. - *Perché?*: Funzionalità trans-applicazione diventano semplici da condividere. Le funzionalità generalmente dipendono dagli stessi moduli tras-applicazione, che sono consolidati in in singolo modulo (`app.core` nell'immagine). + *Perché?*: Ogni area di funzionalità contiene un manifesto di ciò da cui dipende, in modo tale da poter essere usato come dipendenza in altre applicazioni e continuare a funzionare. *Perché?*: Funzionalità intra-app come servizio ai dati condiviso diventano facilmente localizzabili da dentro `app.core` (questi il nome che più di piaccia per questo modulo). Nota: Questa è una strategia per la consistenza. Ci sono diverse buone opzioni in questo caso. Scegline una che sia consistente, segua le regole delle dipendenze di AngularJS e sia facile da manutenere e scalabile. > La mia struttura varia leggermente tra progetti ma tutti seguono queste linee guida per la strutturazione e modularità. L'implementazione può variare in relazione alle funzionalità ed al team. In altre parole, non ti bloccare su una struttura che sia esattamente uguale ma giustifica la tua struttura tenendo a mente l'uso di consistenza, manutenibilità ed efficienza. + + > In una applicazione piccola, si può considerare di mettere tutte le dipendenze condivise nel modulo dell'app dove i moduli delle funzionalità non hanno dipendenze dirette. Ciò rende più semplice mantenere l'applicazione più piccola ma rende più difficile riutilizzare i moduli fuori dell'applicazione stessa. **[Torna all'inizio](#tavola-dei-contenuti)** From a0300d3a8f837c03518a32bfecb30fccc3333aa3 Mon Sep 17 00:00:00 2001 From: robertd Date: Wed, 3 Dec 2014 12:04:07 -0700 Subject: [PATCH 067/567] Fix space and commas --- README.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 4c3dfaa9..07c386a1 100644 --- a/README.md +++ b/README.md @@ -62,8 +62,8 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see /* avoid */ angular .module('app', ['ngRoute']) - .controller('SomeController' , SomeController) - .factory('someFactory' , someFactory); + .controller('SomeController', SomeController) + .factory('someFactory', someFactory); function SomeController() { } @@ -86,7 +86,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see // someController.js angular .module('app') - .controller('SomeController' , SomeController); + .controller('SomeController', SomeController); function SomeController() { } ``` @@ -97,7 +97,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see // someFactory.js angular .module('app') - .factory('someFactory' , someFactory); + .factory('someFactory', someFactory); function someFactory() { } ``` @@ -219,7 +219,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see ```javascript /* avoid */ var app = angular.module('app'); - app.controller('SomeController' , SomeController); + app.controller('SomeController', SomeController); function SomeController() { } ``` @@ -228,7 +228,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see /* recommended */ angular .module('app') - .controller('SomeController' , SomeController); + .controller('SomeController', SomeController); function SomeController() { } ``` From 521474b882a7094d06f70446a23608f38804a5ca Mon Sep 17 00:00:00 2001 From: angelochiello Date: Thu, 4 Dec 2014 08:45:43 +0100 Subject: [PATCH 068/567] [it-IT] PR #166 Updated as PR #166 --- i18n/it-IT.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/i18n/it-IT.md b/i18n/it-IT.md index 3e241dea..b61a81fc 100644 --- a/i18n/it-IT.md +++ b/i18n/it-IT.md @@ -66,8 +66,8 @@ Nonostante questa guida spieghi i *cosa*, *come* e *perché*, trovo che sia di a /* evitare */ angular .module('app', ['ngRoute']) - .controller('SomeController' , SomeController) - .factory('someFactory' , someFactory); + .controller('SomeController', SomeController) + .factory('someFactory', someFactory); function SomeController() { } @@ -90,7 +90,7 @@ Nonostante questa guida spieghi i *cosa*, *come* e *perché*, trovo che sia di a // someController.js angular .module('app') - .controller('SomeController' , SomeController); + .controller('SomeController', SomeController); function SomeController() { } ``` @@ -101,7 +101,7 @@ Nonostante questa guida spieghi i *cosa*, *come* e *perché*, trovo che sia di a // someFactory.js angular .module('app') - .factory('someFactory' , someFactory); + .factory('someFactory', someFactory); function someFactory() { } ``` @@ -222,7 +222,7 @@ Nonostante questa guida spieghi i *cosa*, *come* e *perché*, trovo che sia di a ```javascript /* evitare */ var app = angular.module('app'); - app.controller('SomeController' , SomeController); + app.controller('SomeController', SomeController); function SomeController() { } ``` @@ -231,7 +231,7 @@ Nonostante questa guida spieghi i *cosa*, *come* e *perché*, trovo che sia di a /* consigliato */ angular .module('app') - .controller('SomeController' , SomeController); + .controller('SomeController', SomeController); function SomeController() { } ``` From acfbbb2b79aa2b9153ebcbf5cf5ab25e35e600d9 Mon Sep 17 00:00:00 2001 From: Chris Schmitz Date: Wed, 3 Dec 2014 16:45:33 -0600 Subject: [PATCH 069/567] Fix a syntax error in Y190 --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 07c386a1..f60e6b93 100644 --- a/README.md +++ b/README.md @@ -2227,11 +2227,11 @@ Unit testing helps maintain clean code, as such I included some of my recommenda //TODO }); - it('should have 10 Avengers', function() {} + it('should have 10 Avengers', function() { //TODO (mock data?) }); - it('should return Avengers via XHR', function() {} + it('should return Avengers via XHR', function() { //TODO ($httpBackend?) }); From 150c7288695c8fbee099b0de07cdd4b347689d46 Mon Sep 17 00:00:00 2001 From: angelochiello Date: Fri, 5 Dec 2014 09:42:48 +0100 Subject: [PATCH 070/567] [it-IT] PR #167 Updated as PR #167 --- i18n/it-IT.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/i18n/it-IT.md b/i18n/it-IT.md index b61a81fc..444f46e1 100644 --- a/i18n/it-IT.md +++ b/i18n/it-IT.md @@ -2238,11 +2238,11 @@ Gli unit test aiutano a mantenere il codice più chiaro, perciò ho incluso alcu //TODO }); - it('dovrebbe avere 10 Avenger', function() {} + it('dovrebbe avere 10 Avenger', function() { //TODO (fare un mock dei dati?) }); - it('dovrebbe ritornare Avenger via XHR', function() {} + it('dovrebbe ritornare Avenger via XHR', function() { //TODO ($httpBackend?) }); From 70b7aa44b9958b83dc32852e68e9d73675ca6800 Mon Sep 17 00:00:00 2001 From: gaboesquivel Date: Tue, 9 Dec 2014 14:54:46 -0600 Subject: [PATCH 071/567] link to raw files for download --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index f60e6b93..ef9d2257 100644 --- a/README.md +++ b/README.md @@ -2495,7 +2495,7 @@ Use file templates or snippets to help follow consistent styles and patterns. He - AngularJS snippets that follow these styles and guidelines. - - Download the [Sublime Angular snippets](assets/sublime-angular-snippets.zip) + - Download the [Sublime Angular snippets](assets/sublime-angular-snippets.zip?raw=true) - Place it in your Packages folder - Restart Sublime - In a JavaScript file type these commands followed by a `TAB` @@ -2521,7 +2521,7 @@ Use file templates or snippets to help follow consistent styles and patterns. He - AngularJS snippets and file templates that follow these styles and guidelines. You can import them into your WebStorm settings: - - Download the [WebStorm AngularJS file templates and snippets](assets/webstorm-angular-file-template.settings.jar) + - Download the [WebStorm AngularJS file templates and snippets](assets/webstorm-angular-file-template.settings.jar?raw=true) - Open WebStorm and go to the `File` menu - Choose the `Import Settings` menu option - Select the file and click `OK` From 8b76716516561e39438091c3fba61ea9cac9464e Mon Sep 17 00:00:00 2001 From: angelochiello Date: Wed, 10 Dec 2014 11:19:09 +0100 Subject: [PATCH 072/567] [it-IT] PR #173 Updated as PR #173 --- i18n/it-IT.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/i18n/it-IT.md b/i18n/it-IT.md index 444f46e1..1377c92a 100644 --- a/i18n/it-IT.md +++ b/i18n/it-IT.md @@ -2506,7 +2506,7 @@ Usa file template o snippet che ti aiutino a seguire stili e schemi consistentem - Snippet di AngularJS che seguono questi stili e linee guida. - - Scarica gli [snippet di Angular per Sublime](assets/sublime-angular-snippets.zip) + - Scarica gli [snippet di Angular per Sublime](assets/sublime-angular-snippets.zip?raw=true) - Mettili nella tua cartella Packages - Riavvia Sublime - In un file JavaScript digita questi comandi seguiti da `TAB` @@ -2532,7 +2532,7 @@ Usa file template o snippet che ti aiutino a seguire stili e schemi consistentem - Snippet di Angular JS e file di template che seguono queste linee guida. Le puoi importare dentro i tuoi settaggi di WebStorm: - - Scarica i [file dei template e gli snippet diAngularJS per WebStorm](assets/webstorm-angular-file-template.settings.jar) + - Scarica i [file dei template e gli snippet diAngularJS per WebStorm](assets/webstorm-angular-file-template.settings.jar?raw=true) - Apri WebStorm e vai al menù `File` - Scegli la voce di menù `Import Settings` - Seleziona il file e clicca `OK` From 19f935bfd1816ef37732c090a1818be0f36347ce Mon Sep 17 00:00:00 2001 From: John Papa Date: Sun, 14 Dec 2014 19:41:32 -0500 Subject: [PATCH 073/567] helps clarify controller as and watches, as per question in issue #176 --- README.md | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 4c3dfaa9..1c75d619 100644 --- a/README.md +++ b/README.md @@ -367,11 +367,20 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see Note: When creating watches in a controller using `controller as`, you can watch the `vm.*` member using the following syntax. (Create watches with caution as they add more load to the digest cycle.) + ```html + + ``` + ```javascript - $scope.$watch('vm.title', function(current, original) { - $log.info('vm.title was %s', original); - $log.info('vm.title is now %s', current); - }); + function SomeController($scope, $log) { + var vm = this; + vm.title = 'Some Title'; + + $scope.$watch('vm.title', function(current, original) { + $log.info('vm.title was %s', original); + $log.info('vm.title is now %s', current); + }); + } ``` ### Bindable Members Up Top From 0962e06d8a5c88f71e28d5fabaa0a94c4d260cc9 Mon Sep 17 00:00:00 2001 From: angelochiello Date: Mon, 15 Dec 2014 09:04:30 +0100 Subject: [PATCH 074/567] [it-IT] PR #178 Updated as PR #178 "helps clarify controller as and watches, as per question in issue #176" --- i18n/it-IT.md | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/i18n/it-IT.md b/i18n/it-IT.md index cdf77880..79d1c12f 100644 --- a/i18n/it-IT.md +++ b/i18n/it-IT.md @@ -370,11 +370,20 @@ Nonostante questa guida spieghi i *cosa*, *come* e *perché*, trovo che sia di a Nota: Quando di creano watch in un controller usando `controller as`, puoi fare il watch del membro `vm.*` usando la seguente sintassi. (Crea watch con cautela poiché aggiungono carico al ciclo di digest.) + ```html + + ``` + ```javascript - $scope.$watch('vm.title', function(current, original) { - $log.info('vm.title was %s', original); - $log.info('vm.title is now %s', current); - }); + function SomeController($scope, $log) { + var vm = this; + vm.title = 'Some Title'; + + $scope.$watch('vm.title', function(current, original) { + $log.info('vm.title was %s', original); + $log.info('vm.title is now %s', current); + }); + } ``` ### Membri che possono fare il bind in cima From 1fa90796c5155c5879fe098f6fcc0efd92d83b2b Mon Sep 17 00:00:00 2001 From: Christian Walther Date: Mon, 15 Dec 2014 15:27:35 +0100 Subject: [PATCH 075/567] Typo: Inconsistent Style Code Y035/Y036 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Style “Defer Controller Logic” has an inconsistent style code: Y035 in the link text and Y036 in the link URL. I don’t know which of the two is more correct. This commit changes the URL to Y035 in order to keep existing links working. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 9b1d5a05..750f0cff 100644 --- a/README.md +++ b/README.md @@ -548,7 +548,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see ``` ### Defer Controller Logic -###### [Style [Y035](#style-y036)] +###### [Style [Y035](#style-y035)] - Defer logic in a controller by delegating to services and factories. From dfd16b205696c08127ed09d99212e38ee1502775 Mon Sep 17 00:00:00 2001 From: Ward Bell Date: Mon, 15 Dec 2014 18:57:43 -0800 Subject: [PATCH 076/567] Clarify w/ a heavy hammer why a viewmodel should delegate data access to a service --- README.md | 34 ++++++++++++++++++++++++++-------- 1 file changed, 26 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 9b1d5a05..8d341330 100644 --- a/README.md +++ b/README.md @@ -559,31 +559,49 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see *Why?*: Removes dependencies and hides implementation details from the controller. ```javascript + /* avoid */ - function Order($http, $q) { + function Order($http, $q, config, userInfo) { var vm = this; vm.checkCredit = checkCredit; + vm.isCreditOk; vm.total = 0; - function checkCredit() { - var orderTotal = vm.total; - return $http.get('api/creditcheck').then(function(data) { - var remaining = data.remaining; - return $q.when(!!(remaining > orderTotal)); - }); + function checkCredit() { + var settings = {}; + // Get the credit service base URL from config + // Set credit service required headers + // Prepare URL query string or data object with request data + // Add user-identifying info so service gets the right credit limit for this user. + // Use JSONP for this browser if it doesn't support CORS + return $http.get(settings) + .then(function(data) { + // Unpack JSON data in the response object + // to find maxRemainingAmount + vm.isCreditOk = vm.total <= maxRemainingAmount + }) + .catch(function(error) { + // Interpret error + // Cope w/ timeout? retry? try alternate service? + // Re-reject with appropriate error for a user to see + }); }; } ``` ```javascript + /* recommended */ function Order(creditService) { var vm = this; vm.checkCredit = checkCredit; + vm.isCreditOk; vm.total = 0; function checkCredit() { - return creditService.check(); + return creditService.isOrderTotalOk(vm.total) + .then(function(isOk) { vm.isCreditOk = isOk; }) + .catch(showServiceError); }; } ``` From 23c3f08f509f292df43ea6b33063bc05afe0c2a7 Mon Sep 17 00:00:00 2001 From: Aleksandar Bogatinov Date: Tue, 16 Dec 2014 05:28:37 +0100 Subject: [PATCH 077/567] Updated to latest version --- i18n/mk-MK.md | 57 +++++++++++++++++++++++++++++++++------------------ 1 file changed, 37 insertions(+), 20 deletions(-) diff --git a/i18n/mk-MK.md b/i18n/mk-MK.md index 74c58b07..c084a03d 100644 --- a/i18n/mk-MK.md +++ b/i18n/mk-MK.md @@ -68,8 +68,8 @@ /* избегнувајте */ angular .module('app', ['ngRoute']) - .controller('someController' , someController) - .factory('someFactory' , someFactory); + .controller('someController', someController) + .factory('someFactory', someFactory); function SomeController() { } @@ -92,7 +92,7 @@ // someController.js angular .module('app') - .controller('SomeController' , SomeController); + .controller('SomeController', SomeController); function SomeController() { } ``` @@ -103,7 +103,7 @@ // someFactory.js angular .module('app') - .factory('someFactory' , someFactory); + .factory('someFactory', someFactory); function someFactory() { } ``` @@ -221,7 +221,7 @@ ```javascript /* избегнувајте */ var app = angular.module('app'); - app.controller('SomeController' , SomeController); + app.controller('SomeController', SomeController); function SomeController() { } ``` @@ -230,7 +230,7 @@ /* препорачано */ angular .module('app') - .controller('SomeController' , SomeController); + .controller('SomeController', SomeController); function SomeController() { } ``` @@ -533,7 +533,7 @@ ``` ### Одлагање Логика во Контролерот -###### [Style [Y035](#style-Y036)] +###### [Style [Y035](#style-Y035)] - Одлагајте логика на во контролерот со делегирање до сервиси и фабрики. *Зошто?*: Логиката може да биде повторно искористена кога е во сервис, од повеќе контролери и изложена преку функција. @@ -544,18 +544,31 @@ ```javascript /* избегнувајте */ - function Order($http, $q) { + function Order($http, $q, config, userInfo) { var vm = this; vm.checkCredit = checkCredit; + vm.isCreditOk; vm.total = 0; - function checkCredit() { - var orderTotal = vm.total; - return $http.get('api/creditcheck').then(function(data) { - var remaining = data.remaining; - return $q.when(!!(remaining > orderTotal)); - }); - }; + function checkCredit() { + var settings = {}; + // Земете го URL-то на сервисот за кредит од config датотеката + // Поставете ги потребните заглавија + // Спремете го потребното URL барање или потребниот податочен објект за побарување на податоците + // Додадете инфо за идентификација на корисникот за сервисот да добие точниот лимит на кредитот за овој корисник + // Употребете JSONP за овој пребарувач доколку не подржува CORS + return $http.get(settings) + .then(function(data) { + // Отпакувајте го JSON податокот во одговорот + // за да го најдете maxRemainingAmount + vm.isCreditOk = vm.total <= maxRemainingAmount + }) + .catch(function(error) { + // Интерпретирајте ја грешката + // Спремете се со истекување на време? пробување пак? друг сервис? + // Повторно одбиете за корисникот да ја забележи соодветната порака + }); + }; } ``` @@ -564,10 +577,14 @@ function Order(creditService) { var vm = this; vm.checkCredit = checkCredit; + vm.isCreditOk; vm.total = 0; function checkCredit() { - return creditService.check(); + return creditService.isOrderTotalOk(vm.total) + .then(function(isOk) { vm.isCreditOk = isOk; }) + .catch(showServiceError); + }; }; } ``` @@ -2167,11 +2184,11 @@ //TODO }); - it('should have 10 Avengers', function() {} + it('should have 10 Avengers', function() { //TODO (mock data?) }); - it('should return Avengers via XHR', function() {} + it('should return Avengers via XHR', function() { //TODO ($httpBackend?) }); @@ -2422,7 +2439,7 @@ ###### [Style [Y250](#style-Y250)] - AngularJS кратки кодови кои ги следат овие водичи и стилови на код. - - Симнете ги [Sublime Angular кратки кодови](assets/sublime-angular-snippets.zip) + - Симнете ги [Sublime Angular кратки кодови](assets/sublime-angular-snippets.zip?raw=true) - Поставете ги во вашата Packages папка - Рестартирајте го Sublime - Во JavaScript датотека напишете ја следната команда и потоа кликнете на `TAB` @@ -2446,7 +2463,7 @@ ###### [Style [Y252](#style-Y252)] - AngularJS кратки кодови и датотечни шаблони кои ги следат овие стилови и водичи на код. Можете да ги внесете во вашите WebStorm подесувања: - - Симнете ги [WebStorm AngularJS датотечни шаблони и кратки кодови](assets/webstorm-angular-file-template.settings.jar) + - Симнете ги [WebStorm AngularJS датотечни шаблони и кратки кодови](assets/webstorm-angular-file-template.settings.jar?raw=true) - Отворете го WebStorm и одберете го `File` менито - Одберете го `Import Settings` - Одберете ја датотеката и кликнете `OK` From a8e57e36adb0f564123bd239d925f80ea6918f8c Mon Sep 17 00:00:00 2001 From: angelochiello Date: Tue, 16 Dec 2014 09:49:41 +0100 Subject: [PATCH 078/567] [it-IT] PR #182 Updated as PR #182 "Clarify why a ViewModel should delegate data access to a service" --- i18n/it-IT.md | 34 ++++++++++++++++++++++++++-------- 1 file changed, 26 insertions(+), 8 deletions(-) diff --git a/i18n/it-IT.md b/i18n/it-IT.md index 79d1c12f..e3f52dde 100644 --- a/i18n/it-IT.md +++ b/i18n/it-IT.md @@ -562,31 +562,49 @@ Nonostante questa guida spieghi i *cosa*, *come* e *perché*, trovo che sia di a *Perché?*: Rimuove dipendenze e nasconde dettagli di implementazione dal controller. ```javascript + /* evitare */ - function Order($http, $q) { + function Order($http, $q, config, userInfo) { var vm = this; vm.checkCredit = checkCredit; + vm.isCreditOk; vm.total = 0; - function checkCredit() { - var orderTotal = vm.total; - return $http.get('api/creditcheck').then(function(data) { - var remaining = data.remaining; - return $q.when(!!(remaining > orderTotal)); - }); + function checkCredit() { + var settings = {}; + // Prendi la URL di base per il servizio del credito + // Setta le intestazioni necessarie per il servizio del credito + // Prepara le URL della query string o i data object con i dati richiesti + // Aggiungi le informazioni sull'identificazione dell'utente così il servizio prende i dati sul limite del credito corretto + // Usare JSONP per questo browser se CORS non è supportato + return $http.get(settings) + .then(function(data) { + // Unpack JSON data in the response object + // to find maxRemainingAmount + vm.isCreditOk = vm.total <= maxRemainingAmount + }) + .catch(function(error) { + // Errore dell'interprete + // Affronta timeout? nuovo tentativo? provare servizi alternativi? + // Rilancia con l'errore appropriato per essere letto dall'utente + }); }; } ``` ```javascript + /* consigliato */ function Order(creditService) { var vm = this; vm.checkCredit = checkCredit; + vm.isCreditOk; vm.total = 0; function checkCredit() { - return creditService.check(); + return creditService.isOrderTotalOk(vm.total) + .then(function(isOk) { vm.isCreditOk = isOk; }) + .catch(showServiceError); }; } ``` From 77b44b38fb0365f0967febe5dcdd4e8b531210d5 Mon Sep 17 00:00:00 2001 From: Andre Baltieri Date: Wed, 17 Dec 2014 13:25:51 -0200 Subject: [PATCH 079/567] Update PT-BR.md --- i18n/PT-BR.md | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/i18n/PT-BR.md b/i18n/PT-BR.md index 0099cb3b..0982811e 100644 --- a/i18n/PT-BR.md +++ b/i18n/PT-BR.md @@ -1535,13 +1535,13 @@ ou *Minificação e Anotação* > Nota: Apartir do AngularJS 1.3 use o parâmetro `ngStrictDi` da diretiva [`ngApp`](https://docs.angularjs.org/api/ng/directive/ngApp). Quando presente, o injetor será criado no modo "strict-di" fazendo com que a aplicação falhe ao tentar invocar funções que não usem anotação explícita de função (elas podem não ser seguras para minificação). Informação de debug será logada no console para ajudar a rastrear o código ofensivo. `` -### Use Gulp or Grunt for ng-annotate +### Utilize Gulp ou Grunt para o ng-annotate - - Use [gulp-ng-annotate](https://www.npmjs.org/package/gulp-ng-annotate) or [grunt-ng-annotate](https://www.npmjs.org/package/grunt-ng-annotate) in an automated build task. Inject `/* @ngInject */` prior to any function that has dependencies. + - Utilize [gulp-ng-annotate](https://www.npmjs.org/package/gulp-ng-annotate) ou [grunt-ng-annotate](https://www.npmjs.org/package/grunt-ng-annotate) para tarefas de build automatizadas. Injete `/* @ngInject */` antes de qualquer função que tenha dependências. - *Why?*: ng-annotate will catch most dependencies, but it sometimes requires hints using the `/* @ngInject */` syntax. + *Por que?*: ng-annotate vai capturar todas as dependências, mas as vezes requer dicas utilizando a sintaxe `/* @ngInject */` . - The following code is an example of a gulp task using ngAnnotate + O código abaixo é um exemplo de uma task Gulp utilizando ngAnnotate ```javascript gulp.task('js', ['jshint'], function() { @@ -1570,11 +1570,11 @@ ou *Minificação e Anotação* ### decorators - - Use a [decorator](https://docs.angularjs.org/api/auto/service/$provide#decorator), at config time using the [`$provide`](https://docs.angularjs.org/api/auto/service/$provide) service, on the [`$exceptionHandler`](https://docs.angularjs.org/api/ng/service/$exceptionHandler) service to perform custom actions when exceptions occur. + - Utilize um [decorator](https://docs.angularjs.org/api/auto/service/$provide#decorator), no seu configutilizando o serviço [`$provide`](https://docs.angularjs.org/api/auto/service/$provide) , no serviço [`$exceptionHandler`](https://docs.angularjs.org/api/ng/service/$exceptionHandler) para realizar ações customizadas quando um erro ocorrer. - *Why?*: Provides a consistent way to handle uncaught AngularJS exceptions for development-time or run-time. + *Por que?*: Fornece um caminho consistente para manipular erros não tratados pelo AngularJS em tempo de desenvolvimento ou run-time. - Note: Another option is to override the service instead of using a decorator. This is a fine option, but if you want to keep the default behavior and extend it a decorator is recommended. + Nota: Outra opção é sobrescrever o serviço ao invés de utilizar um decorator. Esta é uma boa opção, mas se você quer manter o comportamento padrão e estender o decorator é recomendado. ```javascript /* recommended */ @@ -1610,9 +1610,9 @@ ou *Minificação e Anotação* ### Exception Catchers - - Create a factory that exposes an interface to catch and gracefully handle exceptions. + - Criar um factory que expôe uma interface para capturar excessões. - *Why?*: Provides a consistent way to catch exceptions that may be thrown in your code (e.g. during XHR calls or promise failures). + *Por que?*: Provides a consistent way to catch exceptions that may be thrown in your code (e.g. during XHR calls or promise failures). Note: The exception catcher is good for catching and reacting to specific exceptions from calls that you know may throw one. For example, when making an XHR call to retrieve data from a remote web service and you want to catch any exceptions from that service and react uniquely. From 4e2c522de64f056baafcbfa59413308fd2047f42 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=B5=B5=E5=8F=AF?= Date: Sun, 21 Dec 2014 15:33:56 +0800 Subject: [PATCH 080/567] latest version --- i18n/zh-CN.md | 50 ++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 38 insertions(+), 12 deletions(-) diff --git a/i18n/zh-CN.md b/i18n/zh-CN.md index cd172046..10430d39 100644 --- a/i18n/zh-CN.md +++ b/i18n/zh-CN.md @@ -368,11 +368,20 @@ ``` - 注:在controller中用`controller as`创建了一个watch时,可以用下面的语法监测`vm.*`的成员。(创建watch时要谨慎,因为它会增加更多的负载) + ```html + + ``` + ```javascript - $scope.$watch('vm.title', function(current, original) { - $log.info('vm.title was %s', original); - $log.info('vm.title is now %s', current); - }); + function SomeController($scope, $log) { + var vm = this; + vm.title = 'Some Title'; + + $scope.$watch('vm.title', function(current, original) { + $log.info('vm.title was %s', original); + $log.info('vm.title is now %s', current); + }); + } ``` @@ -542,7 +551,7 @@ ``` ###推迟Controller中的逻辑 -###### [Style [Y035](#style-y036)] +###### [Style [Y035](#style-y035)] - 通过委派到service和factory中来推迟controller中的逻辑。 @@ -554,30 +563,47 @@ ```javascript /* avoid */ - function Order ($http, $q) { + function Order($http, $q, config, userInfo) { var vm = this; vm.checkCredit = checkCredit; + vm.isCreditOk; vm.total = 0; function checkCredit () { - var orderTotal = vm.total; - return $http.get('api/creditcheck').then(function(data) { - var remaining = data.remaining; - return $q.when(!!(remaining > orderTotal)); - }); + var settings = {}; + // Get the credit service base URL from config + // Set credit service required headers + // Prepare URL query string or data object with request data + // Add user-identifying info so service gets the right credit limit for this user. + // Use JSONP for this browser if it doesn't support CORS + return $http.get(settings) + .then(function(data) { + // Unpack JSON data in the response object + // to find maxRemainingAmount + vm.isCreditOk = vm.total <= maxRemainingAmount + }) + .catch(function(error) { + // Interpret error + // Cope w/ timeout? retry? try alternate service? + // Re-reject with appropriate error for a user to see + }); }; } ``` ```javascript + /* recommended */ function Order (creditService) { var vm = this; vm.checkCredit = checkCredit; + vm.isCreditOk; vm.total = 0; function checkCredit () { - return creditService.check(); + return creditService.isOrderTotalOk(vm.total) + .then(function(isOk) { vm.isCreditOk = isOk; }) + .catch(showServiceError); }; } ``` From e7f3a5779de9472eac99d77594ceb63fa2e92eb4 Mon Sep 17 00:00:00 2001 From: Alexander Afanasiev Date: Tue, 23 Dec 2014 01:12:27 -0500 Subject: [PATCH 081/567] Fixing minor typo and adding link to sinonjs --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index c497013e..cf83785b 100644 --- a/README.md +++ b/README.md @@ -2166,7 +2166,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see ### Configuration ###### [Style [Y170](#style-y170)] - - Inject code into [module configuration](https://docs.angularjs.org/guide/module#module-loading-dependencies) that must be configured before running the angular app. Ideal candidaes include providers and constants. + - Inject code into [module configuration](https://docs.angularjs.org/guide/module#module-loading-dependencies) that must be configured before running the angular app. Ideal candidates include providers and constants. *Why?*: This makes it easier to have a less places for configuration. @@ -2290,7 +2290,7 @@ Unit testing helps maintain clean code, as such I included some of my recommenda ### Stubbing and Spying ###### [Style [Y193](#style-y193)] - - Use Sinon for stubbing and spying. + - Use [Sinon](http://sinonjs.org/) for stubbing and spying. *Why?*: Sinon works well with both Jasmine and Mocha and extends the stubbing and spying features they offer. From 94b67c26436289a53e3892e61886815d37fd7a65 Mon Sep 17 00:00:00 2001 From: angelochiello Date: Tue, 23 Dec 2014 10:51:22 +0100 Subject: [PATCH 082/567] [it-IT] PR #193 Updated as PR #193: Fixing minor typo and adding link to sinonjs --- i18n/it-IT.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/i18n/it-IT.md b/i18n/it-IT.md index e3f52dde..4d45da1d 100644 --- a/i18n/it-IT.md +++ b/i18n/it-IT.md @@ -2301,7 +2301,7 @@ Gli unit test aiutano a mantenere il codice più chiaro, perciò ho incluso alcu ### Stubbing e Spying ###### [Stile [Y193](#stile-y193)] - - Usa Sinon per lo stubbing e spying. + - Usa [Sinon](http://sinonjs.org) per lo stubbing e spying. *Perché?*: Sinon lavora bene sia con Jasmine che Mocha ed estende le funzionalità di stubbing e spying che questi offrono. From ddacc66e7a25c6eafbc6409b2e8f00a09d572e14 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=B5=B5=E5=8F=AF?= Date: Fri, 26 Dec 2014 10:53:05 +0800 Subject: [PATCH 083/567] merge #195 --- i18n/zh-CN.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/i18n/zh-CN.md b/i18n/zh-CN.md index 10430d39..982daef8 100644 --- a/i18n/zh-CN.md +++ b/i18n/zh-CN.md @@ -2272,7 +2272,7 @@ ###Stubbing和Spying ###### [Style [Y193](#style-y193)] - - 用Sinon。 + - 用[Sinon](http://sinonjs.org/)。 *为什么?*:Sinon可以和Jasmine和Mocha合作良好,并且可以扩展它们提供的stubbing和spying。 From cfd9721314cca37ddbec4dc947756c6172e64c46 Mon Sep 17 00:00:00 2001 From: John Papa Date: Sat, 27 Dec 2014 09:32:35 -0500 Subject: [PATCH 084/567] added an example of a named reoute resolve function --- README.md | 39 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 38 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 1c75d619..f050da90 100644 --- a/README.md +++ b/README.md @@ -1272,7 +1272,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see ### Route Resolve Promises ###### [Style [Y081](#style-y081)] - - When a controller depends on a promise to be resolved, resolve those dependencies in the `$routeProvider` before the controller logic is executed. If you need to conditionally cancel a route before the controller is activated, use a route resolver. + - When a controller depends on a promise to be resolved before the controller is activated, resolve those dependencies in the `$routeProvider` before the controller logic is executed. If you need to conditionally cancel a route before the controller is activated, use a route resolver. *Why?*: A controller may require data before it loads. That data may come from a promise via a custom factory or [$http](https://docs.angularjs.org/api/ng/service/$http). Using a [route resolve](https://docs.angularjs.org/api/ngRoute/provider/$routeProvider) allows the promise to resolve before the controller logic executes, so it might take action based on that data from the promise. @@ -1327,6 +1327,43 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see } ``` + Note: The example below shows the route resolve function becomes a named function, which is easier to debug and easier to handle dependency injection. + + ```javascript + /* even better */ + + // route-config.js + angular + .module('app') + .config(config); + + function config($routeProvider) { + $routeProvider + .when('/avengers', { + templateUrl: 'avengers.html', + controller: 'Avengers', + controllerAs: 'vm', + resolve: { + moviesPrepService: moviesPrepService + } + }); + } + + function(movieService) { + return movieService.getMovies(); + } + + // avengers.js + angular + .module('app') + .controller('Avengers', Avengers); + + Avengers.$inject = ['moviesPrepService']; + function Avengers(moviesPrepService) { + var vm = this; + vm.movies = moviesPrepService.movies; + } + ``` Note: The code example's dependency on `movieService` is not minification safe on its own. For details on how to make this code minification safe, see the sections on [dependency injection](#manual-annotating-for-dependency-injection) and on [minification and annotation](#minification-and-annotation). **[Back to top](#table-of-contents)** From 249337fc1422c5b5491a82f0679be76c679f259f Mon Sep 17 00:00:00 2001 From: John Papa Date: Sat, 27 Dec 2014 09:33:43 -0500 Subject: [PATCH 085/567] added an example of a named reoute resolve function --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index f050da90..b4aaecbf 100644 --- a/README.md +++ b/README.md @@ -1327,7 +1327,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see } ``` - Note: The example below shows the route resolve function becomes a named function, which is easier to debug and easier to handle dependency injection. + Note: The example below shows the route resolve points to a named function, which is easier to debug and easier to handle dependency injection. ```javascript /* even better */ From 8b0fe57214b4e4b3d744897c1ad1267544f2eec6 Mon Sep 17 00:00:00 2001 From: John Papa Date: Sat, 27 Dec 2014 09:36:10 -0500 Subject: [PATCH 086/567] Oops! named the route resolve function --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index b4aaecbf..a89773ff 100644 --- a/README.md +++ b/README.md @@ -1349,7 +1349,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see }); } - function(movieService) { + function moviePrepService(movieService) { return movieService.getMovies(); } From c7b23b1a2392022a74e608f5294763809c670250 Mon Sep 17 00:00:00 2001 From: John Papa Date: Sat, 27 Dec 2014 10:04:34 -0500 Subject: [PATCH 087/567] added more details to the route resolver and controller activate techniques --- README.md | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index a89773ff..fbec8e1c 100644 --- a/README.md +++ b/README.md @@ -1233,7 +1233,9 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see *Why?*: Placing start-up logic in a consistent place in the controller makes it easier to locate, more consistent to test, and helps avoid spreading out the activation logic across the controller. - Note: If you need to conditionally cancel the route before you start use the controller, use a route resolve instead. + *Why?: The controller `activate` makes it convenient to re-use the logic for a refresh for the controller/View, keeps the logic together, gets the user to the View faster, makes animations easy on the `ng-view` or `ui-view`, and feels snappier to the user. + + Note: If you need to conditionally cancel the route before you start use the controller, use a [route resolve](#style-y081) instead. ```javascript /* avoid */ @@ -1274,8 +1276,14 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see - When a controller depends on a promise to be resolved before the controller is activated, resolve those dependencies in the `$routeProvider` before the controller logic is executed. If you need to conditionally cancel a route before the controller is activated, use a route resolver. + - Use a route resolve when you want to decide to cancel the route before ever transitioning to the View. + *Why?*: A controller may require data before it loads. That data may come from a promise via a custom factory or [$http](https://docs.angularjs.org/api/ng/service/$http). Using a [route resolve](https://docs.angularjs.org/api/ngRoute/provider/$routeProvider) allows the promise to resolve before the controller logic executes, so it might take action based on that data from the promise. + *Why?: The code executes after the route and in the controller’s activate function. The View starts to load right away. Data binding kicks in when the activate promise resolves. A “busy” animation can be shown during the view transition (via ng-view or ui-view) + + Note: The code executes before the route via a promise. Rejecting the promise cancels the route. Resolve makes the new view wait for the route to resolve. A “busy” animation can be shown before the resolve and through the view transition. If you want to get to the View faster and do not require a checkpoint to decide if you can get to the View, consider the [controller `activate` technique](#style-y080) instead. + ```javascript /* avoid */ angular From c814fcfa98c36e8296e42cb8c53a935aa898bb99 Mon Sep 17 00:00:00 2001 From: John Papa Date: Sat, 27 Dec 2014 10:05:16 -0500 Subject: [PATCH 088/567] formatting of note --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index fbec8e1c..1b0b77de 100644 --- a/README.md +++ b/README.md @@ -1235,7 +1235,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see *Why?: The controller `activate` makes it convenient to re-use the logic for a refresh for the controller/View, keeps the logic together, gets the user to the View faster, makes animations easy on the `ng-view` or `ui-view`, and feels snappier to the user. - Note: If you need to conditionally cancel the route before you start use the controller, use a [route resolve](#style-y081) instead. + Note: If you need to conditionally cancel the route before you start use the controller, use a [route resolve](#style-y081) instead. ```javascript /* avoid */ From 1de1b1c8e2aeaf5cedea1e5497ae80e12212d94f Mon Sep 17 00:00:00 2001 From: John Papa Date: Sat, 27 Dec 2014 10:05:53 -0500 Subject: [PATCH 089/567] unformatting of note --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 1b0b77de..fbec8e1c 100644 --- a/README.md +++ b/README.md @@ -1235,7 +1235,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see *Why?: The controller `activate` makes it convenient to re-use the logic for a refresh for the controller/View, keeps the logic together, gets the user to the View faster, makes animations easy on the `ng-view` or `ui-view`, and feels snappier to the user. - Note: If you need to conditionally cancel the route before you start use the controller, use a [route resolve](#style-y081) instead. + Note: If you need to conditionally cancel the route before you start use the controller, use a [route resolve](#style-y081) instead. ```javascript /* avoid */ From c777c21cade5316f7fd120485b39397891089344 Mon Sep 17 00:00:00 2001 From: John Papa Date: Sat, 27 Dec 2014 10:06:55 -0500 Subject: [PATCH 090/567] formatted WHY --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index fbec8e1c..2d7f663d 100644 --- a/README.md +++ b/README.md @@ -1233,7 +1233,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see *Why?*: Placing start-up logic in a consistent place in the controller makes it easier to locate, more consistent to test, and helps avoid spreading out the activation logic across the controller. - *Why?: The controller `activate` makes it convenient to re-use the logic for a refresh for the controller/View, keeps the logic together, gets the user to the View faster, makes animations easy on the `ng-view` or `ui-view`, and feels snappier to the user. + *Why?*: The controller `activate` makes it convenient to re-use the logic for a refresh for the controller/View, keeps the logic together, gets the user to the View faster, makes animations easy on the `ng-view` or `ui-view`, and feels snappier to the user. Note: If you need to conditionally cancel the route before you start use the controller, use a [route resolve](#style-y081) instead. @@ -1280,7 +1280,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see *Why?*: A controller may require data before it loads. That data may come from a promise via a custom factory or [$http](https://docs.angularjs.org/api/ng/service/$http). Using a [route resolve](https://docs.angularjs.org/api/ngRoute/provider/$routeProvider) allows the promise to resolve before the controller logic executes, so it might take action based on that data from the promise. - *Why?: The code executes after the route and in the controller’s activate function. The View starts to load right away. Data binding kicks in when the activate promise resolves. A “busy” animation can be shown during the view transition (via ng-view or ui-view) + *Why?*: The code executes after the route and in the controller’s activate function. The View starts to load right away. Data binding kicks in when the activate promise resolves. A “busy” animation can be shown during the view transition (via ng-view or ui-view) Note: The code executes before the route via a promise. Rejecting the promise cancels the route. Resolve makes the new view wait for the route to resolve. A “busy” animation can be shown before the resolve and through the view transition. If you want to get to the View faster and do not require a checkpoint to decide if you can get to the View, consider the [controller `activate` technique](#style-y080) instead. From 10655d2a257dcb1916750dc35a66ae2c7cdec4c4 Mon Sep 17 00:00:00 2001 From: angelochiello Date: Sun, 28 Dec 2014 16:11:09 +0100 Subject: [PATCH 091/567] PR #202 Updated as PR #202 "added an example of a named reoute resolve function" --- i18n/it-IT.md | 39 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 38 insertions(+), 1 deletion(-) diff --git a/i18n/it-IT.md b/i18n/it-IT.md index 4d45da1d..855d7c85 100644 --- a/i18n/it-IT.md +++ b/i18n/it-IT.md @@ -1294,7 +1294,7 @@ Nonostante questa guida spieghi i *cosa*, *come* e *perché*, trovo che sia di a ### Promesse risolte nel route ###### [Stile [Y081](#stile-y081)] - - Quando un controller dipende dalla dal fatto che una promessa sia risolta risolvi queste dipendenze nel `$routeProvider` prima che la logica del controller sia eseguita. Se hai bisogno di annullare condizionalmente una route prima che il controller sia attivato, usa un resolver della route. + - Quando un controller dipende dal fatto che una promessa sia risolta prima che il controller sia attivato, risolvi queste dipendenze nel `$routeProvider` prima che la logica del controller sia eseguita. Se hai bisogno di annullare condizionalmente una route prima che il controller sia attivato, usa un resolver della route. *Perché?*: Un controller può richiedere dei dati prima che si carichi. Quei dati potrebbero venire da una promessa di una factory su misura oppure [$http](https://docs.angularjs.org/api/ng/service/$http). Usando un [resolver della route](https://docs.angularjs.org/api/ngRoute/provider/$routeProvider) acconsenti che la promessa sia risolta prima che la logica del controller sia eseguita, così da poter prendere decisioni basandosi sui dati provenienti dalla promessa. @@ -1349,7 +1349,44 @@ Nonostante questa guida spieghi i *cosa*, *come* e *perché*, trovo che sia di a vm.movies = moviesPrepService.movies; } ``` + + Note: L'esempio sotto mostra il punto di risoluzione della route in una funzione con il nome per cui è più semplice da fare il debug e più semplice da gestire nella iniezione delle dependenze. + + ```javascript + /* even better */ + + // route-config.js + angular + .module('app') + .config(config); + + function config($routeProvider) { + $routeProvider + .when('/avengers', { + templateUrl: 'avengers.html', + controller: 'Avengers', + controllerAs: 'vm', + resolve: { + moviesPrepService: moviesPrepService + } + }); + } + + function moviePrepService(movieService) { + return movieService.getMovies(); + } + + // avengers.js + angular + .module('app') + .controller('Avengers', Avengers); + Avengers.$inject = ['moviesPrepService']; + function Avengers(moviesPrepService) { + var vm = this; + vm.movies = moviesPrepService.movies; + } + ``` Nota: La dipendenza del codice di esempio da `movieService` non è a prova di minificazione in se stessa. Per i dettagli su come rendere questo codice a prova di minificazione, vedi la sezione sulla [dependency injection](#manual-annotating-for-dependency-injection) e sulla [minificazione e annotazione](#minification-and-annotation). **[Torna all'inizio](#tavola-dei-contenuti)** From ad485485696576c167e9b866bc6516bb1fbb408c Mon Sep 17 00:00:00 2001 From: angelochiello Date: Sun, 28 Dec 2014 16:43:26 +0100 Subject: [PATCH 092/567] [it-IT] PR #204 Updated as PR #204 "added more details to the route resolver and controller activate techniques" --- i18n/it-IT.md | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/i18n/it-IT.md b/i18n/it-IT.md index 855d7c85..27b17db2 100644 --- a/i18n/it-IT.md +++ b/i18n/it-IT.md @@ -1255,7 +1255,9 @@ Nonostante questa guida spieghi i *cosa*, *come* e *perché*, trovo che sia di a *Perché?*: Porre la logica di start-up in una posizione consistente nel controller la rende semplice da localizzare, più consistente da testare e aiuta a prevenire la diffusione di logica su tutto il controller. - Nota: Se hai necessità di annullare condizionalmente il route prima di iniziare ad usare il controller, usa piuttosto una risoluzione nella route. + *Perché?*: La funzione `activate` del controller rende il riuso della logica adatto in caso di un refresh del controller/view, tiene la logica assieme, porta l'utente alla view più rapidamente, rende le animazini più facili su `ng-view` o `ui-view`e da la sensazione all'utente di istantaneità. + + Nota: Se hai necessità di annullare condizionalmente il route prima di iniziare ad usare il controller, usa piuttosto una [risoluzione nella route](#stile-y081). ```javascript /* evitare */ @@ -1296,8 +1298,14 @@ Nonostante questa guida spieghi i *cosa*, *come* e *perché*, trovo che sia di a - Quando un controller dipende dal fatto che una promessa sia risolta prima che il controller sia attivato, risolvi queste dipendenze nel `$routeProvider` prima che la logica del controller sia eseguita. Se hai bisogno di annullare condizionalmente una route prima che il controller sia attivato, usa un resolver della route. + - Usa la risoluzione della route quando decidi di annullare la route prima ancora di iniziara la transizione alla view. + *Perché?*: Un controller può richiedere dei dati prima che si carichi. Quei dati potrebbero venire da una promessa di una factory su misura oppure [$http](https://docs.angularjs.org/api/ng/service/$http). Usando un [resolver della route](https://docs.angularjs.org/api/ngRoute/provider/$routeProvider) acconsenti che la promessa sia risolta prima che la logica del controller sia eseguita, così da poter prendere decisioni basandosi sui dati provenienti dalla promessa. + *Perché?*: Il codice è eseguito dopo la route e nella funzione di attivazione del controller. La view inizia il caricamento immediatamente. Il data binding è effettivo quando le promesse nella funzine di attivazione sono risolte. Una animazione di “attendere” può essere mostrata durante la transizione alla view (via ng-view o ui-view). + + Nota: Il codice è eseguito prima il route per mezo di una promessa. Il rifiuto della promessa annulla la route. "resolve" fa attendere la view mentre viene risolta. Una animazione “attendere” può essere mostrata prima della risoluzione e durante tutta la transizione alla vista. Se desideri di arrivare alla view più in fretta e non hai bisogno di un punto di controllo per decidere se vuoi navigare alla view, considera piuttosto [Promesse di attivazione di un Controller](#stile-y080). + ```javascript /* evitare */ angular @@ -1353,7 +1361,7 @@ Nonostante questa guida spieghi i *cosa*, *come* e *perché*, trovo che sia di a Note: L'esempio sotto mostra il punto di risoluzione della route in una funzione con il nome per cui è più semplice da fare il debug e più semplice da gestire nella iniezione delle dependenze. ```javascript - /* even better */ + /* meglio */ // route-config.js angular From 3c5c95f6eed5df22458d8220575a2bb2108c5aa3 Mon Sep 17 00:00:00 2001 From: Aleksandar Bogatinov Date: Mon, 29 Dec 2014 17:43:21 +0100 Subject: [PATCH 093/567] Updated to latest version --- i18n/mk-MK.md | 50 ++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 48 insertions(+), 2 deletions(-) diff --git a/i18n/mk-MK.md b/i18n/mk-MK.md index c084a03d..5e993b8e 100644 --- a/i18n/mk-MK.md +++ b/i18n/mk-MK.md @@ -1219,7 +1219,9 @@ *Зошто?*: Поставување на почетна логика во согласно место во контролерот е полесно за лоцирање, полесно за тестирање и го оневозможува распределувањето на почетната логика низ целиот контролер. - Забелешка: Доколку условно треба да ја спречите патеката пред употреба на контролерот, тогаш решете ја патеката. + *Зошто?*: Функцијата `activate` во контролерот е погодна за повторно да се искористи логиката за освежување на контролер/Преглед, ја држи логиката на едно место, побрзо го прикажува Прегледот, ги олеснува анимациите на `ng-view` или `ui-view` и е елегантно за корисникот. + + Забелешка: Доколку условно требате да го прекинете решавањето на патеката пред да го користите контролерот, тогаш разгледајте го [route resolve](#style-y081). ```javascript /* избегнувајте */ @@ -1257,10 +1259,16 @@ ### Решавање на патеката преку Promises ###### [Style [Y081](#style-Y081)] - - Кога контролер зависи на решавање на promise, решете ги сите зависности во `$routeProvider` пред логиката на контролерот да биде извршена. Ако треба опционално да ја спречите патеката пред да биде контролерот активиран, решете ја патеката. + - Кога контролер зависи на решавање на promise, решете ги сите зависности во `$routeProvider` пред контролерот да биде активиран. Ако треба опционално да ја спречите патеката пред да биде контролерот активиран, решете ја патеката. + + - Употребете решавање на патеката кога сакате да ја прекинете патеката пред да преминете на Прегледот. *Зошто?*: Контролерот може да зависи од податоци пред да се изврши. Овој податок може да дојде преку promise од сопствена фабрика или [$http](https://docs.angularjs.org/api/ng/service/$http). Со употреба на [route resolve](https://docs.angularjs.org/api/ngRoute/provider/$routeProvider) ќе овозможиме promise да се реши пред логиката на контролерот да биде извршена, така што може да зависи од акција во податокот. + *Зошто?*: Кодот се извршува после патеката и во activate функцијата во контролерот. Прегледот започнува одма да се вчитува. Поврзување со податоците се вклучува кога ќе се реши promise-от во activate функцијата. "Зафатена" анимација ќе се појави додека преминувате на Прегледот. (со ng-view или ui-view) + + Забелешка: Кодот се извршува пред патеката со promise. Со одбивање на promise се спречува патеката. Со решавање, се чека на новиот преглед да заврши. "Зафатена" анимација може да се прикаже пред да се реши патеката и во преминот на Прегледот. Доколку сакате побрзо да стигнете до Прегледот, а не ви е потребен checkpoint доколку сакате да стигнете до Прегледот, тогаш разгледајте го [controller `activate` technique](#style-y080). + ```javascript /* избегнувајте */ angular @@ -1312,6 +1320,44 @@ } ``` + Забелешка: Примерот подоле покажува како решавање на патеката покажува кон именувана функција, која е полесна за дебагирање и полесно справување со вклучување на зависностите. + + ```javascript + /* уште подобро */ + + // route-config.js + angular + .module('app') + .config(config); + + function config($routeProvider) { + $routeProvider + .when('/avengers', { + templateUrl: 'avengers.html', + controller: 'Avengers', + controllerAs: 'vm', + resolve: { + moviesPrepService: moviesPrepService + } + }); + } + + function moviePrepService(movieService) { + return movieService.getMovies(); + } + + // avengers.js + angular + .module('app') + .controller('Avengers', Avengers); + + Avengers.$inject = ['moviesPrepService']; + function Avengers(moviesPrepService) { + var vm = this; + vm.movies = moviesPrepService.movies; + } + ``` + Забелешка: Примерот на `movieService` не е безбеден за минификација. За детали како да го направите безбеден за минификација, прегледајте ги секциите за [dependency injection](#manual-annotating-for-dependency-injection) и [minification and annotation](#minification-and-annotation). **[Назад кон содржината](#table-of-contents)** From b390a7e5d510679e293293c1409e342cf41e9e5b Mon Sep 17 00:00:00 2001 From: John Papa Date: Thu, 1 Jan 2015 09:05:37 -0500 Subject: [PATCH 094/567] added constants separation. closes #191 --- README.md | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/README.md b/README.md index 2d7f663d..ad67dab4 100644 --- a/README.md +++ b/README.md @@ -2538,6 +2538,31 @@ Unit testing helps maintain clean code, as such I included some of my recommenda .constant('moment', moment); })(); ``` + +###### [Style [Y241](#style-y241)] + + - Use constants for values that do not change and do not come from another service. When constants are used only for a module that may be reused in multiple applications, place constants in a file per module named after the module. Until this is required, keep constants in the main module in a `constants.js` file. + + *Why?*: A value that may change, even infrequently, should be retrieved from a service so you do not have to change the source code. For example, a url for a data service could be placed in a constants but a better place would be to load it from a web service. + + *Why?*: Constants can be injected into any angular component, including providers. + + *Why?*: When an application is separated into modules that may be reused in other applications, each standlone module should be able to operation on its own including any dependent constants. + + ```javascript + // Constants used by the entire app + angular + .module('app.core') + .constant('moment', moment); + + // Constants used only by the sales module + angular + .module('app.sales') + .constant('events', { + ORDER_CREATED: 'event_order_created', + INVENTORY_DEPLETED: 'event_inventory_depleted' + }); + ``` **[Back to top](#table-of-contents)** From 050e712685d0472ae25e492989e0d96cd00d5602 Mon Sep 17 00:00:00 2001 From: John Papa Date: Thu, 1 Jan 2015 12:02:46 -0500 Subject: [PATCH 095/567] fixed typo --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index ad67dab4..0381d6b6 100644 --- a/README.md +++ b/README.md @@ -1099,7 +1099,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see ### Restrict to Elements and Attributes ###### [Style [Y074](#style-y074)] - - When creating a directive that makes sense as a standalone element, allow restrict `E` (custom element) and optionally restrict `A` (custom attribute). Generally, if it could be its own control, `E` is appropriate. General guideline is allow `EA` but lean towards implementing as an element when its standalone and as an attribute when it enhances its existing DOM element. + - When creating a directive that makes sense as a stand-alone element, allow restrict `E` (custom element) and optionally restrict `A` (custom attribute). Generally, if it could be its own control, `E` is appropriate. General guideline is allow `EA` but lean towards implementing as an element when its stand-alone and as an attribute when it enhances its existing DOM element. *Why?*: It makes sense. @@ -2547,7 +2547,7 @@ Unit testing helps maintain clean code, as such I included some of my recommenda *Why?*: Constants can be injected into any angular component, including providers. - *Why?*: When an application is separated into modules that may be reused in other applications, each standlone module should be able to operation on its own including any dependent constants. + *Why?*: When an application is separated into modules that may be reused in other applications, each stand-alone module should be able to operate on its own including any dependent constants. ```javascript // Constants used by the entire app From 7738b752cac3fa96ff393227117390878aa22139 Mon Sep 17 00:00:00 2001 From: angelochiello Date: Fri, 2 Jan 2015 11:02:18 +0100 Subject: [PATCH 096/567] [it-IT] PR #209 Updated as PR #209: "added constants separation. closes #191" --- i18n/it-IT.md | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/i18n/it-IT.md b/i18n/it-IT.md index 27b17db2..6f7fe083 100644 --- a/i18n/it-IT.md +++ b/i18n/it-IT.md @@ -2567,6 +2567,31 @@ Gli unit test aiutano a mantenere il codice più chiaro, perciò ho incluso alcu .constant('moment', moment); })(); ``` + +###### [Stile [Y241](#stile-y241)] + + - Usa constanti per i valori che non cambiano e che non provengono da un altro servizio. Quando le costanti sono utilizzate sonlo per un modulo che potrebbe essere riutilizzato in più applicazioni, metti le costanti in un file per modulo e nominalo come il modulo. Fintanto che tale necesstià non si presenti, tieni le constanti nel modulo principale in un file `constants.js`. + + *Perché*: Un valore che potrebbe variare, anche non di frequente, dovrebbe essere recuperato da un servizio così che non sia necessario cambiare il sorgente. Per esempio, una URL per un servizio di accesso ai dati può essere messo in una costante ma un miglior posizionamento sarebbe quello di caricarlo da un web service. + + *Perché?*: Le costanti possono essere iniettate in un componente di angular, provider inclusi. + + *Perché?*: Quando una applicazione è separata in modulo che potrebbero essere usati in altre applicazioni, ogni modulo a se stante dovrbbe essre in grado di funzionare da solo ivi incluse ogni costante da cui dipende. + + ```javascript + // Costanti usate dall'intera applicazione + angular + .module('app.core') + .constant('moment', moment); + + // Costanti usate solo dal modulo delle vendite + angular + .module('app.sales') + .constant('events', { + ORDER_CREATED: 'event_order_created', + INVENTORY_DEPLETED: 'event_inventory_depleted' + }); + ``` **[Torna all'inizio](#tavola-dei-contenuti)** From f3f3c260b20be5cafdbaa6d3789cd122afacb0f8 Mon Sep 17 00:00:00 2001 From: angelochiello Date: Fri, 2 Jan 2015 11:07:46 +0100 Subject: [PATCH 097/567] [it-IT] Typos after PR #209 Correction of typos after PR #209 update. --- i18n/it-IT.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/i18n/it-IT.md b/i18n/it-IT.md index 6f7fe083..b698279e 100644 --- a/i18n/it-IT.md +++ b/i18n/it-IT.md @@ -2570,13 +2570,13 @@ Gli unit test aiutano a mantenere il codice più chiaro, perciò ho incluso alcu ###### [Stile [Y241](#stile-y241)] - - Usa constanti per i valori che non cambiano e che non provengono da un altro servizio. Quando le costanti sono utilizzate sonlo per un modulo che potrebbe essere riutilizzato in più applicazioni, metti le costanti in un file per modulo e nominalo come il modulo. Fintanto che tale necesstià non si presenti, tieni le constanti nel modulo principale in un file `constants.js`. + - Usa constanti per i valori che non cambiano e che non provengono da un altro servizio. Quando le costanti sono utilizzate solo per un modulo che potrebbe essere riutilizzato in più applicazioni, metti le costanti in un file per modulo e nominalo come il modulo. Fintanto che tale necesstià non si presenti, tieni le constanti nel modulo principale in un file `constants.js`. *Perché*: Un valore che potrebbe variare, anche non di frequente, dovrebbe essere recuperato da un servizio così che non sia necessario cambiare il sorgente. Per esempio, una URL per un servizio di accesso ai dati può essere messo in una costante ma un miglior posizionamento sarebbe quello di caricarlo da un web service. *Perché?*: Le costanti possono essere iniettate in un componente di angular, provider inclusi. - *Perché?*: Quando una applicazione è separata in modulo che potrebbero essere usati in altre applicazioni, ogni modulo a se stante dovrbbe essre in grado di funzionare da solo ivi incluse ogni costante da cui dipende. + *Perché?*: Quando una applicazione è separata in modulo che potrebbero essere usati in altre applicazioni, ogni modulo a se stante dovrebbe essere in grado di funzionare da solo ivi incluse ogni costante da cui dipende. ```javascript // Costanti usate dall'intera applicazione From 7d138f8447fb2eac37b3397f861d99a95eb0a439 Mon Sep 17 00:00:00 2001 From: Aleksandar Bogatinov Date: Fri, 2 Jan 2015 17:37:33 +0100 Subject: [PATCH 098/567] Updated \w constants change --- i18n/mk-MK.md | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/i18n/mk-MK.md b/i18n/mk-MK.md index 5e993b8e..20a94cbb 100644 --- a/i18n/mk-MK.md +++ b/i18n/mk-MK.md @@ -2476,6 +2476,30 @@ })(); ``` +###### [Style [Y241](#style-Y241)] + - Употребете константи за вредности кои не се променуваат и не доаѓаат од друг сервис. Кога константи се употребени само за модул кој може повторно да биде искористен во повеќе апликации, потавете ги константите во една датотека за модул именувана како модулот. Се додека ова не е потребно, нека останат константите во главниот модул, во `constants.js` датотеката. + + *Зошто?*: Вредност која може да се промени, дури и поретко, треба да биде превземена од сервис со цел да не го менувате изворниот код. На пример, линк до податочниот сервис може да биде поставен во константите, но подобро е да се превземе од веб сервис. + + *Зошто?*: Константи можат да бидат вметнати во било која ангулар компонента, вклучувајќи ги провајдерите. + + *Зошто?*: Кога апликацијата е поделена во модули кои можат да бидат повторно искористени во други апликации, секој поединечен модул треба да се извршува самостојно вклучувајќи било какви зависни константи. + +```javascript + // Константи употребени во целата апликација +angular + .module('app.core') + .constant('moment', moment); + +// Константи употребени само во sales модулот +angular + .module('app.sales') + .constant('events', { + ORDER_CREATED: 'event_order_created', + INVENTORY_DEPLETED: 'event_inventory_depleted' + }); +``` + **[Назад кон содржината](#table-of-contents)** ## File Templates and Snippets From cac98ff4a4a6f88c1d662ee1bad23eb23d5e077c Mon Sep 17 00:00:00 2001 From: Vinicius Sabadim Fernandes Date: Mon, 5 Jan 2015 12:03:24 -0200 Subject: [PATCH 099/567] Translate for the topic 'Exception handling' (PT-BR) --- i18n/PT-BR.md | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/i18n/PT-BR.md b/i18n/PT-BR.md index 0982811e..befc0d49 100644 --- a/i18n/PT-BR.md +++ b/i18n/PT-BR.md @@ -1567,17 +1567,19 @@ ou *Minificação e Anotação* **[⬆ De volta ao topo ⬆](#tabela-de-conte%C3%BAdo)** ## Exception Handling +ou *Tratamento de exceção* ### decorators +ou *decoradores* - - Utilize um [decorator](https://docs.angularjs.org/api/auto/service/$provide#decorator), no seu configutilizando o serviço [`$provide`](https://docs.angularjs.org/api/auto/service/$provide) , no serviço [`$exceptionHandler`](https://docs.angularjs.org/api/ng/service/$exceptionHandler) para realizar ações customizadas quando um erro ocorrer. + - Utilize um [decorator](https://docs.angularjs.org/api/auto/service/$provide#decorator), no seu config utilizando o serviço [`$provide`](https://docs.angularjs.org/api/auto/service/$provide), no serviço [`$exceptionHandler`](https://docs.angularjs.org/api/ng/service/$exceptionHandler) para realizar ações customizadas quando um erro ocorrer. - *Por que?*: Fornece um caminho consistente para manipular erros não tratados pelo AngularJS em tempo de desenvolvimento ou run-time. + **Por que?**: Fornece um caminho consistente para manipular erros não tratados pelo AngularJS em tempo de desenvolvimento ou execução (run-time). - Nota: Outra opção é sobrescrever o serviço ao invés de utilizar um decorator. Esta é uma boa opção, mas se você quer manter o comportamento padrão e estender o decorator é recomendado. + Nota: Outra opção é sobrescrever o serviço ao invés de utilizar um decorator. Esta é uma boa opção, mas se você quer manter o comportamento padrão e estender, o decorator é recomendado. ```javascript - /* recommended */ + /* recomendado */ angular .module('blocks.exception') .config(exceptionConfig); @@ -1598,9 +1600,9 @@ ou *Minificação e Anotação* cause: cause }; /** - * Could add the error to a service's collection, - * add errors to $rootScope, log errors to remote web server, - * or log locally. Or throw hard. It is entirely up to you. + * Pode adicionar o erro para um serviço de coleções, + * adicionar os erros no $rootScope, logar os erros em um servidor remoto + * ou logar localmente. Ou lançar a exceção. Isso cabe interiamente à você. * throw exception; */ toastr.error(exception.msg, errorData); @@ -1609,15 +1611,16 @@ ou *Minificação e Anotação* ``` ### Exception Catchers +ou *Coletores de exceção* - - Criar um factory que expôe uma interface para capturar excessões. + - Criar um factory que expôe uma interface para capturar e tratar adequadamente as exceções. - *Por que?*: Provides a consistent way to catch exceptions that may be thrown in your code (e.g. during XHR calls or promise failures). + *Por que?*: Fornece uma forma consistente de coletar exceções que podem ser lançadas no seu código (ex. durante uma chamada XHR ou uma promessa (promise) que falhou). - Note: The exception catcher is good for catching and reacting to specific exceptions from calls that you know may throw one. For example, when making an XHR call to retrieve data from a remote web service and you want to catch any exceptions from that service and react uniquely. + Nota: O coletor de exceção é bom para coletar e reagir às exceções específicas das chamadas que você sabe que podem ser lançadas. Por exemplo, quando realizar uma chamada XHR que retorna dados de um serviço remoto e você quer coletar qualquer exceção desse serviço, reagindo de uma maneira única. ```javascript - /* recommended */ + /* recomendado */ angular .module('blocks.exception') .factory('exception', exception); From e4f67e99a93203695081ae83bbd6bac11cfae70c Mon Sep 17 00:00:00 2001 From: Fabien Tassin Date: Wed, 7 Jan 2015 20:07:00 +0100 Subject: [PATCH 100/567] fix Y075/controllerAs example to account for the isolated scope. --- README.md | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 883ef29d..a0d07c18 100644 --- a/README.md +++ b/README.md @@ -1207,13 +1207,13 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see }, link: linkFunc, controller : ExampleController, - controllerAs: 'vm' + controllerAs: 'vm', + bindToController: true // because the scope is isolated }; return directive; function linkFunc(scope, el, attr, ctrl) { - console.log('LINK: scope.max = %i', scope.max); console.log('LINK: scope.vm.min = %i', scope.vm.min); console.log('LINK: scope.vm.max = %i', scope.vm.max); } @@ -1226,8 +1226,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see var vm = this; vm.min = 3; - vm.max = $scope.max; - console.log('CTRL: $scope.max = %i', $scope.max); + console.log('CTRL: $scope.vm.max = %i', $scope.vm.max); console.log('CTRL: vm.min = %i', vm.min); console.log('CTRL: vm.max = %i', vm.max); } From 9c198ef188f8a2f281c0b4e9f3fa5dcbabaea52a Mon Sep 17 00:00:00 2001 From: Chris Montrois Date: Wed, 7 Jan 2015 15:34:24 -0700 Subject: [PATCH 101/567] Minor changes to trailing whitespace, spelling, double spaces, etc --- README.md | 249 +++++++++++++++++++++++++++--------------------------- 1 file changed, 123 insertions(+), 126 deletions(-) diff --git a/README.md b/README.md index 883ef29d..e599a7bb 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ If you are looking for an opinionated style guide for syntax, conventions, and s The purpose of this style guide is to provide guidance on building AngularJS applications by showing the conventions I use and, more importantly, why I choose them. ## Community Awesomeness and Credit -Never work in a vacuum. I find that the AngularJS community is an incredible group who are passionate about sharing experiences. As such, a friend and AngularJS expert Todd Motto and I have collaborated on many styles and conventions. We agree on most, and some we diverge. I encourage you to check out [Todd's guidelines](https://github.com/toddmotto/angularjs-styleguide) to get a sense for his approach and how it compares. +Never work in a vacuum. I find that the AngularJS community is an incredible group who are passionate about sharing experiences. As such, a friend and AngularJS expert Todd Motto and I have collaborated on many styles and conventions. We agree on most, and some we diverge. I encourage you to check out [Todd's guidelines](https://github.com/toddmotto/angularjs-styleguide) to get a sense for his approach and how it compares. Many of my styles have been from the many pair programming sessions [Ward Bell](http://twitter.com/wardbell) and I have had. While we don't always agree, my friend Ward has certainly helped influence the ultimate evolution of this guide. @@ -54,51 +54,51 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see ### Rule of 1 ###### [Style [Y001](#style-y001)] - - Define 1 component per file. + - Define 1 component per file. - The following example defines the `app` module and its dependencies, defines a controller, and defines a factory all in the same file. + The following example defines the `app` module and its dependencies, defines a controller, and defines a factory all in the same file. ```javascript /* avoid */ angular - .module('app', ['ngRoute']) - .controller('SomeController', SomeController) - .factory('someFactory', someFactory); - + .module('app', ['ngRoute']) + .controller('SomeController', SomeController) + .factory('someFactory', someFactory); + function SomeController() { } function someFactory() { } ``` - - The same components are now separated into their own files. + + The same components are now separated into their own files. ```javascript /* recommended */ - + // app.module.js angular - .module('app', ['ngRoute']); + .module('app', ['ngRoute']); ``` ```javascript /* recommended */ - + // someController.js angular - .module('app') - .controller('SomeController', SomeController); + .module('app') + .controller('SomeController', SomeController); function SomeController() { } ``` ```javascript /* recommended */ - + // someFactory.js angular - .module('app') - .factory('someFactory', someFactory); - + .module('app') + .factory('someFactory', someFactory); + function someFactory() { } ``` @@ -109,7 +109,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see ###### [Style [Y010](#style-y010)] - Wrap AngularJS components in an Immediately Invoked Function Expression (IIFE). - + *Why?*: An IIFE removes variables from the global scope. This helps prevent variables and function declarations from living longer than expected in the global scope, which also helps avoid variable collisions. *Why?*: When your code is minified and bundled into a single file for deployment to a production server, you could have collisions of variables and many global variables. An IIFE protects you against both of these by providing variable scope for each file. @@ -133,7 +133,6 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see function storage() { } ``` - ```javascript /** * recommended @@ -144,7 +143,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see // logger.js (function() { 'use strict'; - + angular .module('app') .factory('logger', logger); @@ -165,7 +164,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see ``` - Note: For brevity only, the rest of the examples in this guide may omit the IIFE syntax. - + - Note: IIFE's prevent test code from reaching private members like regular expressions or helper functions which are often good to unit test directly on their own. However you can test these through accessible members or by exposing them through their own component. For example placing helper functions, regular expressions or constants in their own factory or constant. **[Back to top](#table-of-contents)** @@ -184,8 +183,8 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see - Declare modules without a variable using the setter syntax. - *Why?*: With 1 component per file, there is rarely a need to introduce a variable for the module. - + *Why?*: With 1 component per file, there is rarely a need to introduce a variable for the module. + ```javascript /* avoid */ var app = angular.module('app', [ @@ -196,12 +195,12 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see ]); ``` - Instead use the simple setter syntax. + Instead use the simple setter syntax. ```javascript /* recommended */ angular - .module('app', [ + .module('app', [ 'ngAnimate', 'ngRoute', 'app.shared', @@ -212,15 +211,15 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see ### Getters ###### [Style [Y022](#style-y022)] - - When using a module, avoid using a variable and instead use chaining with the getter syntax. + - When using a module, avoid using a variable and instead use chaining with the getter syntax. - *Why?* : This produces more readable code and avoids variable collisions or leaks. + *Why?*: This produces more readable code and avoids variable collisions or leaks. ```javascript /* avoid */ var app = angular.module('app'); app.controller('SomeController', SomeController); - + function SomeController() { } ``` @@ -229,7 +228,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see angular .module('app') .controller('SomeController', SomeController); - + function SomeController() { } ``` @@ -237,18 +236,18 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see ###### [Style [Y023](#style-y023)] - Only set once and get for all other instances. - - *Why?*: A module should only be created once, then retrieved from that point and after. - - - Use `angular.module('app', []);` to set a module. - - Use `angular.module('app');` to get a module. + + *Why?*: A module should only be created once, then retrieved from that point and after. + + - Use `angular.module('app', []);` to set a module. + - Use `angular.module('app');` to get a module. ### Named vs Anonymous Functions ###### [Style [Y024](#style-y024)] - Use named functions instead of passing an anonymous function in as a callback. - *Why?*: This produces more readable code, is much easier to debug, and reduces the amount of nested callback code. + *Why?*: This produces more readable code, is much easier to debug, and reduces the amount of nested callback code. ```javascript /* avoid */ @@ -287,11 +286,11 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see - Use the [`controllerAs`](http://www.johnpapa.net/do-you-like-your-angular-controllers-with-or-without-sugar/) syntax over the `classic controller with $scope` syntax. - *Why?*: Controllers are constructed, "newed" up, and provide a single new instance, and the `controllerAs` syntax is closer to that of a JavaScript constructor than the `classic $scope syntax`. + *Why?*: Controllers are constructed, "newed" up, and provide a single new instance, and the `controllerAs` syntax is closer to that of a JavaScript constructor than the `classic $scope syntax`. - *Why?*: It promotes the use of binding to a "dotted" object in the View (e.g. `customer.name` instead of `name`), which is more contextual, easier to read, and avoids any reference issues that may occur without "dotting". + *Why?*: It promotes the use of binding to a "dotted" object in the View (e.g. `customer.name` instead of `name`), which is more contextual, easier to read, and avoids any reference issues that may occur without "dotting". - *Why?*: Helps avoid using `$parent` calls in Views with nested controllers. + *Why?*: Helps avoid using `$parent` calls in Views with nested controllers. ```html @@ -303,7 +302,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see ```html

``` @@ -314,7 +313,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see - The `controllerAs` syntax uses `this` inside controllers which gets bound to `$scope` - *Why?*: `controllerAs` is syntactic sugar over `$scope`. You can still bind to the View and still access `$scope` methods. + *Why?*: `controllerAs` is syntactic sugar over `$scope`. You can still bind to the View and still access `$scope` methods. *Why?*: Helps avoid the temptation of using `$scope` methods inside a controller when it may otherwise be better to avoid them or move them to a factory. Consider using `$scope` in a factory, or if in a controller just when needed. For example when publishing and subscribing events using [`$emit`](https://docs.angularjs.org/api/ng/type/$rootScope.Scope#$emit), [`$broadcast`](https://docs.angularjs.org/api/ng/type/$rootScope.Scope#$broadcast), or [`$on`](https://docs.angularjs.org/api/ng/type/$rootScope.Scope#$on) consider moving these uses to a factory and invoke from the controller. @@ -359,11 +358,11 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see ``` Note: You can avoid any [jshint](http://www.jshint.com/) warnings by placing the comment below above the line of code. However it is not needed when the function is named using UpperCasing, as this convention means it is a constructor function, which is what a controller is in Angular. - + ```javascript /* jshint validthis: true */ var vm = this; - ``` + ``` Note: When creating watches in a controller using `controller as`, you can watch the `vm.*` member using the following syntax. (Create watches with caution as they add more load to the digest cycle.) @@ -375,7 +374,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see function SomeController($scope, $log) { var vm = this; vm.title = 'Some Title'; - + $scope.$watch('vm.title', function(current, original) { $log.info('vm.title was %s', original); $log.info('vm.title is now %s', current); @@ -387,7 +386,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see ###### [Style [Y033](#style-y033)] - Place bindable members at the top of the controller, alphabetized, and not spread through the controller code. - + *Why?*: Placing bindable members at the top makes it easy to read and helps you instantly identify which members of the controller can be bound and used in the View. *Why?*: Setting anonymous functions in-line can be easy, but when those functions are more than 1 line of code they can reduce the readability. Defining the functions below the bindable members (the functions will be hoisted) moves the implementation details down, keeps the bindable members up top, and makes it easier to read. @@ -476,14 +475,14 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see ###### [Style [Y034](#style-y034)] - Use function declarations to hide implementation details. Keep your bindable members up top. When you need to bind a function in a controller, point it to a function declaration that appears later in the file. This is tied directly to the section Bindable Members Up Top. For more details see [this post](http://www.johnpapa.net/angular-function-declarations-function-expressions-and-readable-code). - + *Why?*: Placing bindable members at the top makes it easy to read and helps you instantly identify which members of the controller can be bound and used in the View. (Same as above.) *Why?*: Placing the implementation details of a function later in the file moves that complexity out of view so you can see the important stuff up top. *Why?*: Function declaration are hoisted so there are no concerns over using a function before it is defined (as there would be with function expressions). - *Why?*: You never have to worry with function declarations that moving `var a` before `var b` will break your code because `a` depends on `b`. + *Why?*: You never have to worry with function declarations that moving `var a` before `var b` will break your code because `a` depends on `b`. *Why?*: Order is critical with function expressions @@ -568,7 +567,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see vm.total = 0; function checkCredit() { - var settings = {}; + var settings = {}; // Get the credit service base URL from config // Set credit service required headers // Prepare URL query string or data object with request data @@ -576,7 +575,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see // Use JSONP for this browser if it doesn't support CORS return $http.get(settings) .then(function(data) { - // Unpack JSON data in the response object + // Unpack JSON data in the response object // to find maxRemainingAmount vm.isCreditOk = vm.total <= maxRemainingAmount }) @@ -590,7 +589,6 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see ``` ```javascript - /* recommended */ function Order(creditService) { var vm = this; @@ -600,7 +598,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see function checkCredit() { return creditService.isOrderTotalOk(vm.total) - .then(function(isOk) { vm.isCreditOk = isOk; }) + .then(function(isOk) { vm.isCreditOk = isOk; }) .catch(showServiceError); }; } @@ -610,14 +608,14 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see ###### [Style [Y037](#style-y037)] - Define a controller for a view, and try not to reuse the controller for other views. Instead, move reusable logic to factories and keep the controller simple and focused on its view. - + *Why?*: Reusing controllers with several views is brittle and good end to end (e2e) test coverage is required to ensure stability across large applications. ### Assigning Controllers ###### [Style [Y038](#style-y038)] - When a controller must be paired with a view and either component may be re-used by other controllers or views, define controllers along with their routes. - + Note: If a View is loaded via another means besides a route, then use the `ng-controller="Avengers as vm"` syntax. *Why?*: Pairing the controller in the route allows different routes to invoke different pairs of controllers and views. When controllers are assigned in the view using [`ng-controller`](https://docs.angularjs.org/api/ng/directive/ngController), that view is always associated with the same controller. @@ -676,7 +674,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see ###### [Style [Y040](#style-y040)] - Services are instantiated with the `new` keyword, use `this` for public methods and variables. Since these are so similar to factories, use a factory instead for consistency. - + Note: [All AngularJS services are singletons](https://docs.angularjs.org/guide/services). This means that there is only one instance of a given service per injector. ```javascript @@ -720,7 +718,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see ###### [Style [Y051](#style-y051)] - Factories are singletons and return an object that contains the members of the service. - + Note: [All AngularJS services are singletons](https://docs.angularjs.org/guide/services). ### Accessible Members Up Top @@ -791,7 +789,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see *Why?*: Function declaration are hoisted so there are no concerns over using a function before it is defined (as there would be with function expressions). - *Why?*: You never have to worry with function declarations that moving `var a` before `var b` will break your code because `a` depends on `b`. + *Why?*: You never have to worry with function declarations that moving `var a` before `var b` will break your code because `a` depends on `b`. *Why?*: Order is critical with function expressions @@ -805,7 +803,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see var primePromise; var getAvengers = function() { - // implementation details go here + // implementation details go here }; var getAvengerCount = function() { @@ -857,7 +855,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see //////////// function getAvengers() { - // implementation details go here + // implementation details go here } function getAvengerCount() { @@ -865,7 +863,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see } function getAvengersCast() { - // implementation details go here + // implementation details go here } function prime() { @@ -1031,7 +1029,6 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see /* spinner directive that can be used anywhere across apps */ .directive('sharedSpinner', sharedSpinner); - function orderCalendarRange() { /* implementation details */ } @@ -1112,7 +1109,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see *Why?*: The unique short prefix identifies the directive's context and origin. For example a prefix of `cc-` may indicate that the directive is part of a CodeCamper app while `acme-` may indicate a directive for the Acme company. - Note: Avoid `ng-` as these are reserved for AngularJS directives.Research widely used directives to avoid naming conflicts, such as `ion-` for the [Ionic Framework](http://ionicframework.com/). + Note: Avoid `ng-` as these are reserved for AngularJS directives. Research widely used directives to avoid naming conflicts, such as `ion-` for the [Ionic Framework](http://ionicframework.com/). ### Restrict to Elements and Attributes ###### [Style [Y074](#style-y074)] @@ -1206,7 +1203,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see max: '=' }, link: linkFunc, - controller : ExampleController, + controller: ExampleController, controllerAs: 'vm' }; @@ -1438,7 +1435,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see .controller('Dashboard', ['$location', '$routeParams', 'common', 'dataservice', function Dashboard($location, $routeParams, common, dataservice) {} - ]); + ]); ``` ```javascript @@ -1446,7 +1443,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see angular .module('app') .controller('Dashboard', - ['$location', '$routeParams', 'common', 'dataservice', Dashboard]); + ['$location', '$routeParams', 'common', 'dataservice', Dashboard]); function Dashboard($location, $routeParams, common, dataservice) { } @@ -1459,7 +1456,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see .controller('Dashboard', Dashboard); Dashboard.$inject = ['$location', '$routeParams', 'common', 'dataservice']; - + function Dashboard($location, $routeParams, common, dataservice) { } ``` @@ -1498,7 +1495,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see ###### [Style [Y092](#style-y092)] - Use $inject to manually identify your route resolver dependencies for AngularJS components. - + *Why?*: This technique breaks out the anonymous function for the route resolver, making it easier to read. *Why?*: An `$inject` statement can easily precede the resolver to handle making any dependencies minification safe. @@ -1517,7 +1514,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see }); } - moviePrepService.$inject = ['movieService']; + moviePrepService.$inject = ['movieService']; function moviePrepService(movieService) { return movieService.getMovies(); } @@ -1551,7 +1548,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see vm.heroSearch = ''; vm.storeHero = storeHero; - function storeHero(){ + function storeHero() { var hero = avengerService.find(vm.heroSearch); storageService.save(hero.name, hero); } @@ -1571,7 +1568,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see vm.heroSearch = ''; vm.storeHero = storeHero; - function storeHero(){ + function storeHero() { var hero = avengerService.find(vm.heroSearch); storageService.save(hero.name, hero); } @@ -1647,7 +1644,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see Note: Another option is to override the service instead of using a decorator. This is a fine option, but if you want to keep the default behavior and extend it a decorator is recommended. - ```javascript + ```javascript /* recommended */ angular .module('blocks.exception') @@ -1677,7 +1674,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see toastr.error(exception.msg, errorData); }; } - ``` + ``` ### Exception Catchers ###### [Style [Y111](#style-y111)] @@ -1717,7 +1714,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see *Why?*: Provides a consistent way handle all routing errors. - *Why?*: Potentially provides a better user experience if a routing error occurs and you route them to a friendly screen with more details or recovery options. + *Why?*: Potentially provides a better user experience if a routing error occurs and you route them to a friendly screen with more details or recovery options. ```javascript /* recommended */ @@ -1750,8 +1747,8 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see ###### [Style [Y120](#style-y120)] - Use consistent names for all components following a pattern that describes the component's feature then (optionally) its type. My recommended pattern is `feature.type.js`. There are 2 names for most assets: - * the file name (`avengers.controller.js`) - * the registered component name with Angular (`AvengersController`) + * the file name (`avengers.controller.js`) + * the registered component name with Angular (`AvengersController`) *Why?*: Naming conventions help provide a consistent way to find content at a glance. Consistency within the project is vital. Consistency with a team is important. Consistency across a company provides tremendous efficiency. @@ -1827,7 +1824,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see ### Test File Names ###### [Style [Y122](#style-y122)] - - Name test specifications similar to the component they test with a suffix of `spec`. + - Name test specifications similar to the component they test with a suffix of `spec`. *Why?*: Provides a consistent way to quickly identify components. @@ -1862,9 +1859,9 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see .module .controller('HeroAvengers', HeroAvengers); - function HeroAvengers(){ } + function HeroAvengers() { } ``` - + ### Controller Name Suffix ###### [Style [Y124](#style-y124)] @@ -1884,7 +1881,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see .module .controller('Avengers', Avengers); - function Avengers(){ } + function Avengers() { } ``` ```javascript @@ -1897,7 +1894,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see .module .controller('AvengersController', AvengersController); - function AvengersController(){ } + function AvengersController() { } ``` ### Factory Names @@ -1917,7 +1914,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see .module .factory('logger', logger); - function logger(){ } + function logger() { } ``` ### Directive Component Names @@ -1932,20 +1929,20 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see * recommended */ - // avenger-profile.directive.js + // avenger-profile.directive.js angular .module .directive('xxAvengerProfile', xxAvengerProfile); // usage is - function xxAvengerProfile(){ } + function xxAvengerProfile() { } ``` ### Modules ###### [Style [Y127](#style-y127)] - - When there are multiple modules, the main module file is named `app.module.js` while other dependent modules are named after what they represent. For example, an admin module is named `admin.module.js`. The respective registered module names would be `app` and `admin`. + - When there are multiple modules, the main module file is named `app.module.js` while other dependent modules are named after what they represent. For example, an admin module is named `admin.module.js`. The respective registered module names would be `app` and `admin`. *Why?*: Provides consistency for multiple module apps, and for expanding to large applications. @@ -1987,7 +1984,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see - Make locating your code intuitive, simple and fast. - *Why?*: I find this to be super important for a project. If the team cannot find the files they need to work on quickly, they will not be able to work as efficiently as possible, and the structure needs to change. You may not know the file name or where its related files are, so putting them in the most intuitive locations and near each other saves a ton of time. A descriptive folder structure can help with this. + *Why?*: I find this to be super important for a project. If the team cannot find the files they need to work on quickly, they will not be able to work as efficiently as possible, and the structure needs to change. You may not know the file name or where its related files are, so putting them in the most intuitive locations and near each other saves a ton of time. A descriptive folder structure can help with this. ``` /bower_components @@ -2035,7 +2032,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see ### Overall Guidelines ###### [Style [Y150](#style-y150)] - - Have a near term view of implementation and a long term vision. In other words, start small and but keep in mind on where the app is heading down the road. All of the app's code goes in a root folder named `app`. All content is 1 feature per file. Each controller, service, module, view is in its own file. All 3rd party vendor scripts are stored in another root folder and not in the `app` folder. I didn't write them and I don't want them cluttering my app (`bower_components`, `scripts`, `lib`). + - Have a near term view of implementation and a long term vision. In other words, start small and but keep in mind on where the app is heading down the road. All of the app's code goes in a root folder named `app`. All content is 1 feature per file. Each controller, service, module, view is in its own file. All 3rd party vendor scripts are stored in another root folder and not in the `app` folder. I didn't write them and I don't want them cluttering my app (`bower_components`, `scripts`, `lib`). Note: Find more details and reasoning behind the structure at [this original post on application structure](http://www.johnpapa.net/angular-app-structuring-guidelines/). @@ -2068,33 +2065,33 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see app.module.js app.config.js app.routes.js - components/ - calendar.directive.js - calendar.directive.html - user-profile.directive.js - user-profile.directive.html + components/ + calendar.directive.js + calendar.directive.html + user-profile.directive.js + user-profile.directive.html layout/ - shell.html + shell.html shell.controller.js - topnav.html - topnav.controller.js + topnav.html + topnav.controller.js people/ attendees.html - attendees.controller.js + attendees.controller.js speakers.html speakers.controller.js speaker-detail.html speaker-detail.controller.js - services/ - data.service.js + services/ + data.service.js localstorage.service.js - logger.service.js + logger.service.js spinner.service.js sessions/ - sessions.html + sessions.html sessions.controller.js session-detail.html - session-detail.controller.js + session-detail.controller.js ``` ![Sample App Structure](https://raw.githubusercontent.com/johnpapa/angularjs-styleguide/master/assets/modularity-2.png) @@ -2113,43 +2110,43 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see app.config.js app.routes.js controllers/ - attendees.js - session-detail.js - sessions.js - shell.js - speakers.js - speaker-detail.js - topnav.js - directives/ - calendar.directive.js - calendar.directive.html - user-profile.directive.js - user-profile.directive.html - services/ - dataservice.js + attendees.js + session-detail.js + sessions.js + shell.js + speakers.js + speaker-detail.js + topnav.js + directives/ + calendar.directive.js + calendar.directive.html + user-profile.directive.js + user-profile.directive.html + services/ + dataservice.j localstorage.js - logger.js + logger.js spinner.js views/ - attendees.html + attendees.html session-detail.html - sessions.html - shell.html - speakers.html + sessions.html + shell.html + speakers.html speaker-detail.html - topnav.html + topnav.html ``` **[Back to top](#table-of-contents)** ## Modularity - + ### Many Small, Self Contained Modules ###### [Style [Y160](#style-y160)] - Create small modules that encapsulate one responsibility. - *Why?*: Modular applications make it easy to plug and go as they allow the development teams to build vertical slices of the applications and roll out incrementally. This means we can plug in new features as we develop them. + *Why?*: Modular applications make it easy to plug and go as they allow the development teams to build vertical slices of the applications and roll out incrementally. This means we can plug in new features as we develop them. ### Create an App Module ###### [Style [Y161](#style-y161)] @@ -2292,19 +2289,19 @@ Unit testing helps maintain clean code, as such I included some of my recommenda ```javascript it('should have Avengers controller', function() { - //TODO + // TODO }); it('should find 1 Avenger when filtered by name', function() { - //TODO + // TODO }); it('should have 10 Avengers', function() { - //TODO (mock data?) + // TODO (mock data?) }); it('should return Avengers via XHR', function() { - //TODO ($httpBackend?) + // TODO ($httpBackend?) }); // and so on @@ -2386,7 +2383,7 @@ Unit testing helps maintain clean code, as such I included some of my recommenda ### Sub Second ###### [Style [Y211](#style-y211)] - - Use short durations for animations. I generally start with 300ms and adjust until appropriate. + - Use short durations for animations. I generally start with 300ms and adjust until appropriate. *Why?*: Long animations can have the reverse affect on User Experience and perceived performance by giving the appearance of a slow application. From fece0c5d1bf7d4d8644596fc041c4178e7f07a69 Mon Sep 17 00:00:00 2001 From: John Papa Date: Sat, 10 Jan 2015 08:54:27 -0500 Subject: [PATCH 102/567] organizing unit tests --- README.md | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/README.md b/README.md index e599a7bb..441c58a9 100644 --- a/README.md +++ b/README.md @@ -2367,6 +2367,32 @@ Unit testing helps maintain clean code, as such I included some of my recommenda ![Testing Tools](https://raw.githubusercontent.com/johnpapa/angularjs-styleguide/master/assets/testing-tools.png) +### Organizing Tests +###### [Style [Y197](#style-y197)] + + - Place unit test files (specs) side-by-side with your client code. Place specs that cover server integration or test multiple components in a separate `tests` folder. + + *Why?*: Unit tests have a direct correlation to a specific component and file in source code. + + *Why?*: It is easier to keep them up to date since they are always in sight. When coding whether you do TDD or test during development or test after development, the specs are side-by-side and never out of sight nor mind, and thus more likely to be maintained which also helps maintain code coverage. + + *Why?*: When you update source code it is easier to go update the tests at the same time. + + *Why?*: Placing them side-by-side makes it easy to find them and easy to move them with the source code if you move the source. + + + *Why?*: Separating specs so they are not in a distributed build is easy with grunt or gulp. + + ``` + /src/client/app/customers/customer-detail.controller.js + /customer-detail.controller.spec.js + /customers.controller.spec.js + /customers.controller-detail.spec.js + /customers.module.js + /customers.route.js + /customers.route.spec.js + ``` + **[Back to top](#table-of-contents)** ## Animations From 1e1d1e669105d3988d58d608dda48b897e664389 Mon Sep 17 00:00:00 2001 From: John Papa Date: Sat, 10 Jan 2015 10:07:27 -0500 Subject: [PATCH 103/567] clean code banner --- README.md | 2 ++ assets/ng-clean-code-banner.png | Bin 0 -> 56340 bytes 2 files changed, 2 insertions(+) create mode 100644 assets/ng-clean-code-banner.png diff --git a/README.md b/README.md index 441c58a9..fad6f03c 100644 --- a/README.md +++ b/README.md @@ -6,6 +6,8 @@ If you are looking for an opinionated style guide for syntax, conventions, and s >If you like this guide, check out my [AngularJS Patterns: Clean Code](http://jpapa.me/ngclean) course at Pluralsight. + [![AngularJs Patterns: Clean Code](https://raw.githubusercontent.com/johnpapa/angularjs-styleguide/master/assets/ng-clean-code-banner.png)](http://jpapa.me/ngclean) + The purpose of this style guide is to provide guidance on building AngularJS applications by showing the conventions I use and, more importantly, why I choose them. ## Community Awesomeness and Credit diff --git a/assets/ng-clean-code-banner.png b/assets/ng-clean-code-banner.png new file mode 100644 index 0000000000000000000000000000000000000000..b35c537fa57245815ee2b11e9a7e44b14e38e5df GIT binary patch literal 56340 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

LkK6~ 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 literal 0 HcmV?d00001 From 1d05d94ae68c366b327ef867ad63dd89853b9e2e Mon Sep 17 00:00:00 2001 From: John Papa Date: Sat, 10 Jan 2015 10:08:21 -0500 Subject: [PATCH 104/567] remove hyperlink --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index fad6f03c..235be454 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ If you are looking for an opinionated style guide for syntax, conventions, and s >If you like this guide, check out my [AngularJS Patterns: Clean Code](http://jpapa.me/ngclean) course at Pluralsight. - [![AngularJs Patterns: Clean Code](https://raw.githubusercontent.com/johnpapa/angularjs-styleguide/master/assets/ng-clean-code-banner.png)](http://jpapa.me/ngclean) + ![AngularJs Patterns: Clean Code](https://raw.githubusercontent.com/johnpapa/angularjs-styleguide/master/assets/ng-clean-code-banner.png) The purpose of this style guide is to provide guidance on building AngularJS applications by showing the conventions I use and, more importantly, why I choose them. From 067c8f53acde829bbcaf9a153c7b18f34a081e0d Mon Sep 17 00:00:00 2001 From: John Papa Date: Sat, 10 Jan 2015 10:10:26 -0500 Subject: [PATCH 105/567] fix indent --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 235be454..71c1f533 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ If you are looking for an opinionated style guide for syntax, conventions, and s >If you like this guide, check out my [AngularJS Patterns: Clean Code](http://jpapa.me/ngclean) course at Pluralsight. - ![AngularJs Patterns: Clean Code](https://raw.githubusercontent.com/johnpapa/angularjs-styleguide/master/assets/ng-clean-code-banner.png) + ![AngularJs Patterns: Clean Code](https://raw.githubusercontent.com/johnpapa/angularjs-styleguide/master/assets/ng-clean-code-banner.png) The purpose of this style guide is to provide guidance on building AngularJS applications by showing the conventions I use and, more importantly, why I choose them. From 222439176b156c5640c57bb17fddf6674425d35b Mon Sep 17 00:00:00 2001 From: John Papa Date: Sat, 10 Jan 2015 10:13:34 -0500 Subject: [PATCH 106/567] link --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 71c1f533..3bec37d0 100644 --- a/README.md +++ b/README.md @@ -6,8 +6,8 @@ If you are looking for an opinionated style guide for syntax, conventions, and s >If you like this guide, check out my [AngularJS Patterns: Clean Code](http://jpapa.me/ngclean) course at Pluralsight. - ![AngularJs Patterns: Clean Code](https://raw.githubusercontent.com/johnpapa/angularjs-styleguide/master/assets/ng-clean-code-banner.png) - + [![AngularJs Patterns: Clean Code](https://raw.githubusercontent.com/johnpapa/angularjs-styleguide/master/assets/ng-clean-code-banner.png)](http://jpapa.me/ngclean) + The purpose of this style guide is to provide guidance on building AngularJS applications by showing the conventions I use and, more importantly, why I choose them. ## Community Awesomeness and Credit From f3d019a1ace910ecbd77723c5779e5d903f9cea5 Mon Sep 17 00:00:00 2001 From: John Papa Date: Sat, 10 Jan 2015 10:15:04 -0500 Subject: [PATCH 107/567] moved text --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 3bec37d0..a9b140b6 100644 --- a/README.md +++ b/README.md @@ -4,12 +4,12 @@ If you are looking for an opinionated style guide for syntax, conventions, and structuring AngularJS applications, then step right in. These styles are based on my development experience with [AngularJS](//angularjs.org), presentations, [Pluralsight training courses](http://pluralsight.com/training/Authors/Details/john-papa) and working in teams. +The purpose of this style guide is to provide guidance on building AngularJS applications by showing the conventions I use and, more importantly, why I choose them. + >If you like this guide, check out my [AngularJS Patterns: Clean Code](http://jpapa.me/ngclean) course at Pluralsight. [![AngularJs Patterns: Clean Code](https://raw.githubusercontent.com/johnpapa/angularjs-styleguide/master/assets/ng-clean-code-banner.png)](http://jpapa.me/ngclean) -The purpose of this style guide is to provide guidance on building AngularJS applications by showing the conventions I use and, more importantly, why I choose them. - ## Community Awesomeness and Credit Never work in a vacuum. I find that the AngularJS community is an incredible group who are passionate about sharing experiences. As such, a friend and AngularJS expert Todd Motto and I have collaborated on many styles and conventions. We agree on most, and some we diverge. I encourage you to check out [Todd's guidelines](https://github.com/toddmotto/angularjs-styleguide) to get a sense for his approach and how it compares. From ad41a6602d6d9749dbe8fa0d78d53e2305b334fa Mon Sep 17 00:00:00 2001 From: angelochiello Date: Mon, 12 Jan 2015 09:19:52 +0100 Subject: [PATCH 108/567] [it-IT] PR #219 Updated as PR #219 "organizing unit tests" --- i18n/it-IT.md | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/i18n/it-IT.md b/i18n/it-IT.md index b698279e..61aea095 100644 --- a/i18n/it-IT.md +++ b/i18n/it-IT.md @@ -2381,6 +2381,32 @@ Gli unit test aiutano a mantenere il codice più chiaro, perciò ho incluso alcu ![Strumenti per i test](https://raw.githubusercontent.com/johnpapa/angularjs-styleguide/master/assets/testing-tools.png) +### Organizzazione dei test +###### [Stile [Y197](#stile-y197)] + + - Posiziona i file degli unit test vicino al codice del client. Posiziona le specifiche che coprono l'integrazione con il server o che testano più componenti in una cartella separata `tests`. + + *Perché?*: Gli unit test hanno una correlazione diretta con un componente specifico e un file nei sogenti. + + *Perché?*: È più semplice da tenere aggiornati dal momento che sono sempre a vista. Quando scrivi codice, sia che tu faccia TDD o fai i test durante o dopo lo sviluppo, le scpecifiche sono sempre di fianco e mai fuori dalla vista o dai pensieri, quindi è più probabile che siano aggiornati e ciò consente inoltre a mantenere una migliore copertura del codice. + + *Perché?*: Quando aggiorni i sorgenti, è più semplice andare ad aggiornare anche i test. + + *Perché?*: Posizionarli vicino rende semplice trovarli e spostarli con i sorgenti qualora ciò accada. + + + *Perché?*: Separare le specifiche così da non essere nella build di distribuzione è semplice con grunt o gulp. + + ``` + /src/client/app/customers/customer-detail.controller.js + /customer-detail.controller.spec.js + /customers.controller.spec.js + /customers.controller-detail.spec.js + /customers.module.js + /customers.route.js + /customers.route.spec.js + ``` + **[Torna all'inizio](#tavola-dei-contenuti)** ## Animazioni From 080485692edaaf83700be12a1e7270f9865c7ef8 Mon Sep 17 00:00:00 2001 From: angelochiello Date: Mon, 12 Jan 2015 09:22:29 +0100 Subject: [PATCH 109/567] [it-IT] PR #220 Updated as PR #220 "Develop" --- i18n/it-IT.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/i18n/it-IT.md b/i18n/it-IT.md index 61aea095..626ee494 100644 --- a/i18n/it-IT.md +++ b/i18n/it-IT.md @@ -10,6 +10,8 @@ Se stai cercando una guida stilistica dogmatica per le sintassi, convenzioni e s >Se ti piace questa guida, dai un'occhiata al mio corso [AngularJS Patterns: Clean Code](http://jpapa.me/ngclean) (in inglese) su Pluralsight. + [![AngularJs Patterns: Clean Code](https://raw.githubusercontent.com/johnpapa/angularjs-styleguide/master/assets/ng-clean-code-banner.png)](http://jpapa.me/ngclean) + L'obbiettivo di questa guida stilistica è di fare da vademecum alla costruzione di applicazioni con AngularJS mostrando le convenzioni che uso e, più importante, perché le uso. ## Eccezionalità della comunità e riconoscimenti From 265a1ac46126dd9c275f81070988ceca8ac77653 Mon Sep 17 00:00:00 2001 From: angelochiello Date: Mon, 12 Jan 2015 09:26:21 +0100 Subject: [PATCH 110/567] [it-IT] PR #222 Updated as PR #222 "moved text" --- i18n/it-IT.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/i18n/it-IT.md b/i18n/it-IT.md index 626ee494..24ee8688 100644 --- a/i18n/it-IT.md +++ b/i18n/it-IT.md @@ -8,12 +8,12 @@ Se stai cercando una guida stilistica dogmatica per le sintassi, convenzioni e struttura di applicazioni AngularJS, allora questo fa per te. Gli stili sono basati sulla mia esperienza di sviluppo con [AngularJS](//angularjs.org), presentazioni, [corsi di formazioni di Pluralsight](http://pluralsight.com/training/Authors/Details/john-papa) e del lavoro in team. +L'obbiettivo di questa guida stilistica è di fare da vademecum alla costruzione di applicazioni con AngularJS mostrando le convenzioni che uso e, più importante, perché le uso. + >Se ti piace questa guida, dai un'occhiata al mio corso [AngularJS Patterns: Clean Code](http://jpapa.me/ngclean) (in inglese) su Pluralsight. [![AngularJs Patterns: Clean Code](https://raw.githubusercontent.com/johnpapa/angularjs-styleguide/master/assets/ng-clean-code-banner.png)](http://jpapa.me/ngclean) -L'obbiettivo di questa guida stilistica è di fare da vademecum alla costruzione di applicazioni con AngularJS mostrando le convenzioni che uso e, più importante, perché le uso. - ## Eccezionalità della comunità e riconoscimenti Mai lavorare nel vuoto. Ritengo che la comunità intorno ad AngularJS sia un gruppo incredibile con la passione di condividere le esperienze. Perciò, Todd Motto, un amico ed un esperto di AngularJS, ed io abbiamo collaborato su molti stili e convenzioni. Su molto siamo d'accordo, su altro meno. Ti invito a controllare le [linee guida di Todd](https://github.com/toddmotto/angularjs-styleguide) per avere cognizione del suo approccio e di come paragonarle. From fee62f22f34bb424af87007b265647bc5cd563b1 Mon Sep 17 00:00:00 2001 From: Ward Bell Date: Mon, 12 Jan 2015 10:36:48 -0800 Subject: [PATCH 111/567] Add a reason to put specs in the same folder as the source --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index a9b140b6..40105da8 100644 --- a/README.md +++ b/README.md @@ -2382,6 +2382,7 @@ Unit testing helps maintain clean code, as such I included some of my recommenda *Why?*: Placing them side-by-side makes it easy to find them and easy to move them with the source code if you move the source. + *Why?*: Having the spec nearby makes it easier for the source code reader to learn how the component is supposed to be used and to discover its known limitations. *Why?*: Separating specs so they are not in a distributed build is easy with grunt or gulp. From 054ce3cf0a5c89926ef25766581577bfaf98b184 Mon Sep 17 00:00:00 2001 From: angelochiello Date: Tue, 13 Jan 2015 08:51:38 +0100 Subject: [PATCH 112/567] [it-IT] PR #224 Updated as PR #224 "Added a reason to y197 to put specs in the same folder as the source" --- i18n/it-IT.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/i18n/it-IT.md b/i18n/it-IT.md index 24ee8688..a8d3f47a 100644 --- a/i18n/it-IT.md +++ b/i18n/it-IT.md @@ -2395,7 +2395,8 @@ Gli unit test aiutano a mantenere il codice più chiaro, perciò ho incluso alcu *Perché?*: Quando aggiorni i sorgenti, è più semplice andare ad aggiornare anche i test. *Perché?*: Posizionarli vicino rende semplice trovarli e spostarli con i sorgenti qualora ciò accada. - + + *Perché?*: Avere le specifiche vicino rende più facile al lettore del codice sorgente imparare come il componente dovrebbe essere usato e scoprire le sue limitazioni. *Perché?*: Separare le specifiche così da non essere nella build di distribuzione è semplice con grunt o gulp. From 74d4b5a7e7023e2b6e467486f4403332c692ab90 Mon Sep 17 00:00:00 2001 From: Aleksandar Bogatinov Date: Tue, 13 Jan 2015 17:36:24 +0100 Subject: [PATCH 113/567] Updated to latest version --- i18n/mk-MK.md | 29 ++++++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/i18n/mk-MK.md b/i18n/mk-MK.md index 20a94cbb..d6951d14 100644 --- a/i18n/mk-MK.md +++ b/i18n/mk-MK.md @@ -9,9 +9,11 @@ Доколку барате своеволен стил на кодирање за синтакса, конвенции и структурирање на AngularJS апликации, тогаш сте на правилното место. Овие стилови се базирани на моето искуство во развој на [AngularJS](//angularjs.org), презентации, [Pluralsight тренинг курсеви](http://pluralsight.com/training/Authors/Details/john-papa) и работа во тимови. +Целта на овој водич на кодирање е да овозможи насока во развој на AngularJS апликации преку конвенциите што јас ги користам, и уште поважно, зошто ги користам. + >Ако ви се допаѓа овој водич, тогаш проверете ми го курсот [AngularJS Patterns: Clean Code](http://jpapa.me/ngclean) на Pluralsight. -Целта на овој водич на кодирање е да овозможи насока во развој на AngularJS апликации преку конвенциите што јас ги користам, и уште поважно, зошто ги користам. +![AngularJs Шаблон: Чист Код](https://raw.githubusercontent.com/johnpapa/angularjs-styleguide/master/assets/ng-clean-code-banner.png) ## Величествена заедница и заслуга Никогаш не работи во вакуум. Јас сметам дека AngularJS заедницата е неверојатна група кои се страсни за споделување искуство. Како резултат, јас и мојот пријател кој е AngularJS експерт, Todd Motto соработувавме со многу стилови и конвенции. Се согласуваме на повеќето, додека на останатите се разликуваме. Ве охрабрувам да ги погледнете на [Todd's guidelines](https://github.com/toddmotto/angularjs-styleguide) со цел да добиете осет за неговиот пристап и како се споредува. @@ -2295,6 +2297,31 @@ ![Алатки за тестирање](https://raw.githubusercontent.com/johnpapa/angularjs-styleguide/master/assets/testing-tools.png) + ### Организирање на тестови +###### [Style [Y197](#style-y197)] + + - Поставете ги датотеките за unit тестови (спецификација) една поред друга во вашиот клиентски код. Поставете ги спецификациите кои ја покриваат интеграцијата со серверот или тестираат повеќе компоненти во посебна `tests` папка. + + *Зошто?*: Unit тестови имаат директна поврзаност со специфична компонента и датотека во изворниот код. + + *Зошто?*: Полесно е временски да ги ажурирате бидејќи секогаш се забележителни. Кога кодирате, дали TDD или тестирате пред или после развојот, специкациите се секогаш една поред друга и никогаш нема да се изгубат, што значи дека треба да се одржуваат притоа подобрувајќи ја покриеноста на кодот. + + *Зошто?*: Кога го ажурирате изворниот код полесно е да ги ажурирате и тестовите во исто време. + + *Зошто?*: Поставувајќи ги една поред друга овозможува полесно пронаоѓање и преместување заедно со изворниот код доколку го преместите. + + *Зошто?*: Разделување на спецификациите така што не се во дистрибуиран build е полесно со grunt или gulp. + + ``` + /src/client/app/customers/customer-detail.controller.js + /customer-detail.controller.spec.js + /customers.controller.spec.js + /customers.controller-detail.spec.js + /customers.module.js + /customers.route.js + /customers.route.spec.js + ``` + **[Назад кон содржината](#table-of-contents)** ## Animations From 27874be258ddeb48fd254ba523904a94c113ace8 Mon Sep 17 00:00:00 2001 From: Aleksandar Bogatinov Date: Tue, 13 Jan 2015 17:41:37 +0100 Subject: [PATCH 114/567] Fixed issue with Back to top not working --- i18n/mk-MK.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/i18n/mk-MK.md b/i18n/mk-MK.md index d6951d14..afca01d1 100644 --- a/i18n/mk-MK.md +++ b/i18n/mk-MK.md @@ -27,7 +27,7 @@ ##Преводи [Преводи од овој AngularJS водич на кодирање](https://github.com/johnpapa/angularjs-styleguide/tree/master/i18n) се одржувани од заедницата и можете да ги најдете тука. -## Содржина +## Table of contents 1. [Single Responsibility](#single-responsibility) 1. [IIFE](#iife) From 6a9db72da60f812a78e2616a8ff90d5adc357965 Mon Sep 17 00:00:00 2001 From: Aleksandar Bogatinov Date: Tue, 13 Jan 2015 17:46:58 +0100 Subject: [PATCH 115/567] Added missing link to Pluralsight course --- i18n/mk-MK.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/i18n/mk-MK.md b/i18n/mk-MK.md index afca01d1..44d3970a 100644 --- a/i18n/mk-MK.md +++ b/i18n/mk-MK.md @@ -13,7 +13,7 @@ >Ако ви се допаѓа овој водич, тогаш проверете ми го курсот [AngularJS Patterns: Clean Code](http://jpapa.me/ngclean) на Pluralsight. -![AngularJs Шаблон: Чист Код](https://raw.githubusercontent.com/johnpapa/angularjs-styleguide/master/assets/ng-clean-code-banner.png) +[![AngularJs Шаблон: Чист Код](https://raw.githubusercontent.com/johnpapa/angularjs-styleguide/master/assets/ng-clean-code-banner.png)](http://jpapa.me/ngclean) ## Величествена заедница и заслуга Никогаш не работи во вакуум. Јас сметам дека AngularJS заедницата е неверојатна група кои се страсни за споделување искуство. Како резултат, јас и мојот пријател кој е AngularJS експерт, Todd Motto соработувавме со многу стилови и конвенции. Се согласуваме на повеќето, додека на останатите се разликуваме. Ве охрабрувам да ги погледнете на [Todd's guidelines](https://github.com/toddmotto/angularjs-styleguide) со цел да добиете осет за неговиот пристап и како се споредува. From 5b99807d02fe07fe1c0117a0336a41954f4bda36 Mon Sep 17 00:00:00 2001 From: jboyer2012 Date: Fri, 16 Jan 2015 16:34:49 -0500 Subject: [PATCH 116/567] Fixed mocha link in Style Y191. Link was returning 404 error. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index a9b140b6..c2704cd3 100644 --- a/README.md +++ b/README.md @@ -2312,7 +2312,7 @@ Unit testing helps maintain clean code, as such I included some of my recommenda ### Testing Library ###### [Style [Y191](#style-y191)] - - Use [Jasmine](http://jasmine.github.io/) or [Mocha](http://visionmedia.github.io/mocha/) for unit testing. + - Use [Jasmine](http://jasmine.github.io/) or [Mocha](http://mochajs.org) for unit testing. *Why?*: Both Jasmine and Mocha are widely used in the AngularJS community. Both are stable, well maintained, and provide robust testing features. From 0e6d3f3de38ab7b4e80bc1158cde983891a65c58 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=B5=B5=E5=8F=AF?= Date: Sat, 17 Jan 2015 23:53:06 +0800 Subject: [PATCH 117/567] Latest Transition --- i18n/zh-CN.md | 110 +++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 104 insertions(+), 6 deletions(-) diff --git a/i18n/zh-CN.md b/i18n/zh-CN.md index 982daef8..6797caec 100644 --- a/i18n/zh-CN.md +++ b/i18n/zh-CN.md @@ -8,9 +8,11 @@ 如果你正在寻找一些关于语法、约定和结构化的AngularJS应用的一个有建设性的风格指南,这个repo正适合你。这里所包含的风格是基于我在团队中使用[AngularJS](//angularjs.org)的一些经验、一些演讲和[Pluralsight培训课程](http://pluralsight.com/training/Authors/Details/john-papa)。 +这个风格指南的目的是为构建AngularJS应用提供指导,当然更加重要的是让大家知道我为什么要选择它们。 + >如果你喜欢这个指南,请在Pluralsight上检出我的[AngularJS Patterns: Clean Code](http://jpapa.me/ngclean)。 -这个风格指南的目的是为构建AngularJS应用提供指导,当然更加重要的是让大家知道我为什么要选择它们。 + [![AngularJs Patterns: Clean Code](https://raw.githubusercontent.com/johnpapa/angularjs-styleguide/master/assets/ng-clean-code-banner.png)](http://jpapa.me/ngclean) ## Community Awesomeness and Credit 我发现AngularJS社区是一个热衷于分享经验的令人难以置信的社区,尽管Todd Motto(他是我的一个朋友,也是AngularJS专家)和我合作了多种风格和惯例,但是我们也存在着一些分歧。我鼓励你去看看[Todd的指南](https://github.com/toddmotto/angularjs-styleguide),从其中了解他的做法和它们是如何比较的。 @@ -1253,7 +1255,9 @@ *为什么?*:把启动逻辑放在一个controller中固定的位置可以更方便定位、有更加一致性的测试,并能够避免在controller中到处都是激活逻辑。 - 注意:如果你需要在开始使用controller之前有条件地取消路由,那么就用route resolve来代替。 + *为什么?*:`activate`这个controller使得重用刷新视图的逻辑变得很方便,把所有的逻辑都放到了一起,可以让用户更快地看到视图,可以很轻松地对`ng-view` 或 `ui-view`使用动画,用户体验更好。 + + 注意:如果你需要在开始使用controller之前有条件地取消路由,那么就用[route resolve](#style-y081)来代替。 ```javascript /* avoid */ @@ -1292,10 +1296,17 @@ ###Route Resolve Promises ###### [Style [Y081](#style-y081)] - - 当一个controller依赖于一个promise来解决,那么就在controller的逻辑执行之前在`$routeProvider`中解决这些依赖。如果你需要在controller被激活之前有条件地取消一个路由,那么就用route resolver。 + - 当一个controller依赖于一个需要在controller被激活之前的就resoved的promise,那么就在controller的逻辑执行之前在`$routeProvider`中解决这些依赖。如果你需要在controller被激活之前有条件地取消一个路由,那么就用route resolver。 + + - 当你决定在过渡到视图之前取消路由时,使用route resolve。 *为什么?*:controller在加载前可能需要一些数据,这些数据可能是从一个通过自定义factory或是[$http](https://docs.angularjs.org/api/ng/service/$http)的promise而来的。[route resolve](https://docs.angularjs.org/api/ngRoute/provider/$routeProvider)允许promise在controller的逻辑执行之前解决,因此它可能对从promise中来的数据做一些处理。 + *为什么?*:这段代码将在路由后的controller的激活函数中执行,视图立即加载,数据绑定将在promise resolve之后,可以(通过ng-view或ui-view)在视图的过渡之间可以加个loading状态的动画。 + + 注意:这段代码将在路由之前通过一个promise来执行,拒绝了承诺就会取消路由,接受了就会等待路由跳转到新视图。如果你想更快地进入视图,并且无需验证是否可以进入视图,你可以考虑用[控制器 `activate` 技术](#style-y080)代替。 + + ```javascript /* avoid */ angular @@ -1345,8 +1356,45 @@ vm.movies = moviesPrepService.movies; } ``` - - 注意:示例代码中的`movieService`不是安全压缩的做法,可以到[手动依赖注入](#手动依赖注入)和[压缩和注释](#压缩和注释)部分学习如何安全压缩。 + 注意:下面这个例子展示了命名函数的路由解决,这种方式对于调试和处理依赖注入更加方便。 + + ```javascript + /* even better */ + + // route-config.js + angular + .module('app') + .config(config); + + function config($routeProvider) { + $routeProvider + .when('/avengers', { + templateUrl: 'avengers.html', + controller: 'Avengers', + controllerAs: 'vm', + resolve: { + moviesPrepService: moviesPrepService + } + }); + } + + function moviePrepService(movieService) { + return movieService.getMovies(); + } + + // avengers.js + angular + .module('app') + .controller('Avengers', Avengers); + + Avengers.$inject = ['moviesPrepService']; + function Avengers(moviesPrepService) { + var vm = this; + vm.movies = moviesPrepService.movies; + } + ``` + + 注意:示例代码中的`movieService`不是安全压缩的做法,可以到[手动依赖注入](#手动依赖注入)和[压缩和注释](#压缩和注释)部分学习如何安全压缩。 **[返回顶部](#目录)** @@ -2250,7 +2298,7 @@ ###测试库 ###### [Style [Y191](#style-y191)] - - 用[Jasmine](http://jasmine.github.io/)或者[Mocha](http://visionmedia.github.io/mocha/)进行单元测试。 + - 用[Jasmine](http://jasmine.github.io/)或者[Mocha](http://mochajs.org)进行单元测试。 *为什么?*:AngularJS社区中Jasmine和Mocha都用的很广,两者都很稳定,可维护性好,提供强大的测试功能。 @@ -2307,6 +2355,31 @@ ![测试工具](https://raw.githubusercontent.com/johnpapa/angularjs-styleguide/master/assets/testing-tools.png) +### 组织测试 +###### [Style [Y197](#style-y197)] + + - 把单元测试的文件放到一个独立的`tests`文件夹中,它和你的客户端代码并列。 + + *为什么?*:单元测试和源代码中的每一个组件和文件都有直接的相关性。 + + *为什么?*:这样它就会一直在你的视野中,很容易让它们保持在最新状态。编码的时候无论你做TDD还是在开发过程中测试,或者开发完成后测试,这些单测都不会脱离你的视线和脑海,这样就更容易维护,也有助于保持代码的覆盖率。 + + *为什么?*:更新源代码的时候可以更简单地在同一时间更新测试代码。 + + *为什么?*:方便找。 + + *为什么?*:方便使用grunt或者gulp。 + + ``` + /src/client/app/customers/customer-detail.controller.js + /customer-detail.controller.spec.js + /customers.controller.spec.js + /customers.controller-detail.spec.js + /customers.module.js + /customers.route.js + /customers.route.spec.js + ``` + **[返回顶部](#目录)** @@ -2497,6 +2570,31 @@ })(); ``` +###### [Style [Y241](#style-y241)] + + - 对于一些不需要变动,也不需要从其它service中获取的值,使用常量定义,当一些常量只是在一个模块中使用但是有可能会在其它应用中使用的话,把它们写到一个以当前的模块命名的文件中。把常量集合到一起是非常有必要的,你可以把它们写到`constants.js`的文件中。 + + *为什么?*:一个可能变化的值,即使变动的很少,也会从service中重新被检索,因此你不需要修改源代码。例如,一个数据服务的url可以被放到一个常量中,但是更好的的做法是把它放到一个web service中。 + + *为什么?*:常量可以被注入到任何angular组件中,包括providers。 + + *为什么?*:当一个应用程序被分割成很多可以在其它应用程序中复用的小模块时,每个独立的模块都应该可以操作它自己包含的相关常量。 + + ```javascript + // Constants used by the entire app + angular + .module('app.core') + .constant('moment', moment); + + // Constants used only by the sales module + angular + .module('app.sales') + .constant('events', { + ORDER_CREATED: 'event_order_created', + INVENTORY_DEPLETED: 'event_inventory_depleted' + }); + ``` + **[返回顶部](#目录)** ## AngularJS文档 From e233241fb41631f51f76d4de6fcf41fcee0fc3c4 Mon Sep 17 00:00:00 2001 From: angelochiello Date: Sun, 18 Jan 2015 08:41:11 +0100 Subject: [PATCH 118/567] [it-IT] PR #229 Updated as PR#229 "Fixed mocha link in Style Y191". --- i18n/it-IT.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/i18n/it-IT.md b/i18n/it-IT.md index a8d3f47a..b94cf67a 100644 --- a/i18n/it-IT.md +++ b/i18n/it-IT.md @@ -2326,7 +2326,7 @@ Gli unit test aiutano a mantenere il codice più chiaro, perciò ho incluso alcu ### Librerie per i test ###### [Stile [Y191](#stile-y191)] - - Usa [Jasmine](http://jasmine.github.io/) oppure [Mocha](http://visionmedia.github.io/mocha/) per lo unit testing. + - Usa [Jasmine](http://jasmine.github.io/) oppure [Mocha](http://mochajs.org) per lo unit testing. *Perché?*: Sia Jasmine che Mocha sono largamente utilizzati nella comunità di AngularJS. Entrambi son stabili, ben manutenuti e forniscono funzionalità solide per i test. From 63fcfde946562e61152fc84ed77813c0fd63c72f Mon Sep 17 00:00:00 2001 From: John Papa Date: Sun, 18 Jan 2015 22:05:57 -0500 Subject: [PATCH 119/567] Revert "fix Y075/controllerAs example to account for the isolated scope." --- README.md | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 5a97576f..c2704cd3 100644 --- a/README.md +++ b/README.md @@ -1206,13 +1206,13 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see }, link: linkFunc, controller: ExampleController, - controllerAs: 'vm', - bindToController: true // because the scope is isolated + controllerAs: 'vm' }; - + return directive; function linkFunc(scope, el, attr, ctrl) { + console.log('LINK: scope.max = %i', scope.max); console.log('LINK: scope.vm.min = %i', scope.vm.min); console.log('LINK: scope.vm.max = %i', scope.vm.max); } @@ -1224,8 +1224,9 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see // Injecting $scope just for comparison var vm = this; - vm.min = 3; - console.log('CTRL: $scope.vm.max = %i', $scope.vm.max); + vm.min = 3; + vm.max = $scope.max; + console.log('CTRL: $scope.max = %i', $scope.max); console.log('CTRL: vm.min = %i', vm.min); console.log('CTRL: vm.max = %i', vm.max); } From 5585ed34b0b4e62405fc8526a61cefe302259d3a Mon Sep 17 00:00:00 2001 From: John Papa Date: Sun, 18 Jan 2015 22:09:00 -0500 Subject: [PATCH 120/567] fix for #213 and refactored for PR #216 --- README.md | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index 40105da8..1dfa2250 100644 --- a/README.md +++ b/README.md @@ -1206,15 +1206,17 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see }, link: linkFunc, controller: ExampleController, - controllerAs: 'vm' - }; - + controllerAs: 'vm', + bindToController: true // because the scope is isolated + }; + return directive; function linkFunc(scope, el, attr, ctrl) { - console.log('LINK: scope.max = %i', scope.max); - console.log('LINK: scope.vm.min = %i', scope.vm.min); - console.log('LINK: scope.vm.max = %i', scope.vm.max); + console.log('LINK: scope.min = %s *** should be undefined', scope.min); + console.log('LINK: scope.max = %s *** should be undefined', scope.max); + console.log('LINK: scope.vm.min = %s', scope.vm.min); + console.log('LINK: scope.vm.max = %s', scope.vm.max); } } @@ -1224,16 +1226,17 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see // Injecting $scope just for comparison var vm = this; - vm.min = 3; - vm.max = $scope.max; - console.log('CTRL: $scope.max = %i', $scope.max); - console.log('CTRL: vm.min = %i', vm.min); - console.log('CTRL: vm.max = %i', vm.max); + vm.min = 3; + + console.log('CTRL: $scope.vm.min = %s', $scope.vm.min); + console.log('CTRL: $scope.vm.max = %s', $scope.vm.max); + console.log('CTRL: vm.min = %s', vm.min); + console.log('CTRL: vm.max = %s', vm.max); } ``` ```html - /* example.directive.html */ +

hello world
max={{vm.max}}
min={{vm.min}}
From 0824b560e1d23b110686e9bc726aebd20862e07c Mon Sep 17 00:00:00 2001 From: John Papa Date: Sun, 18 Jan 2015 22:17:03 -0500 Subject: [PATCH 121/567] added bindToController style --- README.md | 47 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/README.md b/README.md index 1dfa2250..bebe13ef 100644 --- a/README.md +++ b/README.md @@ -1242,6 +1242,53 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see
min={{vm.min}}
``` +###### [Style [Y076](#style-y076)] + + - Use `bindToController = true` when using `controller as` syntax with a directive when you want to bind the outer scope to the directive's controller's scope. + + *Why?*: It makes it easy to bind outer scope to the directive's controller scope. + + Note: `bindToController` was introduced in Angular 1.3.0. + + ```html +
+ ``` + + ```javascript + angular + .module('app') + .directive('myExample', myExample); + + function myExample() { + var directive = { + restrict: 'EA', + templateUrl: 'app/feature/example.directive.html', + scope: { + max: '=' + }, + controller: ExampleController, + controllerAs: 'vm', + bindToController: true + }; + + return directive; + } + + function ExampleController() { + var vm = this; + vm.min = 3; + console.log('CTRL: vm.min = %s', vm.min); + console.log('CTRL: vm.max = %s', vm.max); + } + ``` + + ```html + +
hello world
+
max={{vm.max}}
+
min={{vm.min}}
+ ``` + **[Back to top](#table-of-contents)** ## Resolving Promises for a Controller From 3285d3a128b49fccba771439f8c5bef8bd547c73 Mon Sep 17 00:00:00 2001 From: John Papa Date: Sun, 18 Jan 2015 22:27:26 -0500 Subject: [PATCH 122/567] closed #91. adds link to yo generator for hottowel --- README.md | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/README.md b/README.md index bebe13ef..00373e13 100644 --- a/README.md +++ b/README.md @@ -47,6 +47,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see 1. [JSHint](#js-hint) 1. [Constants](#constants) 1. [File Templates and Snippets](#file-templates-and-snippets) + 1. [Yeoman Generator](#yeoman-generator) 1. [AngularJS Docs](#angularjs-docs) 1. [Contributing](#contributing) 1. [License](#license) @@ -2708,6 +2709,28 @@ Use file templates or snippets to help follow consistent styles and patterns. He **[Back to top](#table-of-contents)** +## Yeoman Generator +You can use the [HotTowel yeoman generator](http://jpapa.me/yohottowel) to create an app that serves as a starting point for Angular that follows this style guide. + +1. Install generator-hottowel + + ``` + npm install -g generator-hottowel + ``` + +2. Create a new folder and change directory to it + + ``` + mkdir myapp + cd myapp + ``` + +3. Run the generator + + ``` + yo hottowel helloWorld + ``` + ## AngularJS docs For anything else, API reference, check the [Angular documentation](//docs.angularjs.org/api). From 6acaa4b57ca56671dbf8fc7b9fb580ca90353d2d Mon Sep 17 00:00:00 2001 From: angelochiello Date: Mon, 19 Jan 2015 08:57:43 +0100 Subject: [PATCH 123/567] [it-IT] PR #216 Updated as PR #216 "fix Y075/controllerAs example to account for the isolated scope". --- i18n/it-IT.md | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/i18n/it-IT.md b/i18n/it-IT.md index b94cf67a..2be114d0 100644 --- a/i18n/it-IT.md +++ b/i18n/it-IT.md @@ -1214,12 +1214,12 @@ Nonostante questa guida spieghi i *cosa*, *come* e *perché*, trovo che sia di a }, link: linkFunc, controller : ExampleController, - controllerAs: 'vm' + controllerAs: 'vm', + bindToController: true // because the scope is isolated }; return directive; function linkFunc(scope, el, attr, ctrl) { - console.log('LINK: scope.max = %i', scope.max); console.log('LINK: scope.vm.min = %i', scope.vm.min); console.log('LINK: scope.vm.max = %i', scope.vm.max); } @@ -1232,8 +1232,7 @@ Nonostante questa guida spieghi i *cosa*, *come* e *perché*, trovo che sia di a var vm = this; vm.min = 3; - vm.max = $scope.max; - console.log('CTRL: $scope.max = %i', $scope.max); + console.log('CTRL: $scope.vm.max = %i', $scope.vm.max); console.log('CTRL: vm.min = %i', vm.min); console.log('CTRL: vm.max = %i', vm.max); } From f12769cd0f6aab2969c55e9a4172ca05d69c585b Mon Sep 17 00:00:00 2001 From: angelochiello Date: Mon, 19 Jan 2015 09:03:29 +0100 Subject: [PATCH 124/567] [it-IT] PR #232 Updated as PR #232 "Revert "fix Y075/controllerAs example to account for the isolated scope" --- i18n/it-IT.md | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/i18n/it-IT.md b/i18n/it-IT.md index 2be114d0..9d52864b 100644 --- a/i18n/it-IT.md +++ b/i18n/it-IT.md @@ -1214,12 +1214,12 @@ Nonostante questa guida spieghi i *cosa*, *come* e *perché*, trovo che sia di a }, link: linkFunc, controller : ExampleController, - controllerAs: 'vm', - bindToController: true // because the scope is isolated + controllerAs: 'vm' }; return directive; function linkFunc(scope, el, attr, ctrl) { + console.log('LINK: scope.max = %i', scope.max); console.log('LINK: scope.vm.min = %i', scope.vm.min); console.log('LINK: scope.vm.max = %i', scope.vm.max); } @@ -1231,8 +1231,9 @@ Nonostante questa guida spieghi i *cosa*, *come* e *perché*, trovo che sia di a // Iniettare $scope solo per confronto var vm = this; - vm.min = 3; - console.log('CTRL: $scope.vm.max = %i', $scope.vm.max); + vm.min = 3; + vm.max = $scope.max; + console.log('CTRL: $scope.max = %i', $scope.max console.log('CTRL: vm.min = %i', vm.min); console.log('CTRL: vm.max = %i', vm.max); } From ec040fe0e825b030b144969930be8dfa98a7725a Mon Sep 17 00:00:00 2001 From: angelochiello Date: Mon, 19 Jan 2015 09:09:29 +0100 Subject: [PATCH 125/567] [it-IT] PR #233 Updated as PR #233 "Develop" --- i18n/it-IT.md | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/i18n/it-IT.md b/i18n/it-IT.md index 9d52864b..67777141 100644 --- a/i18n/it-IT.md +++ b/i18n/it-IT.md @@ -1214,14 +1214,16 @@ Nonostante questa guida spieghi i *cosa*, *come* e *perché*, trovo che sia di a }, link: linkFunc, controller : ExampleController, - controllerAs: 'vm' + controllerAs: 'vm', + bindToController: true // because the scope is isolated }; return directive; function linkFunc(scope, el, attr, ctrl) { - console.log('LINK: scope.max = %i', scope.max); - console.log('LINK: scope.vm.min = %i', scope.vm.min); - console.log('LINK: scope.vm.max = %i', scope.vm.max); + console.log('LINK: scope.min = %s *** should be undefined', scope.min); + console.log('LINK: scope.max = %s *** should be undefined', scope.max); + console.log('LINK: scope.vm.min = %s', scope.vm.min); + console.log('LINK: scope.vm.max = %s', scope.vm.max); } } @@ -1232,15 +1234,16 @@ Nonostante questa guida spieghi i *cosa*, *come* e *perché*, trovo che sia di a var vm = this; vm.min = 3; - vm.max = $scope.max; - console.log('CTRL: $scope.max = %i', $scope.max - console.log('CTRL: vm.min = %i', vm.min); - console.log('CTRL: vm.max = %i', vm.max); + + console.log('CTRL: $scope.vm.min = %s', $scope.vm.min); + console.log('CTRL: $scope.vm.max = %s', $scope.vm.max); + console.log('CTRL: vm.min = %s', vm.min); + console.log('CTRL: vm.max = %s', vm.max); } ``` ```html - /* example.directive.html */ +
hello world
max={{vm.max}}
min={{vm.min}}
From 86fdf992b98a9f9fefb93188711ef46ca51b11eb Mon Sep 17 00:00:00 2001 From: angelochiello Date: Mon, 19 Jan 2015 09:18:08 +0100 Subject: [PATCH 126/567] [it-IT] PR #234 Updated as PR #234 "added bindToController style" --- i18n/it-IT.md | 47 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/i18n/it-IT.md b/i18n/it-IT.md index 67777141..6568b344 100644 --- a/i18n/it-IT.md +++ b/i18n/it-IT.md @@ -1249,6 +1249,53 @@ Nonostante questa guida spieghi i *cosa*, *come* e *perché*, trovo che sia di a
min={{vm.min}}
``` +###### [Stile [Y076](#stile-y076)] + + - Usa `bindToController = true` quando usi la sintassi `controller as` con una directive al fine di fare il bind tra lo scope esterno e lo scope del controller della directive. + + *Perché?*: Rende semplice il bind tra lo scope esterno e lo scope del controller delle directive. + + Nota: `bindToController` è stato introdotto con Angular 1.3.0. + + ```html +
+ ``` + + ```javascript + angular + .module('app') + .directive('myExample', myExample); + + function myExample() { + var directive = { + restrict: 'EA', + templateUrl: 'app/feature/example.directive.html', + scope: { + max: '=' + }, + controller: ExampleController, + controllerAs: 'vm', + bindToController: true + }; + + return directive; + } + + function ExampleController() { + var vm = this; + vm.min = 3; + console.log('CTRL: vm.min = %s', vm.min); + console.log('CTRL: vm.max = %s', vm.max); + } + ``` + + ```html + +
hello world
+
max={{vm.max}}
+
min={{vm.min}}
+ ``` + **[Torna all'inizio](#tavola-dei-contenuti)** ## Risoluzioni di promesse per un controller From d909e120d59bee587f64eb942073a18f58d28b81 Mon Sep 17 00:00:00 2001 From: John Papa Date: Mon, 19 Jan 2015 08:33:02 -0500 Subject: [PATCH 127/567] contributions --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 00373e13..f9610742 100644 --- a/README.md +++ b/README.md @@ -2741,8 +2741,8 @@ Open an issue first to discuss potential changes/additions. If you have question *By contributing to this repository you are agreeing to make your content available subject to the license of this repository.* ### Process - 1. Discuss the changes in an Issue. - 2. Open a Pull Request, reference the issue, and explain the change and why it adds value. + 1. Discuss the changes in a GitHub issue. + 2. Open a Pull Request against the develop branch, reference the issue, and explain the change and why it adds value. 3. The Pull Request will be evaluated and either merged or declined. ## License From 3842d6c1155a4208874e92fe684cd82924735d8d Mon Sep 17 00:00:00 2001 From: John Papa Date: Mon, 19 Jan 2015 08:36:05 -0500 Subject: [PATCH 128/567] syncing i18n files --- i18n/it-IT.md | 103 ++++++++++++++++++++++++++++++++++++++++------ i18n/mk-MK.md | 31 +++++++++++++- i18n/zh-CN.md | 110 +++++++++++++++++++++++++++++++++++++++++++++++--- 3 files changed, 224 insertions(+), 20 deletions(-) diff --git a/i18n/it-IT.md b/i18n/it-IT.md index a23b8320..997b687b 100644 --- a/i18n/it-IT.md +++ b/i18n/it-IT.md @@ -8,9 +8,11 @@ Se stai cercando una guida stilistica dogmatica per le sintassi, convenzioni e struttura di applicazioni AngularJS, allora questo fa per te. Gli stili sono basati sulla mia esperienza di sviluppo con [AngularJS](//angularjs.org), presentazioni, [corsi di formazioni di Pluralsight](http://pluralsight.com/training/Authors/Details/john-papa) e del lavoro in team. +L'obbiettivo di questa guida stilistica è di fare da vademecum alla costruzione di applicazioni con AngularJS mostrando le convenzioni che uso e, più importante, perché le uso. + >Se ti piace questa guida, dai un'occhiata al mio corso [AngularJS Patterns: Clean Code](http://jpapa.me/ngclean) (in inglese) su Pluralsight. -L'obbiettivo di questa guida stilistica è di fare da vademecum alla costruzione di applicazioni con AngularJS mostrando le convenzioni che uso e, più importante, perché le uso. + [![AngularJs Patterns: Clean Code](https://raw.githubusercontent.com/johnpapa/angularjs-styleguide/master/assets/ng-clean-code-banner.png)](http://jpapa.me/ngclean) ## Eccezionalità della comunità e riconoscimenti Mai lavorare nel vuoto. Ritengo che la comunità intorno ad AngularJS sia un gruppo incredibile con la passione di condividere le esperienze. Perciò, Todd Motto, un amico ed un esperto di AngularJS, ed io abbiamo collaborato su molti stili e convenzioni. Su molto siamo d'accordo, su altro meno. Ti invito a controllare le [linee guida di Todd](https://github.com/toddmotto/angularjs-styleguide) per avere cognizione del suo approccio e di come paragonarle. @@ -1212,14 +1214,16 @@ Nonostante questa guida spieghi i *cosa*, *come* e *perché*, trovo che sia di a }, link: linkFunc, controller : ExampleController, - controllerAs: 'vm' + controllerAs: 'vm', + bindToController: true // because the scope is isolated }; return directive; function linkFunc(scope, el, attr, ctrl) { - console.log('LINK: scope.max = %i', scope.max); - console.log('LINK: scope.vm.min = %i', scope.vm.min); - console.log('LINK: scope.vm.max = %i', scope.vm.max); + console.log('LINK: scope.min = %s *** should be undefined', scope.min); + console.log('LINK: scope.max = %s *** should be undefined', scope.max); + console.log('LINK: scope.vm.min = %s', scope.vm.min); + console.log('LINK: scope.vm.max = %s', scope.vm.max); } } @@ -1229,16 +1233,64 @@ Nonostante questa guida spieghi i *cosa*, *come* e *perché*, trovo che sia di a // Iniettare $scope solo per confronto var vm = this; - vm.min = 3; - vm.max = $scope.max; - console.log('CTRL: $scope.max = %i', $scope.max); - console.log('CTRL: vm.min = %i', vm.min); - console.log('CTRL: vm.max = %i', vm.max); + vm.min = 3; + + console.log('CTRL: $scope.vm.min = %s', $scope.vm.min); + console.log('CTRL: $scope.vm.max = %s', $scope.vm.max); + console.log('CTRL: vm.min = %s', vm.min); + console.log('CTRL: vm.max = %s', vm.max); } ``` ```html - /* example.directive.html */ + +
hello world
+
max={{vm.max}}
+
min={{vm.min}}
+ ``` + +###### [Stile [Y076](#stile-y076)] + + - Usa `bindToController = true` quando usi la sintassi `controller as` con una directive al fine di fare il bind tra lo scope esterno e lo scope del controller della directive. + + *Perché?*: Rende semplice il bind tra lo scope esterno e lo scope del controller delle directive. + + Nota: `bindToController` è stato introdotto con Angular 1.3.0. + + ```html +
+ ``` + + ```javascript + angular + .module('app') + .directive('myExample', myExample); + + function myExample() { + var directive = { + restrict: 'EA', + templateUrl: 'app/feature/example.directive.html', + scope: { + max: '=' + }, + controller: ExampleController, + controllerAs: 'vm', + bindToController: true + }; + + return directive; + } + + function ExampleController() { + var vm = this; + vm.min = 3; + console.log('CTRL: vm.min = %s', vm.min); + console.log('CTRL: vm.max = %s', vm.max); + } + ``` + + ```html +
hello world
max={{vm.max}}
min={{vm.min}}
@@ -2324,7 +2376,7 @@ Gli unit test aiutano a mantenere il codice più chiaro, perciò ho incluso alcu ### Librerie per i test ###### [Stile [Y191](#stile-y191)] - - Usa [Jasmine](http://jasmine.github.io/) oppure [Mocha](http://visionmedia.github.io/mocha/) per lo unit testing. + - Usa [Jasmine](http://jasmine.github.io/) oppure [Mocha](http://mochajs.org) per lo unit testing. *Perché?*: Sia Jasmine che Mocha sono largamente utilizzati nella comunità di AngularJS. Entrambi son stabili, ben manutenuti e forniscono funzionalità solide per i test. @@ -2381,6 +2433,33 @@ Gli unit test aiutano a mantenere il codice più chiaro, perciò ho incluso alcu ![Strumenti per i test](https://raw.githubusercontent.com/johnpapa/angularjs-styleguide/master/assets/testing-tools.png) +### Organizzazione dei test +###### [Stile [Y197](#stile-y197)] + + - Posiziona i file degli unit test vicino al codice del client. Posiziona le specifiche che coprono l'integrazione con il server o che testano più componenti in una cartella separata `tests`. + + *Perché?*: Gli unit test hanno una correlazione diretta con un componente specifico e un file nei sogenti. + + *Perché?*: È più semplice da tenere aggiornati dal momento che sono sempre a vista. Quando scrivi codice, sia che tu faccia TDD o fai i test durante o dopo lo sviluppo, le scpecifiche sono sempre di fianco e mai fuori dalla vista o dai pensieri, quindi è più probabile che siano aggiornati e ciò consente inoltre a mantenere una migliore copertura del codice. + + *Perché?*: Quando aggiorni i sorgenti, è più semplice andare ad aggiornare anche i test. + + *Perché?*: Posizionarli vicino rende semplice trovarli e spostarli con i sorgenti qualora ciò accada. + + *Perché?*: Avere le specifiche vicino rende più facile al lettore del codice sorgente imparare come il componente dovrebbe essere usato e scoprire le sue limitazioni. + + *Perché?*: Separare le specifiche così da non essere nella build di distribuzione è semplice con grunt o gulp. + + ``` + /src/client/app/customers/customer-detail.controller.js + /customer-detail.controller.spec.js + /customers.controller.spec.js + /customers.controller-detail.spec.js + /customers.module.js + /customers.route.js + /customers.route.spec.js + ``` + **[Torna all'inizio](#tavola-dei-contenuti)** ## Animazioni diff --git a/i18n/mk-MK.md b/i18n/mk-MK.md index 20a94cbb..44d3970a 100644 --- a/i18n/mk-MK.md +++ b/i18n/mk-MK.md @@ -9,9 +9,11 @@ Доколку барате своеволен стил на кодирање за синтакса, конвенции и структурирање на AngularJS апликации, тогаш сте на правилното место. Овие стилови се базирани на моето искуство во развој на [AngularJS](//angularjs.org), презентации, [Pluralsight тренинг курсеви](http://pluralsight.com/training/Authors/Details/john-papa) и работа во тимови. +Целта на овој водич на кодирање е да овозможи насока во развој на AngularJS апликации преку конвенциите што јас ги користам, и уште поважно, зошто ги користам. + >Ако ви се допаѓа овој водич, тогаш проверете ми го курсот [AngularJS Patterns: Clean Code](http://jpapa.me/ngclean) на Pluralsight. -Целта на овој водич на кодирање е да овозможи насока во развој на AngularJS апликации преку конвенциите што јас ги користам, и уште поважно, зошто ги користам. +[![AngularJs Шаблон: Чист Код](https://raw.githubusercontent.com/johnpapa/angularjs-styleguide/master/assets/ng-clean-code-banner.png)](http://jpapa.me/ngclean) ## Величествена заедница и заслуга Никогаш не работи во вакуум. Јас сметам дека AngularJS заедницата е неверојатна група кои се страсни за споделување искуство. Како резултат, јас и мојот пријател кој е AngularJS експерт, Todd Motto соработувавме со многу стилови и конвенции. Се согласуваме на повеќето, додека на останатите се разликуваме. Ве охрабрувам да ги погледнете на [Todd's guidelines](https://github.com/toddmotto/angularjs-styleguide) со цел да добиете осет за неговиот пристап и како се споредува. @@ -25,7 +27,7 @@ ##Преводи [Преводи од овој AngularJS водич на кодирање](https://github.com/johnpapa/angularjs-styleguide/tree/master/i18n) се одржувани од заедницата и можете да ги најдете тука. -## Содржина +## Table of contents 1. [Single Responsibility](#single-responsibility) 1. [IIFE](#iife) @@ -2295,6 +2297,31 @@ ![Алатки за тестирање](https://raw.githubusercontent.com/johnpapa/angularjs-styleguide/master/assets/testing-tools.png) + ### Организирање на тестови +###### [Style [Y197](#style-y197)] + + - Поставете ги датотеките за unit тестови (спецификација) една поред друга во вашиот клиентски код. Поставете ги спецификациите кои ја покриваат интеграцијата со серверот или тестираат повеќе компоненти во посебна `tests` папка. + + *Зошто?*: Unit тестови имаат директна поврзаност со специфична компонента и датотека во изворниот код. + + *Зошто?*: Полесно е временски да ги ажурирате бидејќи секогаш се забележителни. Кога кодирате, дали TDD или тестирате пред или после развојот, специкациите се секогаш една поред друга и никогаш нема да се изгубат, што значи дека треба да се одржуваат притоа подобрувајќи ја покриеноста на кодот. + + *Зошто?*: Кога го ажурирате изворниот код полесно е да ги ажурирате и тестовите во исто време. + + *Зошто?*: Поставувајќи ги една поред друга овозможува полесно пронаоѓање и преместување заедно со изворниот код доколку го преместите. + + *Зошто?*: Разделување на спецификациите така што не се во дистрибуиран build е полесно со grunt или gulp. + + ``` + /src/client/app/customers/customer-detail.controller.js + /customer-detail.controller.spec.js + /customers.controller.spec.js + /customers.controller-detail.spec.js + /customers.module.js + /customers.route.js + /customers.route.spec.js + ``` + **[Назад кон содржината](#table-of-contents)** ## Animations diff --git a/i18n/zh-CN.md b/i18n/zh-CN.md index 982daef8..6797caec 100644 --- a/i18n/zh-CN.md +++ b/i18n/zh-CN.md @@ -8,9 +8,11 @@ 如果你正在寻找一些关于语法、约定和结构化的AngularJS应用的一个有建设性的风格指南,这个repo正适合你。这里所包含的风格是基于我在团队中使用[AngularJS](//angularjs.org)的一些经验、一些演讲和[Pluralsight培训课程](http://pluralsight.com/training/Authors/Details/john-papa)。 +这个风格指南的目的是为构建AngularJS应用提供指导,当然更加重要的是让大家知道我为什么要选择它们。 + >如果你喜欢这个指南,请在Pluralsight上检出我的[AngularJS Patterns: Clean Code](http://jpapa.me/ngclean)。 -这个风格指南的目的是为构建AngularJS应用提供指导,当然更加重要的是让大家知道我为什么要选择它们。 + [![AngularJs Patterns: Clean Code](https://raw.githubusercontent.com/johnpapa/angularjs-styleguide/master/assets/ng-clean-code-banner.png)](http://jpapa.me/ngclean) ## Community Awesomeness and Credit 我发现AngularJS社区是一个热衷于分享经验的令人难以置信的社区,尽管Todd Motto(他是我的一个朋友,也是AngularJS专家)和我合作了多种风格和惯例,但是我们也存在着一些分歧。我鼓励你去看看[Todd的指南](https://github.com/toddmotto/angularjs-styleguide),从其中了解他的做法和它们是如何比较的。 @@ -1253,7 +1255,9 @@ *为什么?*:把启动逻辑放在一个controller中固定的位置可以更方便定位、有更加一致性的测试,并能够避免在controller中到处都是激活逻辑。 - 注意:如果你需要在开始使用controller之前有条件地取消路由,那么就用route resolve来代替。 + *为什么?*:`activate`这个controller使得重用刷新视图的逻辑变得很方便,把所有的逻辑都放到了一起,可以让用户更快地看到视图,可以很轻松地对`ng-view` 或 `ui-view`使用动画,用户体验更好。 + + 注意:如果你需要在开始使用controller之前有条件地取消路由,那么就用[route resolve](#style-y081)来代替。 ```javascript /* avoid */ @@ -1292,10 +1296,17 @@ ###Route Resolve Promises ###### [Style [Y081](#style-y081)] - - 当一个controller依赖于一个promise来解决,那么就在controller的逻辑执行之前在`$routeProvider`中解决这些依赖。如果你需要在controller被激活之前有条件地取消一个路由,那么就用route resolver。 + - 当一个controller依赖于一个需要在controller被激活之前的就resoved的promise,那么就在controller的逻辑执行之前在`$routeProvider`中解决这些依赖。如果你需要在controller被激活之前有条件地取消一个路由,那么就用route resolver。 + + - 当你决定在过渡到视图之前取消路由时,使用route resolve。 *为什么?*:controller在加载前可能需要一些数据,这些数据可能是从一个通过自定义factory或是[$http](https://docs.angularjs.org/api/ng/service/$http)的promise而来的。[route resolve](https://docs.angularjs.org/api/ngRoute/provider/$routeProvider)允许promise在controller的逻辑执行之前解决,因此它可能对从promise中来的数据做一些处理。 + *为什么?*:这段代码将在路由后的controller的激活函数中执行,视图立即加载,数据绑定将在promise resolve之后,可以(通过ng-view或ui-view)在视图的过渡之间可以加个loading状态的动画。 + + 注意:这段代码将在路由之前通过一个promise来执行,拒绝了承诺就会取消路由,接受了就会等待路由跳转到新视图。如果你想更快地进入视图,并且无需验证是否可以进入视图,你可以考虑用[控制器 `activate` 技术](#style-y080)代替。 + + ```javascript /* avoid */ angular @@ -1345,8 +1356,45 @@ vm.movies = moviesPrepService.movies; } ``` - - 注意:示例代码中的`movieService`不是安全压缩的做法,可以到[手动依赖注入](#手动依赖注入)和[压缩和注释](#压缩和注释)部分学习如何安全压缩。 + 注意:下面这个例子展示了命名函数的路由解决,这种方式对于调试和处理依赖注入更加方便。 + + ```javascript + /* even better */ + + // route-config.js + angular + .module('app') + .config(config); + + function config($routeProvider) { + $routeProvider + .when('/avengers', { + templateUrl: 'avengers.html', + controller: 'Avengers', + controllerAs: 'vm', + resolve: { + moviesPrepService: moviesPrepService + } + }); + } + + function moviePrepService(movieService) { + return movieService.getMovies(); + } + + // avengers.js + angular + .module('app') + .controller('Avengers', Avengers); + + Avengers.$inject = ['moviesPrepService']; + function Avengers(moviesPrepService) { + var vm = this; + vm.movies = moviesPrepService.movies; + } + ``` + + 注意:示例代码中的`movieService`不是安全压缩的做法,可以到[手动依赖注入](#手动依赖注入)和[压缩和注释](#压缩和注释)部分学习如何安全压缩。 **[返回顶部](#目录)** @@ -2250,7 +2298,7 @@ ###测试库 ###### [Style [Y191](#style-y191)] - - 用[Jasmine](http://jasmine.github.io/)或者[Mocha](http://visionmedia.github.io/mocha/)进行单元测试。 + - 用[Jasmine](http://jasmine.github.io/)或者[Mocha](http://mochajs.org)进行单元测试。 *为什么?*:AngularJS社区中Jasmine和Mocha都用的很广,两者都很稳定,可维护性好,提供强大的测试功能。 @@ -2307,6 +2355,31 @@ ![测试工具](https://raw.githubusercontent.com/johnpapa/angularjs-styleguide/master/assets/testing-tools.png) +### 组织测试 +###### [Style [Y197](#style-y197)] + + - 把单元测试的文件放到一个独立的`tests`文件夹中,它和你的客户端代码并列。 + + *为什么?*:单元测试和源代码中的每一个组件和文件都有直接的相关性。 + + *为什么?*:这样它就会一直在你的视野中,很容易让它们保持在最新状态。编码的时候无论你做TDD还是在开发过程中测试,或者开发完成后测试,这些单测都不会脱离你的视线和脑海,这样就更容易维护,也有助于保持代码的覆盖率。 + + *为什么?*:更新源代码的时候可以更简单地在同一时间更新测试代码。 + + *为什么?*:方便找。 + + *为什么?*:方便使用grunt或者gulp。 + + ``` + /src/client/app/customers/customer-detail.controller.js + /customer-detail.controller.spec.js + /customers.controller.spec.js + /customers.controller-detail.spec.js + /customers.module.js + /customers.route.js + /customers.route.spec.js + ``` + **[返回顶部](#目录)** @@ -2497,6 +2570,31 @@ })(); ``` +###### [Style [Y241](#style-y241)] + + - 对于一些不需要变动,也不需要从其它service中获取的值,使用常量定义,当一些常量只是在一个模块中使用但是有可能会在其它应用中使用的话,把它们写到一个以当前的模块命名的文件中。把常量集合到一起是非常有必要的,你可以把它们写到`constants.js`的文件中。 + + *为什么?*:一个可能变化的值,即使变动的很少,也会从service中重新被检索,因此你不需要修改源代码。例如,一个数据服务的url可以被放到一个常量中,但是更好的的做法是把它放到一个web service中。 + + *为什么?*:常量可以被注入到任何angular组件中,包括providers。 + + *为什么?*:当一个应用程序被分割成很多可以在其它应用程序中复用的小模块时,每个独立的模块都应该可以操作它自己包含的相关常量。 + + ```javascript + // Constants used by the entire app + angular + .module('app.core') + .constant('moment', moment); + + // Constants used only by the sales module + angular + .module('app.sales') + .constant('events', { + ORDER_CREATED: 'event_order_created', + INVENTORY_DEPLETED: 'event_inventory_depleted' + }); + ``` + **[返回顶部](#目录)** ## AngularJS文档 From 757c5d00d282f97a9648abedb51c554c6b36bc5d Mon Sep 17 00:00:00 2001 From: angelochiello Date: Mon, 19 Jan 2015 18:28:36 +0100 Subject: [PATCH 129/567] [it-IT] PR #236 Updated as PR #236 "Develop". Minor changes. --- i18n/it-IT.md | 29 ++++++++++++++++++++++++++--- 1 file changed, 26 insertions(+), 3 deletions(-) diff --git a/i18n/it-IT.md b/i18n/it-IT.md index 997b687b..5d4a00d7 100644 --- a/i18n/it-IT.md +++ b/i18n/it-IT.md @@ -51,6 +51,7 @@ Nonostante questa guida spieghi i *cosa*, *come* e *perché*, trovo che sia di a 1. [JSHint](#jshint) 1. [Costanti](#costanti) 1. [File Template e Snippet](#file-template-e-snippet) + 1. [Generatore Yeoman](#generatore-yeoman) 1. [Documentazione di AngularJS](#documentazione-di-angularjs) 1. [Contribuire](#contribuire) 1. [Licenza](#licenza) @@ -2722,8 +2723,30 @@ Usa file template o snippet che ti aiutino a seguire stili e schemi consistentem **[Torna all'inizio](#tavola-dei-contenuti)** +## Generatore Yeoman +Puoi usare il [generatore yeoman di HotTowel](http://jpapa.me/yohottowel) per creare un'app che funga da punto di partenza per Angular che segua questa guida stilistica. + +1. Installa generator-hottowel + + ``` + npm install -g generator-hottowel + ``` + +2. Crea un nuova cartella e cambia la directory verso di essa + + ``` + mkdir myapp + cd myapp + ``` + +3. Lancia il generatore + + ``` + yo hottowel helloWorld + ``` + ## Documentazione di AngularJS -For anything else, API reference, check the [Angular documentation](//docs.angularjs.org/api). +Per qualsiasi altro, riferimento alle API, controlla la [documentazione di Angular](//docs.angularjs.org/api). ## Contribuire @@ -2733,8 +2756,8 @@ Apri prima una "issue" per discutere potenziali cambiamenti/aggiunte. Se hai del ### Processo - 1. Discuti i cambiamenti in un Issue. - 2. Apri una Pull Request, fai riferimento all issue e spiega i cambiamenti e perché questi aggiungono valore. + 1. Discuti i cambiamenti in un Issue di Github. + 2. Apri una Pull Request verso la brach develop, fai riferimento all issue e spiega i cambiamenti e perché questi aggiungono valore. 3. La Pull Request sarà vagliata e quindi fatto un merge o declinata. ## Licenza From 0060435fab009f72f89eb3ac6548133d0dd6688d Mon Sep 17 00:00:00 2001 From: John Papa Date: Mon, 19 Jan 2015 17:13:00 -0500 Subject: [PATCH 130/567] added task automation for module files --- README.md | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/README.md b/README.md index f9610742..6b282f67 100644 --- a/README.md +++ b/README.md @@ -48,6 +48,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see 1. [Constants](#constants) 1. [File Templates and Snippets](#file-templates-and-snippets) 1. [Yeoman Generator](#yeoman-generator) + 1. [Task Automation](#task-automation) 1. [AngularJS Docs](#angularjs-docs) 1. [Contributing](#contributing) 1. [License](#license) @@ -2731,6 +2732,31 @@ You can use the [HotTowel yeoman generator](http://jpapa.me/yohottowel) to creat yo hottowel helloWorld ``` +**[Back to top](#table-of-contents)** + +## Task Automation +Use [Gulp](http://gulpjs.com) or [Grunt](http://gruntjs.com) for creating automated tasks. Gulp leans to code over configuration while Grunt leans to configuration over code. I personally prefer Gulp as I feel it is easier to read and write, but both are excellent. + +###### [Style [Y400](#style-y400)] + + - Use task automation to list module definition files `*.module.js` before all other application JavaScript files. + + *Why?*: Angular needs the module definitions to be registered before they are used. + + *Why?*: Naming modules with a specific pattern such as `*.module.js` makes it easy to grab them with a glob and list them first. + + ```javascript + var clientApp = './src/client/app/'; + + // Always grab module files first + var files = [ + clientApp + '**/*.module.js', + clientApp + '**/*.js' + ]; + ``` + +**[Back to top](#table-of-contents)** + ## AngularJS docs For anything else, API reference, check the [Angular documentation](//docs.angularjs.org/api). From 2db59e090dd54731bb20860344a7c35037e7d8e5 Mon Sep 17 00:00:00 2001 From: John Papa Date: Mon, 19 Jan 2015 18:02:45 -0500 Subject: [PATCH 131/567] added routing basics to close #20 --- README.md | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/README.md b/README.md index 6b282f67..f3de2140 100644 --- a/README.md +++ b/README.md @@ -2711,6 +2711,8 @@ Use file templates or snippets to help follow consistent styles and patterns. He **[Back to top](#table-of-contents)** ## Yeoman Generator +###### [Style [Y260](#style-y260)] + You can use the [HotTowel yeoman generator](http://jpapa.me/yohottowel) to create an app that serves as a starting point for Angular that follows this style guide. 1. Install generator-hottowel @@ -2734,6 +2736,29 @@ You can use the [HotTowel yeoman generator](http://jpapa.me/yohottowel) to creat **[Back to top](#table-of-contents)** +## Routing +Client-side routing is important for creating a navigation flow between views and composing views that are made of many smaller templates and directives. + +###### [Style [Y270](#style-y270)] + + - Use the [AngularUI Router](http://angular-ui.github.io/ui-router/) for client-side routing. + + *Why?*: UI Router offers all the features of the Angular router plus a few additional ones including nested routes and states. + + *Why?*: The syntax is quite similar to the Angular router and is easy to migrate to UI Router. + +###### [Style [Y271](#style-y271)] + + - Define routes for views in the module where they exist. Each module should contain the routes for the views in the module. + + *Why?*: Each module should be able to stand on its own. + + *Why?*: When removing a module or adding a module, the app will only contain routes that point to existing views. + + *Why?*: This makes it easy to enable or disable portions of an application without concern over orphaned routes. + +**[Back to top](#table-of-contents)** + ## Task Automation Use [Gulp](http://gulpjs.com) or [Grunt](http://gruntjs.com) for creating automated tasks. Gulp leans to code over configuration while Grunt leans to configuration over code. I personally prefer Gulp as I feel it is easier to read and write, but both are excellent. From 51ca86ef7e2feba70b3e44cb974c01753d6a4d2a Mon Sep 17 00:00:00 2001 From: John Papa Date: Mon, 19 Jan 2015 18:03:14 -0500 Subject: [PATCH 132/567] added routing basics to close #20 --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index f3de2140..e1d805e3 100644 --- a/README.md +++ b/README.md @@ -48,6 +48,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see 1. [Constants](#constants) 1. [File Templates and Snippets](#file-templates-and-snippets) 1. [Yeoman Generator](#yeoman-generator) + 1. [Routing](#routing) 1. [Task Automation](#task-automation) 1. [AngularJS Docs](#angularjs-docs) 1. [Contributing](#contributing) From 9e3b871978726ee65ae874593c8e2852bb5603e8 Mon Sep 17 00:00:00 2001 From: angelochiello Date: Wed, 21 Jan 2015 11:04:05 +0100 Subject: [PATCH 133/567] [it-IT] PRs #240, #241 Updated as PRs: #240 "develop"; #241 "added task automation for module files". --- i18n/it-IT.md | 52 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) diff --git a/i18n/it-IT.md b/i18n/it-IT.md index 5d4a00d7..5866e921 100644 --- a/i18n/it-IT.md +++ b/i18n/it-IT.md @@ -52,6 +52,8 @@ Nonostante questa guida spieghi i *cosa*, *come* e *perché*, trovo che sia di a 1. [Costanti](#costanti) 1. [File Template e Snippet](#file-template-e-snippet) 1. [Generatore Yeoman](#generatore-yeoman) + 1. [Routing](#routing) + 1. [Automazione dei Processi](#automazione-dei-processi) 1. [Documentazione di AngularJS](#documentazione-di-angularjs) 1. [Contribuire](#contribuire) 1. [Licenza](#licenza) @@ -2724,6 +2726,8 @@ Usa file template o snippet che ti aiutino a seguire stili e schemi consistentem **[Torna all'inizio](#tavola-dei-contenuti)** ## Generatore Yeoman +###### [Stile [Y260](#stile-y260)] + Puoi usare il [generatore yeoman di HotTowel](http://jpapa.me/yohottowel) per creare un'app che funga da punto di partenza per Angular che segua questa guida stilistica. 1. Installa generator-hottowel @@ -2745,6 +2749,54 @@ Puoi usare il [generatore yeoman di HotTowel](http://jpapa.me/yohottowel) per cr yo hottowel helloWorld ``` +**[Torna all'inizio](#tavola-dei-contenuti)** + +## Routing +Il routing dal lato client è importante al fine di creare un flusso di navigazione tra le viste e le viste composte che sono fatte da diversi template più piccoli e directive. + +###### [Stile [Y270](#stile-y270)] + + - Usa [AngularUI Router](http://angular-ui.github.io/ui-router/) per il routing dal lato client. + + *Perché?*: UI Router offre tutte le funzionalità del router di Angular più altre che includono route nidificate e stati. + + *Perché?*: La sintassi è piuttosto simile al router di Angular ed è semplice migrare ad UI Router. + +###### [Stile [Y271](#stile-y271)] + + - Definisci le route per le viste nel modulo nel quale esistono. Ogni modulo dovrebbe contenere le route per le viste che si trovano nel modulo. + + *Perché?*: Ogni modulo dovrebbe essere a se stante. + + *Perché?*: Quando rimuovi o aggiungi un modulo, l'app conterrà le route che puntano a viste esistenti. + + *Perché?*: Questo rende semplice abilitare o disabilitare porzioni di una applicazione senza preoccuparsi di route orfane. + +**[Torna all'inizio](#tavola-dei-contenuti)** + +## Automazione dei Processi +Use [Gulp](http://gulpjs.com) or [Grunt](http://gruntjs.com) for creating automated tasks. Gulp leans to code over configuration while Grunt leans to configuration over code. I personally prefer Gulp as I feel it is easier to read and write, but both are excellent. + +###### [Stile [Y400](#stile-y400)] + + - Usa l'automazione dei processi per listare i file che deinifscono i moduli `*.module.js` prima di ogni altro file dell'applicazione di JavaScript. + + *Perché?*: Angular necessita delle definizioni del moduli che devono essere registrati prima del loro utilizzo. + + *Perché?*: Dai i nomi ai moduli usando un pattern specifico quale `*.module.js` rende semplice prenderli con un glob e listarli prima. + + ```javascript + var clientApp = './src/client/app/'; + + // Prendi sempre i file dei moduli prima + var files = [ + clientApp + '**/*.module.js', + clientApp + '**/*.js' + ]; + ``` + +**[Torna all'inizio](#tavola-dei-contenuti)** + ## Documentazione di AngularJS Per qualsiasi altro, riferimento alle API, controlla la [documentazione di Angular](//docs.angularjs.org/api). From e1a3838b6b7a1731f92f2cbaad5127d401700dbf Mon Sep 17 00:00:00 2001 From: angelochiello Date: Wed, 21 Jan 2015 11:10:57 +0100 Subject: [PATCH 134/567] [it-IT] Missinng translantion part about PR #240 Updated with a missing translation part about PR #240. --- i18n/it-IT.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/i18n/it-IT.md b/i18n/it-IT.md index 5866e921..d9e9d48e 100644 --- a/i18n/it-IT.md +++ b/i18n/it-IT.md @@ -2775,7 +2775,7 @@ Il routing dal lato client è importante al fine di creare un flusso di navigazi **[Torna all'inizio](#tavola-dei-contenuti)** ## Automazione dei Processi -Use [Gulp](http://gulpjs.com) or [Grunt](http://gruntjs.com) for creating automated tasks. Gulp leans to code over configuration while Grunt leans to configuration over code. I personally prefer Gulp as I feel it is easier to read and write, but both are excellent. +Usa [Gulp](http://gulpjs.com) o [Grunt](http://gruntjs.com) per la creazione di processi automatizzati. Gulp tende a codice sopra configurazione mentre Grunt tende a configurazione sopra codice. Personalmente preferisco Gulp perché lo percepisco più semplice da leggere e scrivere ma entrambi sono eccellenti. ###### [Stile [Y400](#stile-y400)] From 20083183782b02655f534951673174a7e3e51b0b Mon Sep 17 00:00:00 2001 From: Aleksandar Bogatinov Date: Thu, 22 Jan 2015 16:54:49 +0100 Subject: [PATCH 135/567] Updated to latest version --- i18n/mk-MK.md | 146 ++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 135 insertions(+), 11 deletions(-) diff --git a/i18n/mk-MK.md b/i18n/mk-MK.md index 44d3970a..3e670c9d 100644 --- a/i18n/mk-MK.md +++ b/i18n/mk-MK.md @@ -53,6 +53,9 @@ 1. [JSHint](#js-hint) 1. [Constants](#constants) 1. [File Templates and Snippets](#file-templates-and-snippets) + 1. [Yeoman Generator](#yeoman-generator) + 1. [Routing](#routing) + 1. [Task Automation](#task-automation) 1. [AngularJS Docs](#angularjs-docs) 1. [Contributing](#contributing) 1. [License](#license) @@ -1184,9 +1187,10 @@ return directive; function linkFunc(scope, el, attr, ctrl) { - console.log('LINK: scope.max = %i', scope.max); - console.log('LINK: scope.vm.min = %i', scope.vm.min); - console.log('LINK: scope.vm.max = %i', scope.vm.max); + console.log('LINK: scope.min = %s *** should be undefined', scope.min); + console.log('LINK: scope.max = %s *** should be undefined', scope.max); + console.log('LINK: scope.vm.min = %s', scope.vm.min); + console.log('LINK: scope.vm.max = %s', scope.vm.max); } } @@ -1197,15 +1201,63 @@ var vm = this; vm.min = 3; - vm.max = $scope.max; - console.log('CTRL: $scope.max = %i', $scope.max); - console.log('CTRL: vm.min = %i', vm.min); - console.log('CTRL: vm.max = %i', vm.max); + + console.log('CTRL: $scope.vm.min = %s', $scope.vm.min); + console.log('CTRL: $scope.vm.max = %s', $scope.vm.max); + console.log('CTRL: vm.min = %s', vm.min); + console.log('CTRL: vm.max = %s', vm.max); } ``` ```html - /* example.directive.html */ + +
hello world
+
max={{vm.max}}
+
min={{vm.min}}
+ ``` + +###### [Style [Y076](#style-y076)] + + - Употребете `bindToController = true` кога употребувате `controller as` синтакса со директива чиј scope на контролерот ќе биде поврзан со надворешниот scope. + + *Зошто?*: Полесно е да се поврзе надворешниот scope со тој на контролерот во директивата. + + Забелешка: `bindToController` беше воведен во Angular 1.3.0. + + ```html +
+ ``` + + ```javascript + angular + .module('app') + .directive('myExample', myExample); + + function myExample() { + var directive = { + restrict: 'EA', + templateUrl: 'app/feature/example.directive.html', + scope: { + max: '=' + }, + controller: ExampleController, + controllerAs: 'vm', + bindToController: true + }; + + return directive; + } + + function ExampleController() { + var vm = this; + vm.min = 3; + console.log('CTRL: vm.min = %s', vm.min); + console.log('CTRL: vm.max = %s', vm.max); + } + ``` + + ```html +
hello world
max={{vm.max}}
min={{vm.min}}
@@ -2245,7 +2297,7 @@ ### Библиотеки за тестирање ###### [Style [Y191](#style-Y191)] - - Употребете [Jasmine](http://jasmine.github.io/) или [Mocha](http://visionmedia.github.io/mocha/) за тестирање на единки. + - Употребете [Jasmine](http://jasmine.github.io/) или [Mocha](http://mochajs.org) за тестирање на единки. *Зошто?*: И Jasmine и Mocha се широко употребувани во AngularJS заедницата. И двете се стабилни, добро одржувани и овозможуваат робустни функции за тестирање. @@ -2574,6 +2626,78 @@ angular **[Назад кон содржината](#table-of-contents)** +## Yeoman Generator +###### [Style [Y260](#style-y260)] + +Можете да го употребите [HotTowel yeoman генераторот](http://jpapa.me/yohottowel) да создадете апликација која ќе биде почетна за Angular следејќи го овој водич. + +1. Инсталирајте generator-hottowel + + ``` + npm install -g generator-hottowel + ``` + +2. Создадете нова папка и сменете ја моменталната папка до неа + + ``` + mkdir myapp + cd myapp + ``` + +3. Започнете го генераторот + + ``` + yo hottowel helloWorld + ``` + +**[Назад кон содржината](#table-of-contents)** + +## Routing +Рутирање од клиентска страна е значајно за создавање на тек во навигација помеѓу прегледи и прегледи составени од помали шаблони и директиви. + +###### [Style [Y270](#style-y270)] + + - Употребете го [AngularUI Router](http://angular-ui.github.io/ui-router/) за рутирање од клиентска страна. + + *Зошто?*: UI Router ги овозможува сите функционалности на Angular рутерот плус некои додатни функционалности како вклучување вгнездени рути и состојби. + + *Зошто?*: Синтаксата е прилично слична со Angular рутерот и лесна за миграција на UI Router. + +###### [Style [Y271](#style-y271)] + + - Дефинирајте рути за прегледи во модулот каде постојат. Секој модул треба да содржи рути за прегледите во модулот. + + *Зошто?*: Секој модул треба да си биде независен. + + *Зошто?*: Кога бришеме или додаваме модул, апликација ќе ги содржи рутите кои посочуваат кон постоечките прегледи. + + *Зошто?*: Ова го олеснува вклучување или исклучување на делови од апликацијата без грижи околу рути сирачиња. + +**[Назад кон содржината](#table-of-contents)** + +## Task Automation +Употребете [Gulp](http://gulpjs.com) or [Grunt](http://gruntjs.com) за создавање автоматизирани задачи. Gulp се приклонува кон код наместо подесување додека Grunt се приклонува кон конфигурација наместо код. Јас лично преферирам Gulp бидејќи сметам е полесно за читање и пишување, но и двата се одлични. + +###### [Style [Y400](#style-y400)] + + - Употребете автоматизирање на тестови за вклучување на сите `*.module.js` датотеки пред останатите JavaScript датотеки од апликацијата. + + *Зошто?*: На Angular му требаат дефинициите на модулите да бидат регистрирани пред да бидат употребени. + + *Зошто?*: Именување на модули со слична шема како `*.module.js` е полесно за нивно превземање со glob и да ги постави први. + + ```javascript + var clientApp = './src/client/app/'; + + // Секогаш превземете ги датотеките со модули први + var files = [ + clientApp + '**/*.module.js', + clientApp + '**/*.js' + ]; + ``` + +**[Назад кон содржината](#table-of-contents)** + ## AngularJS Docs За се останато, референцирајте се до неговото API во [Angular документацијата](//docs.angularjs.org/api). @@ -2584,8 +2708,8 @@ angular *Со придонесување до ова складиште, се придржувате вашата содржина да подлежи на лиценцата на ова складиште.* ### Процес - 1. Дискусирајте за промените во Issue. - 2. Отворете Pull Request, поставете референца до Issue и објаснете ја промената и како додава на вредност. + 1. Дискусирајте за промените во Github Issue. + 2. Отворете Pull Request врз develop гранката, поставете референца до Issue и објаснете ја промената и како додава на вредност. 3. Pull Request ќе биде оценето и биде или споено или одбиено. ## License From ed9cb278faf825f9b9f7ca4e82a8221832292d99 Mon Sep 17 00:00:00 2001 From: Guilherme Rv Coelho Date: Sat, 24 Jan 2015 22:53:39 -0200 Subject: [PATCH 136/567] Translate naming conventions to pt-BR --- i18n/PT-BR.md | 27 +++++++++++++-------------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/i18n/PT-BR.md b/i18n/PT-BR.md index befc0d49..0265901d 100644 --- a/i18n/PT-BR.md +++ b/i18n/PT-BR.md @@ -1642,15 +1642,14 @@ ou *Coletores de exceção* ``` ### Route Errors + - Gerencie e log todos os erros de routing utilizando o [`$routeChangeError`](https://docs.angularjs.org/api/ngRoute/service/$route#$routeChangeError). - - Handle and log all routing errors using [`$routeChangeError`](https://docs.angularjs.org/api/ngRoute/service/$route#$routeChangeError). - - *Why?*: Provides a consistent way handle all routing errors. - - *Why?*: Potentially provides a better user experience if a routing error occurs and you route them to a friendly screen with more details or recovery options. + *Por que?*: Fornece uma maneira consistente de gerenciar erros relacionados a routing. + + *Por que?*: Potencialmente fornece uma melhor experiência de usuário se um erro de routing ocorrer e você redirecionar o usuário para uma tela amigável com mais detalhes ou opções de recuperação. ```javascript - /* recommended */ + /* recomendado */ function handleRoutingErrors() { /** * Route cancellation: @@ -1674,18 +1673,18 @@ ou *Coletores de exceção* **[⬆ De volta ao topo ⬆](#tabela-de-conte%C3%BAdo)** -## Naming +## Nomenclatura -### Naming Guidelines +### Diretrizes de Nomenclatura - - Use consistent names for all components following a pattern that describes the component's feature then (optionally) its type. My recommended pattern is `feature.type.js`. There are 2 names for most assets: - * the file name (`avengers.controller.js`) - * the registered component name with Angular (`AvengersController`) - - *Why?*: Naming conventions help provide a consistent way to find content at a glance. Consistency within the project is vital. Consistency with a team is important. Consistency across a company provides tremendous efficiency. + - Use nomes consistentes para todos os componentes seguindo um padrão que descreve a funcionalidade do componente e (opcionalmente) seu tipo. Meu padrão recomendado é `característica.tipo.js`. Existem dois nomes para a maioria dos componentes: + * o nome do arquivo (`avengers.controllers.js`) + * o nome de componente registrado pelo Angular (`AvengersController`) - *Why?*: The naming conventions should simply help you find your code faster and make it easier to understand. + *Por que?*: As convenções de nomenclatura ajudam a fornecer uma maneira consistente de encontrar algo à primeira vista. Consistência dentro do projeto e vital. Consistência dentro de um time é importante. Consistência em toda a empresa proporciona uma enorme eficiência. + *Por que?*: As convenções de nomenclatura deveriam simplesmente te ajudar a encontrar trechos do seu código mais rápido e torná-lo mais fácil de se entender. + ### Feature File Names - Use consistent names for all components following a pattern that describes the component's feature then (optionally) its type. My recommended pattern is `feature.type.js`. From 27eb743b2a86eb587821230c19a9f14537886c93 Mon Sep 17 00:00:00 2001 From: John Papa Date: Thu, 29 Jan 2015 21:16:05 -0500 Subject: [PATCH 137/567] whitespace --- README.md | 220 +++++++++++++++++++++++++++--------------------------- 1 file changed, 110 insertions(+), 110 deletions(-) diff --git a/README.md b/README.md index 3a001fb2..e2f75d48 100644 --- a/README.md +++ b/README.md @@ -2,14 +2,14 @@ *Opinionated AngularJS style guide for teams by [@john_papa](//twitter.com/john_papa)* -If you are looking for an opinionated style guide for syntax, conventions, and structuring AngularJS applications, then step right in. These styles are based on my development experience with [AngularJS](//angularjs.org), presentations, [Pluralsight training courses](http://pluralsight.com/training/Authors/Details/john-papa) and working in teams. +If you are looking for an opinionated style guide for syntax, conventions, and structuring AngularJS applications, then step right in. These styles are based on my development experience with [AngularJS](//angularjs.org), presentations, [Pluralsight training courses](http://pluralsight.com/training/Authors/Details/john-papa) and working in teams. -The purpose of this style guide is to provide guidance on building AngularJS applications by showing the conventions I use and, more importantly, why I choose them. +The purpose of this style guide is to provide guidance on building AngularJS applications by showing the conventions I use and, more importantly, why I choose them. >If you like this guide, check out my [AngularJS Patterns: Clean Code](http://jpapa.me/ngclean) course at Pluralsight. [![AngularJs Patterns: Clean Code](https://raw.githubusercontent.com/johnpapa/angularjs-styleguide/master/assets/ng-clean-code-banner.png)](http://jpapa.me/ngclean) - + ## Community Awesomeness and Credit Never work in a vacuum. I find that the AngularJS community is an incredible group who are passionate about sharing experiences. As such, a friend and AngularJS expert Todd Motto and I have collaborated on many styles and conventions. We agree on most, and some we diverge. I encourage you to check out [Todd's guidelines](https://github.com/toddmotto/angularjs-styleguide) to get a sense for his approach and how it compares. @@ -18,7 +18,7 @@ Many of my styles have been from the many pair programming sessions [Ward Bell]( ## See the Styles in a Sample App While this guide explains the *what*, *why* and *how*, I find it helpful to see them in practice. This guide is accompanied by a sample application that follows these styles and patterns. You can find the [sample application (named modular) here](https://github.com/johnpapa/ng-demos) in the `modular` folder. Feel free to grab it, clone it, or fork it. [Instructions on running it are in its readme](https://github.com/johnpapa/ng-demos/tree/master/modular). -##Translations +##Translations [Translations of this Angular style guide](https://github.com/johnpapa/angularjs-styleguide/tree/master/i18n) are maintained by the community and can be found here. ## Table of Contents @@ -42,7 +42,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see 1. [Startup Logic](#startup-logic) 1. [Angular $ Wrapper Services](#angular--wrapper-services) 1. [Testing](#testing) - 1. [Animations](#animations) + 1. [Animations](#animations) 1. [Comments](#comments) 1. [JSHint](#js-hint) 1. [Constants](#constants) @@ -56,7 +56,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see ## Single Responsibility -### Rule of 1 +### Rule of 1 ###### [Style [Y001](#style-y001)] - Define 1 component per file. @@ -69,7 +69,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see .module('app', ['ngRoute']) .controller('SomeController', SomeController) .factory('someFactory', someFactory); - + function SomeController() { } function someFactory() { } @@ -103,7 +103,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see angular .module('app') .factory('someFactory', someFactory); - + function someFactory() { } ``` @@ -113,7 +113,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see ### JavaScript Closures ###### [Style [Y010](#style-y010)] - - Wrap AngularJS components in an Immediately Invoked Function Expression (IIFE). + - Wrap AngularJS components in an Immediately Invoked Function Expression (IIFE). *Why?*: An IIFE removes variables from the global scope. This helps prevent variables and function declarations from living longer than expected in the global scope, which also helps avoid variable collisions. @@ -126,7 +126,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see .module('app') .factory('logger', logger); - // logger function is added as a global variable + // logger function is added as a global variable function logger() { } // storage.js @@ -134,15 +134,15 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see .module('app') .factory('storage', storage); - // storage function is added as a global variable + // storage function is added as a global variable function storage() { } ``` ```javascript /** - * recommended + * recommended * - * no globals are left behind + * no globals are left behind */ // logger.js @@ -168,7 +168,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see })(); ``` - - Note: For brevity only, the rest of the examples in this guide may omit the IIFE syntax. + - Note: For brevity only, the rest of the examples in this guide may omit the IIFE syntax. - Note: IIFE's prevent test code from reaching private members like regular expressions or helper functions which are often good to unit test directly on their own. However you can test these through accessible members or by exposing them through their own component. For example placing helper functions, regular expressions or constants in their own factory or constant. @@ -179,17 +179,17 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see ### Avoid Naming Collisions ###### [Style [Y020](#style-y020)] - - Use unique naming conventions with separators for sub-modules. + - Use unique naming conventions with separators for sub-modules. - *Why?*: Unique names help avoid module name collisions. Separators help define modules and their submodule hierarchy. For example `app` may be your root module while `app.dashboard` and `app.users` may be modules that are used as dependencies of `app`. + *Why?*: Unique names help avoid module name collisions. Separators help define modules and their submodule hierarchy. For example `app` may be your root module while `app.dashboard` and `app.users` may be modules that are used as dependencies of `app`. ### Definitions (aka Setters) ###### [Style [Y021](#style-y021)] - - Declare modules without a variable using the setter syntax. + - Declare modules without a variable using the setter syntax. *Why?*: With 1 component per file, there is rarely a need to introduce a variable for the module. - + ```javascript /* avoid */ var app = angular.module('app', [ @@ -245,12 +245,12 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see *Why?*: A module should only be created once, then retrieved from that point and after. - Use `angular.module('app', []);` to set a module. - - Use `angular.module('app');` to get a module. + - Use `angular.module('app');` to get a module. ### Named vs Anonymous Functions ###### [Style [Y024](#style-y024)] - - Use named functions instead of passing an anonymous function in as a callback. + - Use named functions instead of passing an anonymous function in as a callback. *Why?*: This produces more readable code, is much easier to debug, and reduces the amount of nested callback code. @@ -289,9 +289,9 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see ### controllerAs View Syntax ###### [Style [Y030](#style-y030)] - - Use the [`controllerAs`](http://www.johnpapa.net/do-you-like-your-angular-controllers-with-or-without-sugar/) syntax over the `classic controller with $scope` syntax. + - Use the [`controllerAs`](http://www.johnpapa.net/do-you-like-your-angular-controllers-with-or-without-sugar/) syntax over the `classic controller with $scope` syntax. - *Why?*: Controllers are constructed, "newed" up, and provide a single new instance, and the `controllerAs` syntax is closer to that of a JavaScript constructor than the `classic $scope syntax`. + *Why?*: Controllers are constructed, "newed" up, and provide a single new instance, and the `controllerAs` syntax is closer to that of a JavaScript constructor than the `classic $scope syntax`. *Why?*: It promotes the use of binding to a "dotted" object in the View (e.g. `customer.name` instead of `name`), which is more contextual, easier to read, and avoids any reference issues that may occur without "dotting". @@ -314,13 +314,13 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see ### controllerAs Controller Syntax ###### [Style [Y031](#style-y031)] - - Use the `controllerAs` syntax over the `classic controller with $scope` syntax. + - Use the `controllerAs` syntax over the `classic controller with $scope` syntax. - The `controllerAs` syntax uses `this` inside controllers which gets bound to `$scope` *Why?*: `controllerAs` is syntactic sugar over `$scope`. You can still bind to the View and still access `$scope` methods. - *Why?*: Helps avoid the temptation of using `$scope` methods inside a controller when it may otherwise be better to avoid them or move them to a factory. Consider using `$scope` in a factory, or if in a controller just when needed. For example when publishing and subscribing events using [`$emit`](https://docs.angularjs.org/api/ng/type/$rootScope.Scope#$emit), [`$broadcast`](https://docs.angularjs.org/api/ng/type/$rootScope.Scope#$broadcast), or [`$on`](https://docs.angularjs.org/api/ng/type/$rootScope.Scope#$on) consider moving these uses to a factory and invoke from the controller. + *Why?*: Helps avoid the temptation of using `$scope` methods inside a controller when it may otherwise be better to avoid them or move them to a factory. Consider using `$scope` in a factory, or if in a controller just when needed. For example when publishing and subscribing events using [`$emit`](https://docs.angularjs.org/api/ng/type/$rootScope.Scope#$emit), [`$broadcast`](https://docs.angularjs.org/api/ng/type/$rootScope.Scope#$broadcast), or [`$on`](https://docs.angularjs.org/api/ng/type/$rootScope.Scope#$on) consider moving these uses to a factory and invoke from the controller. ```javascript /* avoid */ @@ -342,7 +342,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see ###### [Style [Y032](#style-y032)] - Use a capture variable for `this` when using the `controllerAs` syntax. Choose a consistent variable name such as `vm`, which stands for ViewModel. - + *Why?*: The `this` keyword is contextual and when used within a function inside a controller may change its context. Capturing the context of `this` avoids encountering this problem. ```javascript @@ -392,9 +392,9 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see - Place bindable members at the top of the controller, alphabetized, and not spread through the controller code. - *Why?*: Placing bindable members at the top makes it easy to read and helps you instantly identify which members of the controller can be bound and used in the View. + *Why?*: Placing bindable members at the top makes it easy to read and helps you instantly identify which members of the controller can be bound and used in the View. - *Why?*: Setting anonymous functions in-line can be easy, but when those functions are more than 1 line of code they can reduce the readability. Defining the functions below the bindable members (the functions will be hoisted) moves the implementation details down, keeps the bindable members up top, and makes it easier to read. + *Why?*: Setting anonymous functions in-line can be easy, but when those functions are more than 1 line of code they can reduce the readability. Defining the functions below the bindable members (the functions will be hoisted) moves the implementation details down, keeps the bindable members up top, and makes it easier to read. ```javascript /* avoid */ @@ -451,8 +451,8 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see vm.gotoSession = gotoSession; vm.refresh = function() { - /** - * lines + /** + * lines * of * code * affects @@ -489,11 +489,11 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see *Why?*: You never have to worry with function declarations that moving `var a` before `var b` will break your code because `a` depends on `b`. - *Why?*: Order is critical with function expressions + *Why?*: Order is critical with function expressions ```javascript - /** - * avoid + /** + * avoid * Using function expressions. */ function Avengers(dataservice, logger) { @@ -601,7 +601,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see vm.isCreditOk; vm.total = 0; - function checkCredit() { + function checkCredit() { return creditService.isOrderTotalOk(vm.total) .then(function(isOk) { vm.isCreditOk = isOk; }) .catch(showServiceError); @@ -612,16 +612,16 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see ### Keep Controllers Focused ###### [Style [Y037](#style-y037)] - - Define a controller for a view, and try not to reuse the controller for other views. Instead, move reusable logic to factories and keep the controller simple and focused on its view. + - Define a controller for a view, and try not to reuse the controller for other views. Instead, move reusable logic to factories and keep the controller simple and focused on its view. *Why?*: Reusing controllers with several views is brittle and good end to end (e2e) test coverage is required to ensure stability across large applications. ### Assigning Controllers ###### [Style [Y038](#style-y038)] - - When a controller must be paired with a view and either component may be re-used by other controllers or views, define controllers along with their routes. + - When a controller must be paired with a view and either component may be re-used by other controllers or views, define controllers along with their routes. - Note: If a View is loaded via another means besides a route, then use the `ng-controller="Avengers as vm"` syntax. + Note: If a View is loaded via another means besides a route, then use the `ng-controller="Avengers as vm"` syntax. *Why?*: Pairing the controller in the route allows different routes to invoke different pairs of controllers and views. When controllers are assigned in the view using [`ng-controller`](https://docs.angularjs.org/api/ng/directive/ngController), that view is always associated with the same controller. @@ -678,7 +678,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see ### Singletons ###### [Style [Y040](#style-y040)] - - Services are instantiated with the `new` keyword, use `this` for public methods and variables. Since these are so similar to factories, use a factory instead for consistency. + - Services are instantiated with the `new` keyword, use `this` for public methods and variables. Since these are so similar to factories, use a factory instead for consistency. Note: [All AngularJS services are singletons](https://docs.angularjs.org/guide/services). This means that there is only one instance of a given service per injector. @@ -729,9 +729,9 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see ### Accessible Members Up Top ###### [Style [Y052](#style-y052)] - - Expose the callable members of the service (it's interface) at the top, using a technique derived from the [Revealing Module Pattern](http://addyosmani.com/resources/essentialjsdesignpatterns/book/#revealingmodulepatternjavascript). + - Expose the callable members of the service (it's interface) at the top, using a technique derived from the [Revealing Module Pattern](http://addyosmani.com/resources/essentialjsdesignpatterns/book/#revealingmodulepatternjavascript). - *Why?*: Placing the callable members at the top makes it easy to read and helps you instantly identify which members of the service can be called and must be unit tested (and/or mocked). + *Why?*: Placing the callable members at the top makes it easy to read and helps you instantly identify which members of the service can be called and must be unit tested (and/or mocked). *Why?*: This is especially helpful when the file gets longer as it helps avoid the need to scroll to see what is exposed. @@ -741,10 +741,10 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see /* avoid */ function dataService() { var someValue = ''; - function save() { + function save() { /* */ }; - function validate() { + function validate() { /* */ }; @@ -769,11 +769,11 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see //////////// - function save() { + function save() { /* */ }; - function validate() { + function validate() { /* */ }; } @@ -796,7 +796,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see *Why?*: You never have to worry with function declarations that moving `var a` before `var b` will break your code because `a` depends on `b`. - *Why?*: Order is critical with function expressions + *Why?*: Order is critical with function expressions ```javascript /** @@ -926,7 +926,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see } } ``` - + Note: The data service is called from consumers, such as a controller, hiding the implementation from the consumers, as shown below. ```javascript @@ -958,7 +958,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see return vm.avengers; }); } - } + } ``` ### Return a Promise from Data Calls @@ -1012,9 +1012,9 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see ### Limit 1 Per File ###### [Style [Y070](#style-y070)] - - Create one directive per file. Name the file for the directive. + - Create one directive per file. Name the file for the directive. - *Why?*: It is easy to mash all the directives in one file, but difficult to then break those out so some are shared across apps, some across modules, some just for one module. + *Why?*: It is easy to mash all the directives in one file, but difficult to then break those out so some are shared across apps, some across modules, some just for one module. *Why?*: One directive per file is easy to maintain. @@ -1071,7 +1071,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see /** * @desc spinner directive that can be used anywhere across the sales app at a company named Acme * @example
- */ + */ angular .module('sales.widgets') .directive('acmeSalesCustomerInfo', salesCustomerInfo); @@ -1103,7 +1103,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see ### Manipulate DOM in a Directive ###### [Style [Y072](#style-y072)] - - When manipulating the DOM directly, use a directive. If alternative ways can be used such as using CSS to set styles or the [animation services](https://docs.angularjs.org/api/ngAnimate), Angular templating, [`ngShow`](https://docs.angularjs.org/api/ng/directive/ngShow) or [`ngHide`](https://docs.angularjs.org/api/ng/directive/ngHide), then use those instead. For example, if the directive simply hides and shows, use ngHide/ngShow. + - When manipulating the DOM directly, use a directive. If alternative ways can be used such as using CSS to set styles or the [animation services](https://docs.angularjs.org/api/ngAnimate), Angular templating, [`ngShow`](https://docs.angularjs.org/api/ng/directive/ngShow) or [`ngHide`](https://docs.angularjs.org/api/ng/directive/ngHide), then use those instead. For example, if the directive simply hides and shows, use ngHide/ngShow. *Why?*: DOM manipulation can be difficult to test, debug, and there are often better ways (e.g. CSS, animations, templates) @@ -1112,9 +1112,9 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see - Provide a short, unique and descriptive directive prefix such as `acmeSalesCustomerInfo` which is declared in HTML as `acme-sales-customer-info`. - *Why?*: The unique short prefix identifies the directive's context and origin. For example a prefix of `cc-` may indicate that the directive is part of a CodeCamper app while `acme-` may indicate a directive for the Acme company. + *Why?*: The unique short prefix identifies the directive's context and origin. For example a prefix of `cc-` may indicate that the directive is part of a CodeCamper app while `acme-` may indicate a directive for the Acme company. - Note: Avoid `ng-` as these are reserved for AngularJS directives. Research widely used directives to avoid naming conflicts, such as `ion-` for the [Ionic Framework](http://ionicframework.com/). + Note: Avoid `ng-` as these are reserved for AngularJS directives. Research widely used directives to avoid naming conflicts, such as `ion-` for the [Ionic Framework](http://ionicframework.com/). ### Restrict to Elements and Attributes ###### [Style [Y074](#style-y074)] @@ -1157,7 +1157,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see
``` - + ```javascript /* recommended */ angular @@ -1185,7 +1185,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see *Why?*: It makes sense and it's not difficult. - Note: The directive below demonstrates some of the ways you can use scope inside of link and directive controllers, using controllerAs. I in-lined the template just to keep it all in one place. + Note: The directive below demonstrates some of the ways you can use scope inside of link and directive controllers, using controllerAs. I in-lined the template just to keep it all in one place. Note: Regarding dependency injection, see [Manually Identify Dependencies](#manual-annotating-for-dependency-injection). @@ -1251,7 +1251,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see *Why?*: It makes it easy to bind outer scope to the directive's controller scope. - Note: `bindToController` was introduced in Angular 1.3.0. + Note: `bindToController` was introduced in Angular 1.3.0. ```html
@@ -1270,9 +1270,9 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see max: '=' }, controller: ExampleController, - controllerAs: 'vm', - bindToController: true - }; + controllerAs: 'vm', + bindToController: true + }; return directive; } @@ -1300,13 +1300,13 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see ###### [Style [Y080](#style-y080)] - Resolve start-up logic for a controller in an `activate` function. - + *Why?*: Placing start-up logic in a consistent place in the controller makes it easier to locate, more consistent to test, and helps avoid spreading out the activation logic across the controller. *Why?*: The controller `activate` makes it convenient to re-use the logic for a refresh for the controller/View, keeps the logic together, gets the user to the View faster, makes animations easy on the `ng-view` or `ui-view`, and feels snappier to the user. Note: If you need to conditionally cancel the route before you start use the controller, use a [route resolve](#style-y081) instead. - + ```javascript /* avoid */ function Avengers(dataservice) { @@ -1452,7 +1452,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see ###### [Style [Y090](#style-y090)] - Avoid using the shortcut syntax of declaring dependencies without using a minification-safe approach. - + *Why?*: The parameters to the component (e.g. controller, factory, etc) will be converted to mangled variables. For example, `common` and `dataservice` may become `a` or `b` and not be found by AngularJS. ```javascript @@ -1476,19 +1476,19 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see ###### [Style [Y091](#style-y091)] - Use `$inject` to manually identify your dependencies for AngularJS components. - + *Why?*: This technique mirrors the technique used by [`ng-annotate`](https://github.com/olov/ng-annotate), which I recommend for automating the creation of minification safe dependencies. If `ng-annotate` detects injection has already been made, it will not duplicate it. *Why?*: This safeguards your dependencies from being vulnerable to minification issues when parameters may be mangled. For example, `common` and `dataservice` may become `a` or `b` and not be found by AngularJS. - *Why?*: Avoid creating in-line dependencies as long lists can be difficult to read in the array. Also it can be confusing that the array is a series of strings while the last item is the component's function. + *Why?*: Avoid creating in-line dependencies as long lists can be difficult to read in the array. Also it can be confusing that the array is a series of strings while the last item is the component's function. ```javascript /* avoid */ angular .module('app') - .controller('Dashboard', - ['$location', '$routeParams', 'common', 'dataservice', + .controller('Dashboard', + ['$location', '$routeParams', 'common', 'dataservice', function Dashboard($location, $routeParams, common, dataservice) {} ]); ``` @@ -1497,9 +1497,9 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see /* avoid */ angular .module('app') - .controller('Dashboard', + .controller('Dashboard', ['$location', '$routeParams', 'common', 'dataservice', Dashboard]); - + function Dashboard($location, $routeParams, common, dataservice) { } ``` @@ -1516,7 +1516,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see } ``` - Note: When your function is below a return statement the $inject may be unreachable (this may happen in a directive). You can solve this by either moving the $inject above the return statement or by using the alternate array injection syntax. + Note: When your function is below a return statement the $inject may be unreachable (this may happen in a directive). You can solve this by either moving the $inject above the return statement or by using the alternate array injection syntax. Note: [`ng-annotate 0.10.0`](https://github.com/olov/ng-annotate) introduced a feature where it moves the `$inject` to where it is reachable. @@ -1583,10 +1583,10 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see ###### [Style [Y100](#style-y100)] - Use [ng-annotate](//github.com/olov/ng-annotate) for [Gulp](http://gulpjs.com) or [Grunt](http://gruntjs.com) and comment functions that need automated dependency injection using `/** @ngInject */` - + *Why?*: This safeguards your code from any dependencies that may not be using minification-safe practices. - *Why?*: [`ng-min`](https://github.com/btford/ngmin) is deprecated + *Why?*: [`ng-min`](https://github.com/btford/ngmin) is deprecated >I prefer Gulp as I feel it is easier to write, to read, and to debug. @@ -1660,7 +1660,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see ###### [Style [Y101](#style-y101)] - Use [gulp-ng-annotate](https://www.npmjs.org/package/gulp-ng-annotate) or [grunt-ng-annotate](https://www.npmjs.org/package/grunt-ng-annotate) in an automated build task. Inject `/* @ngInject */` prior to any function that has dependencies. - + *Why?*: ng-annotate will catch most dependencies, but it sometimes requires hints using the `/* @ngInject */` syntax. The following code is an example of a gulp task using ngAnnotate @@ -1694,7 +1694,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see ###### [Style [Y110](#style-y110)] - Use a [decorator](https://docs.angularjs.org/api/auto/service/$provide#decorator), at config time using the [`$provide`](https://docs.angularjs.org/api/auto/service/$provide) service, on the [`$exceptionHandler`](https://docs.angularjs.org/api/ng/service/$exceptionHandler) service to perform custom actions when exceptions occur. - + *Why?*: Provides a consistent way to handle uncaught AngularJS exceptions for development-time or run-time. Note: Another option is to override the service instead of using a decorator. This is a fine option, but if you want to keep the default behavior and extend it a decorator is recommended. @@ -1716,9 +1716,9 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see function extendExceptionHandler($delegate, toastr) { return function(exception, cause) { $delegate(exception, cause); - var errorData = { - exception: exception, - cause: cause + var errorData = { + exception: exception, + cause: cause }; /** * Could add the error to a service's collection, @@ -1804,10 +1804,10 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see - Use consistent names for all components following a pattern that describes the component's feature then (optionally) its type. My recommended pattern is `feature.type.js`. There are 2 names for most assets: * the file name (`avengers.controller.js`) * the registered component name with Angular (`AvengersController`) - + *Why?*: Naming conventions help provide a consistent way to find content at a glance. Consistency within the project is vital. Consistency with a team is important. Consistency across a company provides tremendous efficiency. - *Why?*: The naming conventions should simply help you find your code faster and make it easier to understand. + *Why?*: The naming conventions should simply help you find your code faster and make it easier to understand. ### Feature File Names ###### [Style [Y121](#style-y121)] @@ -1820,7 +1820,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see ```javascript /** - * common options + * common options */ // Controllers @@ -1849,7 +1849,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see // constants constants.js - + // module definition avengers.module.js @@ -1859,7 +1859,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see // configuration avengers.config.js - + // directives avenger-profile.directive.js avenger-profile.directive.spec.js @@ -1997,7 +1997,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see ### Modules ###### [Style [Y127](#style-y127)] - - When there are multiple modules, the main module file is named `app.module.js` while other dependent modules are named after what they represent. For example, an admin module is named `admin.module.js`. The respective registered module names would be `app` and `admin`. + - When there are multiple modules, the main module file is named `app.module.js` while other dependent modules are named after what they represent. For example, an admin module is named `admin.module.js`. The respective registered module names would be `app` and `admin`. *Why?*: Provides consistency for multiple module apps, and for expanding to large applications. @@ -2015,7 +2015,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see ### Routes ###### [Style [Y129](#style-y129)] - - Separate route configuration into its own file. Examples might be `app.route.js` for the main module and `admin.route.js` for the `admin` module. Even in smaller apps I prefer this separation from the rest of the configuration. + - Separate route configuration into its own file. Examples might be `app.route.js` for the main module and `admin.route.js` for the `admin` module. Even in smaller apps I prefer this separation from the rest of the configuration. **[Back to top](#table-of-contents)** @@ -2023,12 +2023,12 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see ### LIFT ###### [Style [Y140](#style-y140)] - - Structure your app such that you can `L`ocate your code quickly, `I`dentify the code at a glance, keep the `F`lattest structure you can, and `T`ry to stay DRY. The structure should follow these 4 basic guidelines. + - Structure your app such that you can `L`ocate your code quickly, `I`dentify the code at a glance, keep the `F`lattest structure you can, and `T`ry to stay DRY. The structure should follow these 4 basic guidelines. *Why LIFT?*: Provides a consistent structure that scales well, is modular, and makes it easier to increase developer efficiency by finding code quickly. Another way to check your app structure is to ask yourself: How quickly can you open and work in all of the related files for a feature? When I find my structure is not feeling comfortable, I go back and revisit these LIFT guidelines - + 1. `L`ocating our code is easy 2. `I`dentify code at a glance 3. `F`lat structure as long as we can @@ -2078,7 +2078,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see - Be DRY, but don't go nuts and sacrifice readability. - *Why?*: Being DRY is important, but not crucial if it sacrifices the others in LIFT, which is why I call it T-DRY. I don’t want to type session-view.html for a view because, well, it’s obviously a view. If it is not obvious or by convention, then I name it. + *Why?*: Being DRY is important, but not crucial if it sacrifices the others in LIFT, which is why I call it T-DRY. I don’t want to type session-view.html for a view because, well, it’s obviously a view. If it is not obvious or by convention, then I name it. **[Back to top](#table-of-contents)** @@ -2094,16 +2094,16 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see ### Layout ###### [Style [Y151](#style-y151)] - - Place components that define the overall layout of the application in a folder named `layout`. These may include a shell view and controller may act as the container for the app, navigation, menus, content areas, and other regions. + - Place components that define the overall layout of the application in a folder named `layout`. These may include a shell view and controller may act as the container for the app, navigation, menus, content areas, and other regions. *Why?*: Organizes all layout in a single place re-used throughout the application. ### Folders-by-Feature Structure ###### [Style [Y152](#style-y152)] - - Create folders named for the feature they represent. When a folder grows to contain more than 7 files, start to consider creating a folder for them. Your threshold may be different, so adjust as needed. + - Create folders named for the feature they represent. When a folder grows to contain more than 7 files, start to consider creating a folder for them. Your threshold may be different, so adjust as needed. - *Why?*: A developer can locate the code, identify what each file represents at a glance, the structure is flat as can be, and there is no repetitive nor redundant names. + *Why?*: A developer can locate the code, identify what each file represents at a glance, the structure is flat as can be, and there is no repetitive nor redundant names. *Why?*: The LIFT guidelines are all covered. @@ -2154,12 +2154,12 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see Note: Do not use structuring using folders-by-type. This requires moving to multiple folders when working on a feature and gets unwieldy quickly as the app grows to 5, 10 or 25+ views and controllers (and other features), which makes it more difficult than folder-by-feature to locate files. ```javascript - /* + /* * avoid * Alternative folders-by-type. * I recommend "folders-by-feature", instead. */ - + app/ app.module.js app.config.js @@ -2190,7 +2190,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see speakers.html speaker-detail.html topnav.html - ``` + ``` **[Back to top](#table-of-contents)** @@ -2217,7 +2217,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see *Why?*: Adding additional roles to the application root to get remote data, display views, or other logic not related to pulling the app together muddies the app module and make both sets of features harder to reuse or turn off. - *Why?*: The app module becomes a manifest that describes which modules help define the application. + *Why?*: The app module becomes a manifest that describes which modules help define the application. ### Feature Areas are Modules ###### [Style [Y163](#style-y163)] @@ -2228,7 +2228,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see *Why?*: Sprints or iterations can focus on feature areas and turn them on at the end of the sprint or iteration. - *Why?*: Separating feature areas into modules makes it easier to test the modules in isolation and reuse code. + *Why?*: Separating feature areas into modules makes it easier to test the modules in isolation and reuse code. ### Reusable Blocks are Modules ###### [Style [Y164](#style-y164)] @@ -2244,15 +2244,15 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see ![Modularity and Dependencies](https://raw.githubusercontent.com/johnpapa/angularjs-styleguide/master/assets/modularity-1.png) - *Why?*: The main app module contains a quickly identifiable manifest of the application's features. + *Why?*: The main app module contains a quickly identifiable manifest of the application's features. - *Why?*: Each feature area contains a manifest of what it depends on, so it can be pulled in as a dependency in other applications and still work. + *Why?*: Each feature area contains a manifest of what it depends on, so it can be pulled in as a dependency in other applications and still work. *Why?*: Intra-App features such as shared data services become easy to locate and share from within `app.core` (choose your favorite name for this module). Note: This is a strategy for consistency. There are many good options here. Choose one that is consistent, follows AngularJS's dependency rules, and is easy to maintain and scale. - > My structures vary slightly between projects but they all follow these guidelines for structure and modularity. The implementation may vary depending on the features and the team. In other words, don't get hung up on an exact like-for-like structure but do justify your structure using consistency, maintainability, and efficiency in mind. + > My structures vary slightly between projects but they all follow these guidelines for structure and modularity. The implementation may vary depending on the features and the team. In other words, don't get hung up on an exact like-for-like structure but do justify your structure using consistency, maintainability, and efficiency in mind. > In a small app, you can also consider putting all the shared dependencies in the app module where the feature modules have no direct dependencies. This makes it easier to maintain the smaller application, but makes it harder to reuse modules outside of this application. @@ -2272,7 +2272,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see .module('app') .config(configure); - configure.$inject = + configure.$inject = ['routerHelperProvider', 'exceptionHandlerProvider', 'toastr']; function configure (routerHelperProvider, exceptionHandlerProvider, toastr) { @@ -2398,14 +2398,14 @@ Unit testing helps maintain clean code, as such I included some of my recommenda - Use [PhantomJS](http://phantomjs.org/) to run your tests on a server. - *Why?*: PhantomJS is a headless browser that helps run your tests without needing a "visual" browser. So you do not have to install Chrome, Safari, IE, or other browsers on your server. + *Why?*: PhantomJS is a headless browser that helps run your tests without needing a "visual" browser. So you do not have to install Chrome, Safari, IE, or other browsers on your server. Note: You should still test on all browsers in your environment, as appropriate for your target audience. ### Code Analysis ###### [Style [Y195](#style-y195)] - - Run JSHint on your tests. + - Run JSHint on your tests. *Why?*: Tests are code. JSHint can help identify code quality issues that may cause the test to work improperly. @@ -2427,7 +2427,7 @@ Unit testing helps maintain clean code, as such I included some of my recommenda - Place unit test files (specs) side-by-side with your client code. Place specs that cover server integration or test multiple components in a separate `tests` folder. - *Why?*: Unit tests have a direct correlation to a specific component and file in source code. + *Why?*: Unit tests have a direct correlation to a specific component and file in source code. *Why?*: It is easier to keep them up to date since they are always in sight. When coding whether you do TDD or test during development or test after development, the specs are side-by-side and never out of sight nor mind, and thus more likely to be maintained which also helps maintain code coverage. @@ -2465,7 +2465,7 @@ Unit testing helps maintain clean code, as such I included some of my recommenda ### Sub Second ###### [Style [Y211](#style-y211)] - - Use short durations for animations. I generally start with 300ms and adjust until appropriate. + - Use short durations for animations. I generally start with 300ms and adjust until appropriate. *Why?*: Long animations can have the reverse affect on User Experience and perceived performance by giving the appearance of a slow application. @@ -2521,7 +2521,7 @@ Unit testing helps maintain clean code, as such I included some of my recommenda /** * @name logError * @desc Logs errors - * @param {String} msg Message to log + * @param {String} msg Message to log * @returns {String} * @memberOf Factories.Logger */ @@ -2635,7 +2635,7 @@ Unit testing helps maintain clean code, as such I included some of my recommenda .constant('moment', moment); })(); ``` - + ###### [Style [Y241](#style-y241)] - Use constants for values that do not change and do not come from another service. When constants are used only for a module that may be reused in multiple applications, place constants in a file per module named after the module. Until this is required, keep constants in the main module in a `constants.js` file. @@ -2644,7 +2644,7 @@ Unit testing helps maintain clean code, as such I included some of my recommenda *Why?*: Constants can be injected into any angular component, including providers. - *Why?*: When an application is separated into modules that may be reused in other applications, each stand-alone module should be able to operate on its own including any dependent constants. + *Why?*: When an application is separated into modules that may be reused in other applications, each stand-alone module should be able to operate on its own including any dependent constants. ```javascript // Constants used by the entire app @@ -2669,13 +2669,13 @@ Use file templates or snippets to help follow consistent styles and patterns. He ### Sublime Text ###### [Style [Y250](#style-y250)] - - AngularJS snippets that follow these styles and guidelines. + - AngularJS snippets that follow these styles and guidelines. - - Download the [Sublime Angular snippets](assets/sublime-angular-snippets.zip?raw=true) + - Download the [Sublime Angular snippets](assets/sublime-angular-snippets.zip?raw=true) - Place it in your Packages folder - - Restart Sublime + - Restart Sublime - In a JavaScript file type these commands followed by a `TAB` - + ```javascript ngcontroller // creates an Angular controller ngdirective // creates an Angular directive @@ -2697,7 +2697,7 @@ Use file templates or snippets to help follow consistent styles and patterns. He - AngularJS snippets and file templates that follow these styles and guidelines. You can import them into your WebStorm settings: - - Download the [WebStorm AngularJS file templates and snippets](assets/webstorm-angular-file-template.settings.jar?raw=true) + - Download the [WebStorm AngularJS file templates and snippets](assets/webstorm-angular-file-template.settings.jar?raw=true) - Open WebStorm and go to the `File` menu - Choose the `Import Settings` menu option - Select the file and click `OK` @@ -2793,7 +2793,7 @@ Open an issue first to discuss potential changes/additions. If you have question *By contributing to this repository you are agreeing to make your content available subject to the license of this repository.* ### Process - 1. Discuss the changes in a GitHub issue. + 1. Discuss the changes in a GitHub issue. 2. Open a Pull Request against the develop branch, reference the issue, and explain the change and why it adds value. 3. The Pull Request will be evaluated and either merged or declined. From d4de1f45d941cb77c7f675862bd3071aff151020 Mon Sep 17 00:00:00 2001 From: Marcelo Palladino Date: Fri, 30 Jan 2015 17:16:20 -0200 Subject: [PATCH 138/567] Update PT-BR.md "JavaScriptar" to "JavaScript". --- i18n/PT-BR.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/i18n/PT-BR.md b/i18n/PT-BR.md index 0265901d..8031d586 100644 --- a/i18n/PT-BR.md +++ b/i18n/PT-BR.md @@ -295,7 +295,7 @@ ou *Controladores* - Utilize a sintaxe [`controllerAs`](http://www.johnpapa.net/do-you-like-your-angular-controllers-with-or-without-sugar/) ao invés da sintaxe `clássica controller com $scope`. - **Por que?**: Controllers são construídos, "iniciados", e fornecem um nova instância única, e a sintaxe `controlerAs` é mais próxima de um construtor JavaScriptar do que a `sintaxe clássica do $scope`. + **Por que?**: Controllers são construídos, "iniciados", e fornecem um nova instância única, e a sintaxe `controlerAs` é mais próxima de um construtor JavaScript do que a `sintaxe clássica do $scope`. **Por que?**: Isso promove o uso do binding de um objeto "pontuado", ou seja, com propriedades na View (ex. `customer.name` ao invés de `name`), que é mais contextual, legível, e evita qualquer problema com referências que podem ocorrer sem a "pontuação" From e6849d057984c9057ff76ba449d657f96efac4ea Mon Sep 17 00:00:00 2001 From: Alberto Date: Tue, 3 Feb 2015 19:41:04 +0000 Subject: [PATCH 139/567] es-ES Spanish translations --- i18n/es-ES.md | 2827 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 2827 insertions(+) create mode 100644 i18n/es-ES.md diff --git a/i18n/es-ES.md b/i18n/es-ES.md new file mode 100644 index 00000000..cb11cbcc --- /dev/null +++ b/i18n/es-ES.md @@ -0,0 +1,2827 @@ +# Guía de estilo AngularJS + +*Guía de estilos colaborativa de AngularJS para equipos por [@john_papa](//twitter.com/john_papa)* + +Si estás buscando una guía colaborativa sobre sintaxis, convenciones y estructura de aplicaciones con AngulRJS, este es el sitio. Estos estilos están basados en mi experiencia desarrollando con [AngularJS](//angularjs.org), persentaciones, [Cursos en Pluralsight](http://pluralsight.com/training/Authors/Details/john-papa) y trabajando en equipo. + +El propósito de esta guía de estilos es proporcionar una guía de cómo construir aplicaciones con AngularJS enseñando convenciones que uso y, lo más importante, el porqué. + +>Si te gusta esta guía, écha un vistazo al curso de Pluralsight [AngularJS Patterns: Clean Code](http://jpapa.me/ngclean). + + [![AngularJs Patterns: Clean Code](https://raw.githubusercontent.com/johnpapa/angularjs-styleguide/master/assets/ng-clean-code-banner.png)](http://jpapa.me/ngclean) + +## Asombrosa comunidad y créditos +Nunca trabajes solo. Personalmente, la comunidad de AngularJS es un increíble grupo que apasionado por compartir experiencias. Como por ejemplo, mi amigo y experto AngularJS Todd Motto, con el que he colaborado en muchas de los estilos y convenciones. Estamos de acuerdo en la mayoría, y en otras no. Te recomiendo que le eches un vistazo a [Todd's guidelines](https://github.com/toddmotto/angularjs-styleguide) para que le des sentido a ésta guía y la compares. + +Muchos de los estilos han salido de las muchas sesiones de pair programming que [Ward Bell](http://twitter.com/wardbell) y yo hemos tenido. Aunque no siempre coincidimos, mi amigo Ward me ha ayudado con la última evolución de ésta guía. + +## Mira los estilos en la aplicación de ejemplo +Mientras que esta guía explica el *qué*, *por qué* y *cómo*, me resulta útil verlos en práctica. Ésta guía viene acompañada de una aplicación de ejemplo que sigue los estilos y patrones. La puedes encontrar en [aplicación de ejemplo (llamada modular) aquí](https://github.com/johnpapa/ng-demos) dentro del directorio `modular`. Siéntete libre de cogerla, hacerle clone o un fork. [Instrucciones de cómo arrancarla en su readme](https://github.com/johnpapa/ng-demos/tree/master/modular). + +## Traducciones +[Traducciones de ésta guía de estilos Angular](https://github.com/johnpapa/angularjs-styleguide/tree/master/i18n) son mantenidas por la comunidad y las puedes encontrar aquí. + +## Tabla de contenidos + + 1. [Single Responsibility](#single-responsibility) + 1. [IIFE](#iife) + 1. [Modules](#modules) + 1. [Controllers](#controllers) + 1. [Services](#services) + 1. [Factories](#factories) + 1. [Data Services](#data-services) + 1. [Directives](#directives) + 1. [Resolving Promises for a Controller](#resolving-promises-for-a-controller) + 1. [Manual Annotating for Dependency Injection](#manual-annotating-for-dependency-injection) + 1. [Minification and Annotation](#minification-and-annotation) + 1. [Exception Handling](#exception-handling) + 1. [Naming](#naming) + 1. [Application Structure LIFT Principle](#application-structure-lift-principle) + 1. [Application Structure](#application-structure) + 1. [Modularity](#modularity) + 1. [Startup Logic](#startup-logic) + 1. [Angular $ Wrapper Services](#angular--wrapper-services) + 1. [Testing](#testing) + 1. [Animations](#animations) + 1. [Comments](#comments) + 1. [JSHint](#js-hint) + 1. [Constants](#constants) + 1. [File Templates and Snippets](#file-templates-and-snippets) + 1. [Yeoman Generator](#yeoman-generator) + 1. [Routing](#routing) + 1. [Task Automation](#task-automation) + 1. [AngularJS Docs](#angularjs-docs) + 1. [Contributing](#contributing) + 1. [License](#license) + +## Single Responsibility o Responsabilidad Única + +### La regla del 1 +###### [Style [Y001](#style-y001)] + + - Define 1 componente por fichero. + + El siguiente ejemplo define el módulo `app` y sus dependencias, define un controller, y defines una factory todo en el mismo fichero. + + ```javascript + /* evitar */ + angular + .module('app', ['ngRoute']) + .controller('SomeController', SomeController) + .factory('someFactory', someFactory); + + function SomeController() { } + + function someFactory() { } + ``` + + Los mismos componentes están separados en su propio fichero. + + ```javascript + /* recomendado */ + + // app.module.js + angular + .module('app', ['ngRoute']); + ``` + + ```javascript + /* recomendado */ + + // someController.js + angular + .module('app') + .controller('SomeController', SomeController); + + function SomeController() { } + ``` + + ```javascript + /* recomendado */ + + // someFactory.js + angular + .module('app') + .factory('someFactory', someFactory); + + function someFactory() { } + ``` + +**[Volver arriba](#table-of-contents)** + +## IIFE +### JavaScript Closures +###### [Style [Y010](#style-y010)] + + - Envuelve los componentes AngularJS en una expersiónb de función que se invoca inmediatamente Immediately Invoked Function Expression (IIFE). + + *¿Por qué?*: Una IIFE elimina las variables del scope global. Esto ayuda a prevenir que las variables y las declaraciones de funciones vivan más de lo esperado en el scope global, evitando así colisión de variables. + + *¿Por qué?*: Cuando tu código se minimiza y se empaqueta en un fichero único para desplegar al servidor de producción, podrías tener colisión de variables y muchas variables globales. Una IIFE te protege contra ambos, creando una scope por cada fichero. + + ```javascript + /* evitar */ + // logger.js + angular + .module('app') + .factory('logger', logger); + + // La función logger es añadida como variable global + function logger() { } + + // storage.js + angular + .module('app') + .factory('storage', storage); + + // la función storage es añadida como variable global + function storage() { } + ``` + + ```javascript + /** + * recomendado + * + * así no dejamos ninguna variable global + */ + + // logger.js + (function() { + 'use strict'; + + angular + .module('app') + .factory('logger', logger); + + function logger() { } + })(); + + // storage.js + (function() { + 'use strict'; + + angular + .module('app') + .factory('storage', storage); + + function storage() { } + })(); + ``` + + - Nota: Para acortar únicamente, el resto de ejemplo de esta guía podrían omitir la sintaxis IIFE. + + - Nota: IIFE previente que el código de los tests llegue a sus variables privadas, como expresiones regulares o funciones de ayuda que normalmente vienen bien para hacer pruebas por sí solas. Sin embargo, puedes acceder a ellas creando accesorios o accediendo a través de sus componentes. Por ejemplo, poniendo las funciones de ayuda, expresiones regulares o constantes en su propia factory. + +**[Volver arriba](#table-of-contents)** + +## Modules + +### Evitando la colisión de nombres +###### [Style [Y020](#style-y020)] + + - Use una convención de nombres única con separadores para los sub-módulos. + + *¿Por qué?*: Nombres únicos ayudan a evitar colisiones en los nombres de módulos. Los separadores ayudan a definir los módulos y la jerarquía de sus sub-módulos. Por ejemplo `app` puede ser tu módulo raiz y `app.dashboard` y `app.users` pueden ser módulos que dependen de `app`. + +### Definitions (aka Setters) +###### [Style [Y021](#style-y021)] + + - Declara los módulos sin usar la variable, usando la sintaxis de los setters. + + *¿Por qué?*: Con un componente por fichero, es raro que necesitemos introducir una variable para el módulo. + + ```javascript + /* evitar */ + var app = angular.module('app', [ + 'ngAnimate', + 'ngRoute', + 'app.shared', + 'app.dashboard' + ]); + ``` + + En su lugar usa la sintaxis de los setters + + ```javascript + /* recomendado */ + angular + .module('app', [ + 'ngAnimate', + 'ngRoute', + 'app.shared', + 'app.dashboard' + ]); + ``` + +### Getters +###### [Style [Y022](#style-y022)] + + - Cuando usemos un módulo, evita usar la variable y usando su getter en su lugar. + + *¿Por quñe?*: Esto hace más legible el código y evita que las variables colisionen. + + ```javascript + /* evitar */ + var app = angular.module('app'); + app.controller('SomeController', SomeController); + + function SomeController() { } + ``` + + ```javascript + /* recomendado */ + angular + .module('app') + .controller('SomeController', SomeController); + + function SomeController() { } + ``` + +### Setting vs Getting +###### [Style [Y023](#style-y023)] + + - Setea sólo una vez y usa get para el resto de instancias. + + *¿Por qué?*: Un módulo debe ser creado sólo una vez y recuperado desde ese punto. + + - Usa `angular.module('app', []);` para setear un módulo. + - Usa `angular.module('app');` para recuperar un módulo. + +### Funciones anónimas vs funciones con nombre +###### [Style [Y024](#style-y024)] + + - Usa funciones con nombre en lugar de pasar una función anónima en el callback. + + *¿Por qué?*: Así el código es más legible, es más fácil de debugear, y reduce la cantidad de código anidado en los callbacks. + + ```javascript + /* evitar */ + angular + .module('app') + .controller('Dashboard', function() { }) + .factory('logger', function() { }); + ``` + + ```javascript + /* recomendado */ + + // dashboard.js + angular + .module('app') + .controller('Dashboard', Dashboard); + + function Dashboard() { } + ``` + + ```javascript + // logger.js + angular + .module('app') + .factory('logger', logger); + + function logger() { } + ``` + +**[Volver arriba](#table-of-contents)** + +## Controllers + +### controllerAs View Syntax +###### [Style [Y030](#style-y030)] + + - Usa la sintaxis [`controllerAs`](http://www.johnpapa.net/do-you-like-your-angular-controllers-with-or-without-sugar/) en lugar del `clásico controller con $scope`. + + *¿Por qué?*: Los Controllers se construyen, renuevan y proporcionan una nueva única instancia, y la sintaxis `controllerAs` se acerca más a eso que con la `sintaxis clásico de $scope`. + + *¿Por qué?*: Enlazas el uso del objeto con el "punto" a la View (ej. `customer.name` en lugar de `name`), así es más contextual, fácil de leer y evitas problemas de referencia que pueden aparecer con el "punto". + + *¿Por qué?*: Ayuda a evitar usar `$parent` en las Views con controllers anidados. + + ```html + +
+ {{ name }} +
+ ``` + + ```html + +
+ {{ customer.name }} +
+ ``` + +### controllerAs Controller Syntax +###### [Style [Y031](#style-y031)] + + - Usa la sintaxis `controllerAs` en lugar del `cláxico controller con $scope`. + + - La sintaxis `controllerAs` usa `this` dentro de los controllers que se asocian al `$scope` + + *¿Por qué?*: `controllerAs` es azucar sintáctico sobre el `$scope`. Puedes enlazar a la vista y acceder a los métodos del `$scope`. + + *¿Por qué?*: Ayuda a evitar la tentación de usar los métodos del `$scope` dentro de un controller cuando debería ser mejor evitar usarlos o moverlos a una factory. Considera usar `$scope` en una factory, o en un controlador sólo cuando sea necesario. Por ejemplo cuando publicas y te suscribes a eventos usando [`$emit`](https://docs.angularjs.org/api/ng/type/$rootScope.Scope#$emit), [`$broadcast`](https://docs.angularjs.org/api/ng/type/$rootScope.Scope#$broadcast), o [`$on`](https://docs.angularjs.org/api/ng/type/$rootScope.Scope#$on) considera mover estos usos a una factory e invocarlos desde el controller. + + ```javascript + /* evitar */ + function Customer($scope) { + $scope.name = {}; + $scope.sendMessage = function() { }; + } + ``` + + ```javascript + /* recomendado - pero mira la sección siguiente */ + function Customer() { + this.name = {}; + this.sendMessage = function() { }; + } + ``` + +### controllerAs with vm +###### [Style [Y032](#style-y032)] + + - Usa una variable para capturar `this` cuando uses la sintaxis `controllerAs`. Elige un nombre de variable consistente como `vm`, de ViewModel. + + *¿Por qué?*: La palabra `this` es contextual y cuando es usada dentro de una función en un controller puede cambiar su contexto. Capturando el contexto de `this` te evita encontrarte este problema. + + ```javascript + /* evitar */ + function Customer() { + this.name = {}; + this.sendMessage = function() { }; + } + ``` + + ```javascript + /* recomendado */ + function Customer() { + var vm = this; + vm.name = {}; + vm.sendMessage = function() { }; + } + ``` + + Nota: Puedes evitar los warnings de [jshint](http://www.jshint.com/) escribiendo un comentario encima de la línea de c´pdigo. Sin embargo no hace falta si el nombre de la función empieza por mayúsculas, ya que esa es la convención para las funciones de los constructores, que es lo que un controller en Angular es. + + ```javascript + /* jshint validthis: true */ + var vm = this; + ``` + + Nota: Cuando crees watches en un controller usando `controller as`, puedes observar la variable `vm.*` usando la siguiente sintaxis.(Crea los watchers con precación ya que añaden mucha carca al ciclo de digest) + + ```html + + ``` + + ```javascript + function SomeController($scope, $log) { + var vm = this; + vm.title = 'Some Title'; + + $scope.$watch('vm.title', function(current, original) { + $log.info('vm.title was %s', original); + $log.info('vm.title is now %s', current); + }); + } + ``` + +### Bindable Members Up Top +###### [Style [Y033](#style-y033)] + + - Coloca las asociaciones en la parte superior del controller, por orden alfabético y no separados a lo largo del código del controller. + + *¿Por qué?*: Colocarlas en la parte superior lo hace más fácil de leer y te ayuda a identificar instantáneamente qué variable del controller pueden ser asociadas y usadas en la View. + + *¿Por qué?*: Setear funciones anónimas puede ser fácil, pero cuando esas funciones tienen más de una línea de código se hace menos legible. Definiendo las funciones bajo a las variables, hace que los detalles de implementación estén abajo, deja las variables arriba y las funciones abajo. + + ```javascript + /* evitar */ + function Sessions() { + var vm = this; + + vm.gotoSession = function() { + /* ... */ + }; + vm.refresh = function() { + /* ... */ + }; + vm.search = function() { + /* ... */ + }; + vm.sessions = []; + vm.title = 'Sessions'; + ``` + + ```javascript + /* recomendado */ + function Sessions() { + var vm = this; + + vm.gotoSession = gotoSession; + vm.refresh = refresh; + vm.search = search; + vm.sessions = []; + vm.title = 'Sessions'; + + //////////// + + function gotoSession() { + /* */ + } + + function refresh() { + /* */ + } + + function search() { + /* */ + } + ``` + + ![Controller Using "Above the Fold"](https://raw.githubusercontent.com/johnpapa/angularjs-styleguide/master/assets/above-the-fold-1.png) + + Nota: Si la función es de una línea, déjala arriba, siempre y cuando no afecte en la legibilidad. + + ```javascript + /* evitar */ + function Sessions(data) { + var vm = this; + + vm.gotoSession = gotoSession; + vm.refresh = function() { + /** + * líneas + * de + * código + * que afectan a + * la legibilidad + */ + }; + vm.search = search; + vm.sessions = []; + vm.title = 'Sessions'; + ``` + + ```javascript + /* recomendado */ + function Sessions(dataservice) { + var vm = this; + + vm.gotoSession = gotoSession; + vm.refresh = dataservice.refresh; // 1 liner is OK + vm.search = search; + vm.sessions = []; + vm.title = 'Sessions'; + ``` + +### Function Declarations to Hide Implementation Details +###### [Style [Y034](#style-y034)] + + - Use function declarations to hide implementation details. Keep your bindable members up top. When you need to bind a function in a controller, point it to a function declaration that appears later in the file. This is tied directly to the section Bindable Members Up Top. For more details see [this post](http://www.johnpapa.net/angular-function-declarations-function-expressions-and-readable-code). + + *¿Por qué?*: Placing bindable members at the top makes it easy to read and helps you instantly identify which members of the controller can be bound and used in the View. (Same as above.) + + *¿Por qué?*: Placing the implementation details of a function later in the file moves that complexity out of view so you can see the important stuff up top. + + *¿Por qué?*: Function declaration are hoisted so there are no concerns over using a function before it is defined (as there would be with function expressions). + + *¿Por qué?*: You never have to worry with function declarations that moving `var a` before `var b` will break your code because `a` depends on `b`. + + *¿Por qué?*: Order is critical with function expressions + + ```javascript + /** + * avoid + * Using function expressions. + */ + function Avengers(dataservice, logger) { + var vm = this; + vm.avengers = []; + vm.title = 'Avengers'; + + var activate = function() { + return getAvengers().then(function() { + logger.info('Activated Avengers View'); + }); + } + + var getAvengers = function() { + return dataservice.getAvengers().then(function(data) { + vm.avengers = data; + return vm.avengers; + }); + } + + vm.getAvengers = getAvengers; + + activate(); + } + ``` + + Notice that the important stuff is scattered in the preceding example. In the example below, notice that the important stuff is up top. For example, the members bound to the controller such as `vm.avengers` and `vm.title`. The implementation details are down below. This is just easier to read. + + ```javascript + /* + * recommend + * Using function declarations + * and bindable members up top. + */ + function Avengers(dataservice, logger) { + var vm = this; + vm.avengers = []; + vm.getAvengers = getAvengers; + vm.title = 'Avengers'; + + activate(); + + function activate() { + return getAvengers().then(function() { + logger.info('Activated Avengers View'); + }); + } + + function getAvengers() { + return dataservice.getAvengers().then(function(data) { + vm.avengers = data; + return vm.avengers; + }); + } + } + ``` + +### Defer Controller Logic +###### [Style [Y035](#style-y035)] + + - Defer logic in a controller by delegating to services and factories. + + *¿Por qué?*: Logic may be reused by multiple controllers when placed within a service and exposed via a function. + + *¿Por qué?*: Logic in a service can more easily be isolated in a unit test, while the calling logic in the controller can be easily mocked. + + *¿Por qué?*: Removes dependencies and hides implementation details from the controller. + + ```javascript + + /* avoid */ + function Order($http, $q, config, userInfo) { + var vm = this; + vm.checkCredit = checkCredit; + vm.isCreditOk; + vm.total = 0; + + function checkCredit() { + var settings = {}; + // Get the credit service base URL from config + // Set credit service required headers + // Prepare URL query string or data object with request data + // Add user-identifying info so service gets the right credit limit for this user. + // Use JSONP for this browser if it doesn't support CORS + return $http.get(settings) + .then(function(data) { + // Unpack JSON data in the response object + // to find maxRemainingAmount + vm.isCreditOk = vm.total <= maxRemainingAmount + }) + .catch(function(error) { + // Interpret error + // Cope w/ timeout? retry? try alternate service? + // Re-reject with appropriate error for a user to see + }); + }; + } + ``` + + ```javascript + /* recommended */ + function Order(creditService) { + var vm = this; + vm.checkCredit = checkCredit; + vm.isCreditOk; + vm.total = 0; + + function checkCredit() { + return creditService.isOrderTotalOk(vm.total) + .then(function(isOk) { vm.isCreditOk = isOk; }) + .catch(showServiceError); + }; + } + ``` + +### Keep Controllers Focused +###### [Style [Y037](#style-y037)] + + - Define a controller for a view, and try not to reuse the controller for other views. Instead, move reusable logic to factories and keep the controller simple and focused on its view. + + *¿Por qué?*: Reusing controllers with several views is brittle and good end to end (e2e) test coverage is required to ensure stability across large applications. + +### Assigning Controllers +###### [Style [Y038](#style-y038)] + + - When a controller must be paired with a view and either component may be re-used by other controllers or views, define controllers along with their routes. + + Note: If a View is loaded via another means besides a route, then use the `ng-controller="Avengers as vm"` syntax. + + *¿Por qué?*: Pairing the controller in the route allows different routes to invoke different pairs of controllers and views. When controllers are assigned in the view using [`ng-controller`](https://docs.angularjs.org/api/ng/directive/ngController), that view is always associated with the same controller. + + ```javascript + /* avoid - when using with a route and dynamic pairing is desired */ + + // route-config.js + angular + .module('app') + .config(config); + + function config($routeProvider) { + $routeProvider + .when('/avengers', { + templateUrl: 'avengers.html' + }); + } + ``` + + ```html + +
+
+ ``` + + ```javascript + /* recommended */ + + // route-config.js + angular + .module('app') + .config(config); + + function config($routeProvider) { + $routeProvider + .when('/avengers', { + templateUrl: 'avengers.html', + controller: 'Avengers', + controllerAs: 'vm' + }); + } + ``` + + ```html + +
+
+ ``` + +**[Volver arriba](#table-of-contents)** + +## Services + +### Singletons +###### [Style [Y040](#style-y040)] + + - Services are instantiated with the `new` keyword, use `this` for public methods and variables. Since these are so similar to factories, use a factory instead for consistency. + + Note: [All AngularJS services are singletons](https://docs.angularjs.org/guide/services). This means that there is only one instance of a given service per injector. + + ```javascript + // service + angular + .module('app') + .service('logger', logger); + + function logger() { + this.logError = function(msg) { + /* */ + }; + } + ``` + + ```javascript + // factory + angular + .module('app') + .factory('logger', logger); + + function logger() { + return { + logError: function(msg) { + /* */ + } + }; + } + ``` + +**[Volver arriba](#table-of-contents)** + +## Factories + +### Single Responsibility +###### [Style [Y050](#style-y050)] + + - Factories should have a [single responsibility](http://en.wikipedia.org/wiki/Single_responsibility_principle), that is encapsulated by its context. Once a factory begins to exceed that singular purpose, a new factory should be created. + +### Singletons +###### [Style [Y051](#style-y051)] + + - Factories are singletons and return an object that contains the members of the service. + + Note: [All AngularJS services are singletons](https://docs.angularjs.org/guide/services). + +### Accessible Members Up Top +###### [Style [Y052](#style-y052)] + + - Expose the callable members of the service (it's interface) at the top, using a technique derived from the [Revealing Module Pattern](http://addyosmani.com/resources/essentialjsdesignpatterns/book/#revealingmodulepatternjavascript). + + *¿Por qué?*: Placing the callable members at the top makes it easy to read and helps you instantly identify which members of the service can be called and must be unit tested (and/or mocked). + + *¿Por qué?*: This is especially helpful when the file gets longer as it helps avoid the need to scroll to see what is exposed. + + *¿Por qué?*: Setting functions as you go can be easy, but when those functions are more than 1 line of code they can reduce the readability and cause more scrolling. Defining the callable interface via the returned service moves the implementation details down, keeps the callable interface up top, and makes it easier to read. + + ```javascript + /* avoid */ + function dataService() { + var someValue = ''; + function save() { + /* */ + }; + function validate() { + /* */ + }; + + return { + save: save, + someValue: someValue, + validate: validate + }; + } + ``` + + ```javascript + /* recommended */ + function dataService() { + var someValue = ''; + var service = { + save: save, + someValue: someValue, + validate: validate + }; + return service; + + //////////// + + function save() { + /* */ + }; + + function validate() { + /* */ + }; + } + ``` + + This way bindings are mirrored across the host object, primitive values cannot update alone using the revealing module pattern + + ![Factories Using "Above the Fold"](https://raw.githubusercontent.com/johnpapa/angularjs-styleguide/master/assets/above-the-fold-2.png) + +### Function Declarations to Hide Implementation Details +###### [Style [Y053](#style-y053)] + + - Use function declarations to hide implementation details. Keep your accessible members of the factory up top. Point those to function declarations that appears later in the file. For more details see [this post](http://www.johnpapa.net/angular-function-declarations-function-expressions-and-readable-code). + + *¿Por qué?*: Placing accessible members at the top makes it easy to read and helps you instantly identify which functions of the factory you can access externally. + + *¿Por qué?*: Placing the implementation details of a function later in the file moves that complexity out of view so you can see the important stuff up top. + + *¿Por qué?*: Function declaration are hoisted so there are no concerns over using a function before it is defined (as there would be with function expressions). + + *¿Por qué?*: You never have to worry with function declarations that moving `var a` before `var b` will break your code because `a` depends on `b`. + + *¿Por qué?*: Order is critical with function expressions + + ```javascript + /** + * avoid + * Using function expressions + */ + function dataservice($http, $location, $q, exception, logger) { + var isPrimed = false; + var primePromise; + + var getAvengers = function() { + // implementation details go here + }; + + var getAvengerCount = function() { + // implementation details go here + }; + + var getAvengersCast = function() { + // implementation details go here + }; + + var prime = function() { + // implementation details go here + }; + + var ready = function(nextPromises) { + // implementation details go here + }; + + var service = { + getAvengersCast: getAvengersCast, + getAvengerCount: getAvengerCount, + getAvengers: getAvengers, + ready: ready + }; + + return service; + } + ``` + + ```javascript + /** + * recommended + * Using function declarations + * and accessible members up top. + */ + function dataservice($http, $location, $q, exception, logger) { + var isPrimed = false; + var primePromise; + + var service = { + getAvengersCast: getAvengersCast, + getAvengerCount: getAvengerCount, + getAvengers: getAvengers, + ready: ready + }; + + return service; + + //////////// + + function getAvengers() { + // implementation details go here + } + + function getAvengerCount() { + // implementation details go here + } + + function getAvengersCast() { + // implementation details go here + } + + function prime() { + // implementation details go here + } + + function ready(nextPromises) { + // implementation details go here + } + } + ``` + +**[Volver arriba](#table-of-contents)** + +## Data Services + +### Separate Data Calls +###### [Style [Y060](#style-y060)] + + - Refactor logic for making data operations and interacting with data to a factory. Make data services responsible for XHR calls, local storage, stashing in memory, or any other data operations. + + *¿Por qué?*: The controller's responsibility is for the presentation and gathering of information for the view. It should not care how it gets the data, just that it knows who to ask for it. Separating the data services moves the logic on how to get it to the data service, and lets the controller be simpler and more focused on the view. + + *¿Por qué?*: This makes it easier to test (mock or real) the data calls when testing a controller that uses a data service. + + *¿Por qué?*: Data service implementation may have very specific code to handle the data repository. This may include headers, how to talk to the data, or other services such as $http. Separating the logic into a data service encapsulates this logic in a single place hiding the implementation from the outside consumers (perhaps a controller), also making it easier to change the implementation. + + ```javascript + /* recommended */ + + // dataservice factory + angular + .module('app.core') + .factory('dataservice', dataservice); + + dataservice.$inject = ['$http', 'logger']; + + function dataservice($http, logger) { + return { + getAvengers: getAvengers + }; + + function getAvengers() { + return $http.get('/api/maa') + .then(getAvengersComplete) + .catch(getAvengersFailed); + + function getAvengersComplete(response) { + return response.data.results; + } + + function getAvengersFailed(error) { + logger.error('XHR Failed for getAvengers.' + error.data); + } + } + } + ``` + + Note: The data service is called from consumers, such as a controller, hiding the implementation from the consumers, as shown below. + + ```javascript + /* recommended */ + + // controller calling the dataservice factory + angular + .module('app.avengers') + .controller('Avengers', Avengers); + + Avengers.$inject = ['dataservice', 'logger']; + + function Avengers(dataservice, logger) { + var vm = this; + vm.avengers = []; + + activate(); + + function activate() { + return getAvengers().then(function() { + logger.info('Activated Avengers View'); + }); + } + + function getAvengers() { + return dataservice.getAvengers() + .then(function(data) { + vm.avengers = data; + return vm.avengers; + }); + } + } + ``` + +### Return a Promise from Data Calls +###### [Style [Y061](#style-y061)] + + - When calling a data service that returns a promise such as $http, return a promise in your calling function too. + + *¿Por qué?*: You can chain the promises together and take further action after the data call completes and resolves or rejects the promise. + + ```javascript + /* recommended */ + + activate(); + + function activate() { + /** + * Step 1 + * Ask the getAvengers function for the + * avenger data and wait for the promise + */ + return getAvengers().then(function() { + /** + * Step 4 + * Perform an action on resolve of final promise + */ + logger.info('Activated Avengers View'); + }); + } + + function getAvengers() { + /** + * Step 2 + * Ask the data service for the data and wait + * for the promise + */ + return dataservice.getAvengers() + .then(function(data) { + /** + * Step 3 + * set the data and resolve the promise + */ + vm.avengers = data; + return vm.avengers; + }); + } + ``` + + **[Volver arriba](#table-of-contents)** + +## Directives +### Limit 1 Per File +###### [Style [Y070](#style-y070)] + + - Create one directive per file. Name the file for the directive. + + *¿Por qué?*: It is easy to mash all the directives in one file, but difficult to then break those out so some are shared across apps, some across modules, some just for one module. + + *¿Por qué?*: One directive per file is easy to maintain. + + ```javascript + /* avoid */ + /* directives.js */ + + angular + .module('app.widgets') + + /* order directive that is specific to the order module */ + .directive('orderCalendarRange', orderCalendarRange) + + /* sales directive that can be used anywhere across the sales app */ + .directive('salesCustomerInfo', salesCustomerInfo) + + /* spinner directive that can be used anywhere across apps */ + .directive('sharedSpinner', sharedSpinner); + + function orderCalendarRange() { + /* implementation details */ + } + + function salesCustomerInfo() { + /* implementation details */ + } + + function sharedSpinner() { + /* implementation details */ + } + ``` + + ```javascript + /* recommended */ + /* calendarRange.directive.js */ + + /** + * @desc order directive that is specific to the order module at a company named Acme + * @example
+ */ + angular + .module('sales.order') + .directive('acmeOrderCalendarRange', orderCalendarRange); + + function orderCalendarRange() { + /* implementation details */ + } + ``` + + ```javascript + /* recommended */ + /* customerInfo.directive.js */ + + /** + * @desc spinner directive that can be used anywhere across the sales app at a company named Acme + * @example
+ */ + angular + .module('sales.widgets') + .directive('acmeSalesCustomerInfo', salesCustomerInfo); + + function salesCustomerInfo() { + /* implementation details */ + } + ``` + + ```javascript + /* recommended */ + /* spinner.directive.js */ + + /** + * @desc spinner directive that can be used anywhere across apps at a company named Acme + * @example
+ */ + angular + .module('shared.widgets') + .directive('acmeSharedSpinner', sharedSpinner); + + function sharedSpinner() { + /* implementation details */ + } + ``` + + Note: There are many naming options for directives, especially since they can be used in narrow or wide scopes. Choose one that makes the directive and it's file name distinct and clear. Some examples are below, but see the naming section for more recommendations. + +### Manipulate DOM in a Directive +###### [Style [Y072](#style-y072)] + + - When manipulating the DOM directly, use a directive. If alternative ways can be used such as using CSS to set styles or the [animation services](https://docs.angularjs.org/api/ngAnimate), Angular templating, [`ngShow`](https://docs.angularjs.org/api/ng/directive/ngShow) or [`ngHide`](https://docs.angularjs.org/api/ng/directive/ngHide), then use those instead. For example, if the directive simply hides and shows, use ngHide/ngShow. + + *¿Por qué?*: DOM manipulation can be difficult to test, debug, and there are often better ways (e.g. CSS, animations, templates) + +### Provide a Unique Directive Prefix +###### [Style [Y073](#style-y073)] + + - Provide a short, unique and descriptive directive prefix such as `acmeSalesCustomerInfo` which is declared in HTML as `acme-sales-customer-info`. + + *¿Por qué?*: The unique short prefix identifies the directive's context and origin. For example a prefix of `cc-` may indicate that the directive is part of a CodeCamper app while `acme-` may indicate a directive for the Acme company. + + Note: Avoid `ng-` as these are reserved for AngularJS directives. Research widely used directives to avoid naming conflicts, such as `ion-` for the [Ionic Framework](http://ionicframework.com/). + +### Restrict to Elements and Attributes +###### [Style [Y074](#style-y074)] + + - When creating a directive that makes sense as a stand-alone element, allow restrict `E` (custom element) and optionally restrict `A` (custom attribute). Generally, if it could be its own control, `E` is appropriate. General guideline is allow `EA` but lean towards implementing as an element when its stand-alone and as an attribute when it enhances its existing DOM element. + + *¿Por qué?*: It makes sense. + + *¿Por qué?*: While we can allow the directive to be used as a class, if the directive is truly acting as an element it makes more sense as an element or at least as an attribute. + + Note: EA is the default for AngularJS 1.3 + + + ```html + +
+ ``` + + ```javascript + /* avoid */ + angular + .module('app.widgets') + .directive('myCalendarRange', myCalendarRange); + + function myCalendarRange() { + var directive = { + link: link, + templateUrl: '/template/is/located/here.html', + restrict: 'C' + }; + return directive; + + function link(scope, element, attrs) { + /* */ + } + } + ``` + + ```html + + +
+ ``` + + ```javascript + /* recommended */ + angular + .module('app.widgets') + .directive('myCalendarRange', myCalendarRange); + + function myCalendarRange() { + var directive = { + link: link, + templateUrl: '/template/is/located/here.html', + restrict: 'EA' + }; + return directive; + + function link(scope, element, attrs) { + /* */ + } + } + ``` + +### Directives and ControllerAs +###### [Style [Y075](#style-y075)] + + - Use `controller as` syntax with a directive to be consistent with using `controller as` with view and controller pairings. + + *¿Por qué?*: It makes sense and it's not difficult. + + Note: The directive below demonstrates some of the ways you can use scope inside of link and directive controllers, using controllerAs. I in-lined the template just to keep it all in one place. + + Note: Regarding dependency injection, see [Manually Identify Dependencies](#manual-annotating-for-dependency-injection). + + Note: Note that the directive's controller is outside the directive's closure. This style eliminates issues where the injection gets created as unreachable code after a `return`. + + ```html +
+ ``` + + ```javascript + angular + .module('app') + .directive('myExample', myExample); + + function myExample() { + var directive = { + restrict: 'EA', + templateUrl: 'app/feature/example.directive.html', + scope: { + max: '=' + }, + link: linkFunc, + controller: ExampleController, + controllerAs: 'vm', + bindToController: true // because the scope is isolated + }; + + return directive; + + function linkFunc(scope, el, attr, ctrl) { + console.log('LINK: scope.min = %s *** should be undefined', scope.min); + console.log('LINK: scope.max = %s *** should be undefined', scope.max); + console.log('LINK: scope.vm.min = %s', scope.vm.min); + console.log('LINK: scope.vm.max = %s', scope.vm.max); + } + } + + ExampleController.$inject = ['$scope']; + + function ExampleController($scope) { + // Injecting $scope just for comparison + var vm = this; + + vm.min = 3; + + console.log('CTRL: $scope.vm.min = %s', $scope.vm.min); + console.log('CTRL: $scope.vm.max = %s', $scope.vm.max); + console.log('CTRL: vm.min = %s', vm.min); + console.log('CTRL: vm.max = %s', vm.max); + } + ``` + + ```html + +
hello world
+
max={{vm.max}}
+
min={{vm.min}}
+ ``` + +###### [Style [Y076](#style-y076)] + + - Use `bindToController = true` when using `controller as` syntax with a directive when you want to bind the outer scope to the directive's controller's scope. + + *¿Por qué?*: It makes it easy to bind outer scope to the directive's controller scope. + + Note: `bindToController` was introduced in Angular 1.3.0. + + ```html +
+ ``` + + ```javascript + angular + .module('app') + .directive('myExample', myExample); + + function myExample() { + var directive = { + restrict: 'EA', + templateUrl: 'app/feature/example.directive.html', + scope: { + max: '=' + }, + controller: ExampleController, + controllerAs: 'vm', + bindToController: true + }; + + return directive; + } + + function ExampleController() { + var vm = this; + vm.min = 3; + console.log('CTRL: vm.min = %s', vm.min); + console.log('CTRL: vm.max = %s', vm.max); + } + ``` + + ```html + +
hello world
+
max={{vm.max}}
+
min={{vm.min}}
+ ``` + +**[Volver arriba](#table-of-contents)** + +## Resolving Promises for a Controller + +### Controller Activation Promises +###### [Style [Y080](#style-y080)] + + - Resolve start-up logic for a controller in an `activate` function. + + *¿Por qué?*: Placing start-up logic in a consistent place in the controller makes it easier to locate, more consistent to test, and helps avoid spreading out the activation logic across the controller. + + *¿Por qué?*: The controller `activate` makes it convenient to re-use the logic for a refresh for the controller/View, keeps the logic together, gets the user to the View faster, makes animations easy on the `ng-view` or `ui-view`, and feels snappier to the user. + + Note: If you need to conditionally cancel the route before you start use the controller, use a [route resolve](#style-y081) instead. + + ```javascript + /* avoid */ + function Avengers(dataservice) { + var vm = this; + vm.avengers = []; + vm.title = 'Avengers'; + + dataservice.getAvengers().then(function(data) { + vm.avengers = data; + return vm.avengers; + }); + } + ``` + + ```javascript + /* recommended */ + function Avengers(dataservice) { + var vm = this; + vm.avengers = []; + vm.title = 'Avengers'; + + activate(); + + //////////// + + function activate() { + return dataservice.getAvengers().then(function(data) { + vm.avengers = data; + return vm.avengers; + }); + } + } + ``` + +### Route Resolve Promises +###### [Style [Y081](#style-y081)] + + - When a controller depends on a promise to be resolved before the controller is activated, resolve those dependencies in the `$routeProvider` before the controller logic is executed. If you need to conditionally cancel a route before the controller is activated, use a route resolver. + + - Use a route resolve when you want to decide to cancel the route before ever transitioning to the View. + + *¿Por qué?*: A controller may require data before it loads. That data may come from a promise via a custom factory or [$http](https://docs.angularjs.org/api/ng/service/$http). Using a [route resolve](https://docs.angularjs.org/api/ngRoute/provider/$routeProvider) allows the promise to resolve before the controller logic executes, so it might take action based on that data from the promise. + + *¿Por qué?*: The code executes after the route and in the controller’s activate function. The View starts to load right away. Data binding kicks in when the activate promise resolves. A “busy” animation can be shown during the view transition (via ng-view or ui-view) + + Note: The code executes before the route via a promise. Rejecting the promise cancels the route. Resolve makes the new view wait for the route to resolve. A “busy” animation can be shown before the resolve and through the view transition. If you want to get to the View faster and do not require a checkpoint to decide if you can get to the View, consider the [controller `activate` technique](#style-y080) instead. + + ```javascript + /* avoid */ + angular + .module('app') + .controller('Avengers', Avengers); + + function Avengers(movieService) { + var vm = this; + // unresolved + vm.movies; + // resolved asynchronously + movieService.getMovies().then(function(response) { + vm.movies = response.movies; + }); + } + ``` + + ```javascript + /* better */ + + // route-config.js + angular + .module('app') + .config(config); + + function config($routeProvider) { + $routeProvider + .when('/avengers', { + templateUrl: 'avengers.html', + controller: 'Avengers', + controllerAs: 'vm', + resolve: { + moviesPrepService: function(movieService) { + return movieService.getMovies(); + } + } + }); + } + + // avengers.js + angular + .module('app') + .controller('Avengers', Avengers); + + Avengers.$inject = ['moviesPrepService']; + function Avengers(moviesPrepService) { + var vm = this; + vm.movies = moviesPrepService.movies; + } + ``` + + Note: The example below shows the route resolve points to a named function, which is easier to debug and easier to handle dependency injection. + + ```javascript + /* even better */ + + // route-config.js + angular + .module('app') + .config(config); + + function config($routeProvider) { + $routeProvider + .when('/avengers', { + templateUrl: 'avengers.html', + controller: 'Avengers', + controllerAs: 'vm', + resolve: { + moviesPrepService: moviesPrepService + } + }); + } + + function moviePrepService(movieService) { + return movieService.getMovies(); + } + + // avengers.js + angular + .module('app') + .controller('Avengers', Avengers); + + Avengers.$inject = ['moviesPrepService']; + function Avengers(moviesPrepService) { + var vm = this; + vm.movies = moviesPrepService.movies; + } + ``` + Note: The code example's dependency on `movieService` is not minification safe on its own. For details on how to make this code minification safe, see the sections on [dependency injection](#manual-annotating-for-dependency-injection) and on [minification and annotation](#minification-and-annotation). + +**[Volver arriba](#table-of-contents)** + +## Manual Annotating for Dependency Injection + +### UnSafe from Minification +###### [Style [Y090](#style-y090)] + + - Avoid using the shortcut syntax of declaring dependencies without using a minification-safe approach. + + *¿Por qué?*: The parameters to the component (e.g. controller, factory, etc) will be converted to mangled variables. For example, `common` and `dataservice` may become `a` or `b` and not be found by AngularJS. + + ```javascript + /* avoid - not minification-safe*/ + angular + .module('app') + .controller('Dashboard', Dashboard); + + function Dashboard(common, dataservice) { + } + ``` + + This code may produce mangled variables when minified and thus cause runtime errors. + + ```javascript + /* avoid - not minification-safe*/ + angular.module('app').controller('Dashboard', d);function d(a, b) { } + ``` + +### Manually Identify Dependencies +###### [Style [Y091](#style-y091)] + + - Use `$inject` to manually identify your dependencies for AngularJS components. + + *¿Por qué?*: This technique mirrors the technique used by [`ng-annotate`](https://github.com/olov/ng-annotate), which I recommend for automating the creation of minification safe dependencies. If `ng-annotate` detects injection has already been made, it will not duplicate it. + + *¿Por qué?*: This safeguards your dependencies from being vulnerable to minification issues when parameters may be mangled. For example, `common` and `dataservice` may become `a` or `b` and not be found by AngularJS. + + *¿Por qué?*: Avoid creating in-line dependencies as long lists can be difficult to read in the array. Also it can be confusing that the array is a series of strings while the last item is the component's function. + + ```javascript + /* avoid */ + angular + .module('app') + .controller('Dashboard', + ['$location', '$routeParams', 'common', 'dataservice', + function Dashboard($location, $routeParams, common, dataservice) {} + ]); + ``` + + ```javascript + /* avoid */ + angular + .module('app') + .controller('Dashboard', + ['$location', '$routeParams', 'common', 'dataservice', Dashboard]); + + function Dashboard($location, $routeParams, common, dataservice) { + } + ``` + + ```javascript + /* recommended */ + angular + .module('app') + .controller('Dashboard', Dashboard); + + Dashboard.$inject = ['$location', '$routeParams', 'common', 'dataservice']; + + function Dashboard($location, $routeParams, common, dataservice) { + } + ``` + + Note: When your function is below a return statement the $inject may be unreachable (this may happen in a directive). You can solve this by either moving the $inject above the return statement or by using the alternate array injection syntax. + + Note: [`ng-annotate 0.10.0`](https://github.com/olov/ng-annotate) introduced a feature where it moves the `$inject` to where it is reachable. + + ```javascript + // inside a directive definition + function outer() { + return { + controller: DashboardPanel, + }; + + DashboardPanel.$inject = ['logger']; // Unreachable + function DashboardPanel(logger) { + } + } + ``` + + ```javascript + // inside a directive definition + function outer() { + DashboardPanel.$inject = ['logger']; // reachable + return { + controller: DashboardPanel, + }; + + function DashboardPanel(logger) { + } + } + ``` + +### Manually Identify Route Resolver Dependencies +###### [Style [Y092](#style-y092)] + + - Use $inject to manually identify your route resolver dependencies for AngularJS components. + + *¿Por qué?*: This technique breaks out the anonymous function for the route resolver, making it easier to read. + + *¿Por qué?*: An `$inject` statement can easily precede the resolver to handle making any dependencies minification safe. + + ```javascript + /* recommended */ + function config($routeProvider) { + $routeProvider + .when('/avengers', { + templateUrl: 'avengers.html', + controller: 'Avengers', + controllerAs: 'vm', + resolve: { + moviesPrepService: moviePrepService + } + }); + } + + moviePrepService.$inject = ['movieService']; + function moviePrepService(movieService) { + return movieService.getMovies(); + } + ``` + +**[Volver arriba](#table-of-contents)** + +## Minification and Annotation + +### ng-annotate +###### [Style [Y100](#style-y100)] + + - Use [ng-annotate](//github.com/olov/ng-annotate) for [Gulp](http://gulpjs.com) or [Grunt](http://gruntjs.com) and comment functions that need automated dependency injection using `/** @ngInject */` + + *¿Por qué?*: This safeguards your code from any dependencies that may not be using minification-safe practices. + + *¿Por qué?*: [`ng-min`](https://github.com/btford/ngmin) is deprecated + + >I prefer Gulp as I feel it is easier to write, to read, and to debug. + + The following code is not using minification safe dependencies. + + ```javascript + angular + .module('app') + .controller('Avengers', Avengers); + + /* @ngInject */ + function Avengers(storageService, avengerService) { + var vm = this; + vm.heroSearch = ''; + vm.storeHero = storeHero; + + function storeHero() { + var hero = avengerService.find(vm.heroSearch); + storageService.save(hero.name, hero); + } + } + ``` + + When the above code is run through ng-annotate it will produce the following output with the `$inject` annotation and become minification-safe. + + ```javascript + angular + .module('app') + .controller('Avengers', Avengers); + + /* @ngInject */ + function Avengers(storageService, avengerService) { + var vm = this; + vm.heroSearch = ''; + vm.storeHero = storeHero; + + function storeHero() { + var hero = avengerService.find(vm.heroSearch); + storageService.save(hero.name, hero); + } + } + + Avengers.$inject = ['storageService', 'avengerService']; + ``` + + Note: If `ng-annotate` detects injection has already been made (e.g. `@ngInject` was detected), it will not duplicate the `$inject` code. + + Note: When using a route resolver you can prefix the resolver's function with `/* @ngInject */` and it will produce properly annotated code, keeping any injected dependencies minification safe. + + ```javascript + // Using @ngInject annotations + function config($routeProvider) { + $routeProvider + .when('/avengers', { + templateUrl: 'avengers.html', + controller: 'Avengers', + controllerAs: 'vm', + resolve: { /* @ngInject */ + moviesPrepService: function(movieService) { + return movieService.getMovies(); + } + } + }); + } + ``` + + > Note: Starting from AngularJS 1.3 use the [`ngApp`](https://docs.angularjs.org/api/ng/directive/ngApp) directive's `ngStrictDi` parameter. When present the injector will be created in "strict-di" mode causing the application to fail to invoke functions which do not use explicit function annotation (these may not be minification safe). Debugging info will be logged to the console to help track down the offending code. + `` + +### Use Gulp or Grunt for ng-annotate +###### [Style [Y101](#style-y101)] + + - Use [gulp-ng-annotate](https://www.npmjs.org/package/gulp-ng-annotate) or [grunt-ng-annotate](https://www.npmjs.org/package/grunt-ng-annotate) in an automated build task. Inject `/* @ngInject */` prior to any function that has dependencies. + + *¿Por qué?*: ng-annotate will catch most dependencies, but it sometimes requires hints using the `/* @ngInject */` syntax. + + The following code is an example of a gulp task using ngAnnotate + + ```javascript + gulp.task('js', ['jshint'], function() { + var source = pkg.paths.js; + return gulp.src(source) + .pipe(sourcemaps.init()) + .pipe(concat('all.min.js', {newLine: ';'})) + // Annotate before uglify so the code get's min'd properly. + .pipe(ngAnnotate({ + // true helps add where @ngInject is not used. It infers. + // Doesn't work with resolve, so we must be explicit there + add: true + })) + .pipe(bytediff.start()) + .pipe(uglify({mangle: true})) + .pipe(bytediff.stop()) + .pipe(sourcemaps.write('./')) + .pipe(gulp.dest(pkg.paths.dev)); + }); + + ``` + +**[Volver arriba](#table-of-contents)** + +## Exception Handling + +### decorators +###### [Style [Y110](#style-y110)] + + - Use a [decorator](https://docs.angularjs.org/api/auto/service/$provide#decorator), at config time using the [`$provide`](https://docs.angularjs.org/api/auto/service/$provide) service, on the [`$exceptionHandler`](https://docs.angularjs.org/api/ng/service/$exceptionHandler) service to perform custom actions when exceptions occur. + + *¿Por qué?*: Provides a consistent way to handle uncaught AngularJS exceptions for development-time or run-time. + + Note: Another option is to override the service instead of using a decorator. This is a fine option, but if you want to keep the default behavior and extend it a decorator is recommended. + + ```javascript + /* recommended */ + angular + .module('blocks.exception') + .config(exceptionConfig); + + exceptionConfig.$inject = ['$provide']; + + function exceptionConfig($provide) { + $provide.decorator('$exceptionHandler', extendExceptionHandler); + } + + extendExceptionHandler.$inject = ['$delegate', 'toastr']; + + function extendExceptionHandler($delegate, toastr) { + return function(exception, cause) { + $delegate(exception, cause); + var errorData = { + exception: exception, + cause: cause + }; + /** + * Could add the error to a service's collection, + * add errors to $rootScope, log errors to remote web server, + * or log locally. Or throw hard. It is entirely up to you. + * throw exception; + */ + toastr.error(exception.msg, errorData); + }; + } + ``` + +### Exception Catchers +###### [Style [Y111](#style-y111)] + + - Create a factory that exposes an interface to catch and gracefully handle exceptions. + + *¿Por qué?*: Provides a consistent way to catch exceptions that may be thrown in your code (e.g. during XHR calls or promise failures). + + Note: The exception catcher is good for catching and reacting to specific exceptions from calls that you know may throw one. For example, when making an XHR call to retrieve data from a remote web service and you want to catch any exceptions from that service and react uniquely. + + ```javascript + /* recommended */ + angular + .module('blocks.exception') + .factory('exception', exception); + + exception.$inject = ['logger']; + + function exception(logger) { + var service = { + catcher: catcher + }; + return service; + + function catcher(message) { + return function(reason) { + logger.error(message, reason); + }; + } + } + ``` + +### Route Errors +###### [Style [Y112](#style-y112)] + + - Handle and log all routing errors using [`$routeChangeError`](https://docs.angularjs.org/api/ngRoute/service/$route#$routeChangeError). + + *¿Por qué?*: Provides a consistent way handle all routing errors. + + *¿Por qué?*: Potentially provides a better user experience if a routing error occurs and you route them to a friendly screen with more details or recovery options. + + ```javascript + /* recommended */ + function handleRoutingErrors() { + /** + * Route cancellation: + * On routing error, go to the dashboard. + * Provide an exit clause if it tries to do it twice. + */ + $rootScope.$on('$routeChangeError', + function(event, current, previous, rejection) { + var destination = (current && (current.title || current.name || current.loadedTemplateUrl)) || + 'unknown target'; + var msg = 'Error routing to ' + destination + '. ' + (rejection.msg || ''); + /** + * Optionally log using a custom service or $log. + * (Don't forget to inject custom service) + */ + logger.warning(msg, [current]); + } + ); + } + ``` + +**[Volver arriba](#table-of-contents)** + +## Naming + +### Naming Guidelines +###### [Style [Y120](#style-y120)] + + - Use consistent names for all components following a pattern that describes the component's feature then (optionally) its type. My recommended pattern is `feature.type.js`. There are 2 names for most assets: + * the file name (`avengers.controller.js`) + * the registered component name with Angular (`AvengersController`) + + *¿Por qué?*: Naming conventions help provide a consistent way to find content at a glance. Consistency within the project is vital. Consistency with a team is important. Consistency across a company provides tremendous efficiency. + + *¿Por qué?*: The naming conventions should simply help you find your code faster and make it easier to understand. + +### Feature File Names +###### [Style [Y121](#style-y121)] + + - Use consistent names for all components following a pattern that describes the component's feature then (optionally) its type. My recommended pattern is `feature.type.js`. + + *¿Por qué?*: Provides a consistent way to quickly identify components. + + *¿Por qué?*: Provides pattern matching for any automated tasks. + + ```javascript + /** + * common options + */ + + // Controllers + avengers.js + avengers.controller.js + avengersController.js + + // Services/Factories + logger.js + logger.service.js + loggerService.js + ``` + + ```javascript + /** + * recommended + */ + + // controllers + avengers.controller.js + avengers.controller.spec.js + + // services/factories + logger.service.js + logger.service.spec.js + + // constants + constants.js + + // module definition + avengers.module.js + + // routes + avengers.routes.js + avengers.routes.spec.js + + // configuration + avengers.config.js + + // directives + avenger-profile.directive.js + avenger-profile.directive.spec.js + ``` + + Note: Another common convention is naming controller files without the word `controller` in the file name such as `avengers.js` instead of `avengers.controller.js`. All other conventions still hold using a suffix of the type. Controllers are the most common type of component so this just saves typing and is still easily identifiable. I recommend you choose 1 convention and be consistent for your team. + + ```javascript + /** + * recommended + */ + // Controllers + avengers.js + avengers.spec.js + ``` + +### Test File Names +###### [Style [Y122](#style-y122)] + + - Name test specifications similar to the component they test with a suffix of `spec`. + + *¿Por qué?*: Provides a consistent way to quickly identify components. + + *¿Por qué?*: Provides pattern matching for [karma](http://karma-runner.github.io/) or other test runners. + + ```javascript + /** + * recommended + */ + avengers.controller.spec.js + logger.service.spec.js + avengers.routes.spec.js + avenger-profile.directive.spec.js + ``` + +### Controller Names +###### [Style [Y123](#style-y123)] + + - Use consistent names for all controllers named after their feature. Use UpperCamelCase for controllers, as they are constructors. + + *¿Por qué?*: Provides a consistent way to quickly identify and reference controllers. + + *¿Por qué?*: UpperCamelCase is conventional for identifying object that can be instantiated using a constructor. + + ```javascript + /** + * recommended + */ + + // avengers.controller.js + angular + .module + .controller('HeroAvengers', HeroAvengers); + + function HeroAvengers() { } + ``` + +### Controller Name Suffix +###### [Style [Y124](#style-y124)] + + - Append the controller name with the suffix `Controller` or with no suffix. Choose 1, not both. + + *¿Por qué?*: The `Controller` suffix is more commonly used and is more explicitly descriptive. + + *¿Por qué?*: Omitting the suffix is more succinct and the controller is often easily identifiable even without the suffix. + + ```javascript + /** + * recommended: Option 1 + */ + + // avengers.controller.js + angular + .module + .controller('Avengers', Avengers); + + function Avengers() { } + ``` + + ```javascript + /** + * recommended: Option 2 + */ + + // avengers.controller.js + angular + .module + .controller('AvengersController', AvengersController); + + function AvengersController() { } + ``` + +### Factory Names +###### [Style [Y125](#style-y125)] + + - Use consistent names for all factories named after their feature. Use camel-casing for services and factories. + + *¿Por qué?*: Provides a consistent way to quickly identify and reference factories. + + ```javascript + /** + * recommended + */ + + // logger.service.js + angular + .module + .factory('logger', logger); + + function logger() { } + ``` + +### Directive Component Names +###### [Style [Y126](#style-y126)] + + - Use consistent names for all directives using camel-case. Use a short prefix to describe the area that the directives belong (some example are company prefix or project prefix). + + *¿Por qué?*: Provides a consistent way to quickly identify and reference components. + + ```javascript + /** + * recommended + */ + + // avenger-profile.directive.js + angular + .module + .directive('xxAvengerProfile', xxAvengerProfile); + + // usage is + + function xxAvengerProfile() { } + ``` + +### Modules +###### [Style [Y127](#style-y127)] + + - When there are multiple modules, the main module file is named `app.module.js` while other dependent modules are named after what they represent. For example, an admin module is named `admin.module.js`. The respective registered module names would be `app` and `admin`. + + *¿Por qué?*: Provides consistency for multiple module apps, and for expanding to large applications. + + *¿Por qué?*: Provides easy way to use task automation to load all module definitions first, then all other angular files (for bundling). + +### Configuration +###### [Style [Y128](#style-y128)] + + - Separate configuration for a module into its own file named after the module. A configuration file for the main `app` module is named `app.config.js` (or simply `config.js`). A configuration for a module named `admin.module.js` is named `admin.config.js`. + + *¿Por qué?*: Separates configuration from module definition, components, and active code. + + *¿Por qué?*: Provides a identifiable place to set configuration for a module. + +### Routes +###### [Style [Y129](#style-y129)] + + - Separate route configuration into its own file. Examples might be `app.route.js` for the main module and `admin.route.js` for the `admin` module. Even in smaller apps I prefer this separation from the rest of the configuration. + +**[Volver arriba](#table-of-contents)** + +## Application Structure LIFT Principle +### LIFT +###### [Style [Y140](#style-y140)] + + - Structure your app such that you can `L`ocate your code quickly, `I`dentify the code at a glance, keep the `F`lattest structure you can, and `T`ry to stay DRY. The structure should follow these 4 basic guidelines. + + *Why LIFT?*: Provides a consistent structure that scales well, is modular, and makes it easier to increase developer efficiency by finding code quickly. Another way to check your app structure is to ask yourself: How quickly can you open and work in all of the related files for a feature? + + When I find my structure is not feeling comfortable, I go back and revisit these LIFT guidelines + + 1. `L`ocating our code is easy + 2. `I`dentify code at a glance + 3. `F`lat structure as long as we can + 4. `T`ry to stay DRY (Don’t Repeat Yourself) or T-DRY + +### Locate +###### [Style [Y141](#style-y141)] + + - Make locating your code intuitive, simple and fast. + + *¿Por qué?*: I find this to be super important for a project. If the team cannot find the files they need to work on quickly, they will not be able to work as efficiently as possible, and the structure needs to change. You may not know the file name or where its related files are, so putting them in the most intuitive locations and near each other saves a ton of time. A descriptive folder structure can help with this. + + ``` + /bower_components + /client + /app + /avengers + /blocks + /exception + /logger + /core + /dashboard + /data + /layout + /widgets + /content + index.html + .bower.json + ``` + +### Identify +###### [Style [Y142](#style-y142)] + + - When you look at a file you should instantly know what it contains and represents. + + *¿Por qué?*: You spend less time hunting and pecking for code, and become more efficient. If this means you want longer file names, then so be it. Be descriptive with file names and keeping the contents of the file to exactly 1 component. Avoid files with multiple controllers, multiple services, or a mixture. There are deviations of the 1 per file rule when I have a set of very small features that are all related to each other, they are still easily identifiable. + +### Flat +###### [Style [Y143](#style-y143)] + + - Keep a flat folder structure as long as possible. When you get to 7+ files, begin considering separation. + + *¿Por qué?*: Nobody wants to search 7 levels of folders to find a file. Think about menus on web sites … anything deeper than 2 should take serious consideration. In a folder structure there is no hard and fast number rule, but when a folder has 7-10 files, that may be time to create subfolders. Base it on your comfort level. Use a flatter structure until there is an obvious value (to help the rest of LIFT) in creating a new folder. + +### T-DRY (Try to Stick to DRY) +###### [Style [Y144](#style-y144)] + + - Be DRY, but don't go nuts and sacrifice readability. + + *¿Por qué?*: Being DRY is important, but not crucial if it sacrifices the others in LIFT, which is why I call it T-DRY. I don’t want to type session-view.html for a view because, well, it’s obviously a view. If it is not obvious or by convention, then I name it. + +**[Volver arriba](#table-of-contents)** + +## Application Structure + +### Overall Guidelines +###### [Style [Y150](#style-y150)] + + - Have a near term view of implementation and a long term vision. In other words, start small and but keep in mind on where the app is heading down the road. All of the app's code goes in a root folder named `app`. All content is 1 feature per file. Each controller, service, module, view is in its own file. All 3rd party vendor scripts are stored in another root folder and not in the `app` folder. I didn't write them and I don't want them cluttering my app (`bower_components`, `scripts`, `lib`). + + Note: Find more details and reasoning behind the structure at [this original post on application structure](http://www.johnpapa.net/angular-app-structuring-guidelines/). + +### Layout +###### [Style [Y151](#style-y151)] + + - Place components that define the overall layout of the application in a folder named `layout`. These may include a shell view and controller may act as the container for the app, navigation, menus, content areas, and other regions. + + *¿Por qué?*: Organizes all layout in a single place re-used throughout the application. + +### Folders-by-Feature Structure +###### [Style [Y152](#style-y152)] + + - Create folders named for the feature they represent. When a folder grows to contain more than 7 files, start to consider creating a folder for them. Your threshold may be different, so adjust as needed. + + *¿Por qué?*: A developer can locate the code, identify what each file represents at a glance, the structure is flat as can be, and there is no repetitive nor redundant names. + + *¿Por qué?*: The LIFT guidelines are all covered. + + *¿Por qué?*: Helps reduce the app from becoming cluttered through organizing the content and keeping them aligned with the LIFT guidelines. + + *¿Por qué?*: When there are a lot of files (10+) locating them is easier with a consistent folder structures and more difficult in flat structures. + + ```javascript + /** + * recommended + */ + + app/ + app.module.js + app.config.js + app.routes.js + components/ + calendar.directive.js + calendar.directive.html + user-profile.directive.js + user-profile.directive.html + layout/ + shell.html + shell.controller.js + topnav.html + topnav.controller.js + people/ + attendees.html + attendees.controller.js + speakers.html + speakers.controller.js + speaker-detail.html + speaker-detail.controller.js + services/ + data.service.js + localstorage.service.js + logger.service.js + spinner.service.js + sessions/ + sessions.html + sessions.controller.js + session-detail.html + session-detail.controller.js + ``` + + ![Sample App Structure](https://raw.githubusercontent.com/johnpapa/angularjs-styleguide/master/assets/modularity-2.png) + + Note: Do not use structuring using folders-by-type. This requires moving to multiple folders when working on a feature and gets unwieldy quickly as the app grows to 5, 10 or 25+ views and controllers (and other features), which makes it more difficult than folder-by-feature to locate files. + + ```javascript + /* + * avoid + * Alternative folders-by-type. + * I recommend "folders-by-feature", instead. + */ + + app/ + app.module.js + app.config.js + app.routes.js + controllers/ + attendees.js + session-detail.js + sessions.js + shell.js + speakers.js + speaker-detail.js + topnav.js + directives/ + calendar.directive.js + calendar.directive.html + user-profile.directive.js + user-profile.directive.html + services/ + dataservice.j + localstorage.js + logger.js + spinner.js + views/ + attendees.html + session-detail.html + sessions.html + shell.html + speakers.html + speaker-detail.html + topnav.html + ``` + +**[Volver arriba](#table-of-contents)** + +## Modularity + +### Many Small, Self Contained Modules +###### [Style [Y160](#style-y160)] + + - Create small modules that encapsulate one responsibility. + + *¿Por qué?*: Modular applications make it easy to plug and go as they allow the development teams to build vertical slices of the applications and roll out incrementally. This means we can plug in new features as we develop them. + +### Create an App Module +###### [Style [Y161](#style-y161)] + + - Create an application root module whose role is pull together all of the modules and features of your application. Name this for your application. + + *¿Por qué?*: AngularJS encourages modularity and separation patterns. Creating an application root module whose role is to tie your other modules together provides a very straightforward way to add or remove modules from your application. + +### Keep the App Module Thin +###### [Style [Y162](#style-y162)] + + - Only put logic for pulling together the app in the application module. Leave features in their own modules. + + *¿Por qué?*: Adding additional roles to the application root to get remote data, display views, or other logic not related to pulling the app together muddies the app module and make both sets of features harder to reuse or turn off. + + *¿Por qué?*: The app module becomes a manifest that describes which modules help define the application. + +### Feature Areas are Modules +###### [Style [Y163](#style-y163)] + + - Create modules that represent feature areas, such as layout, reusable and shared services, dashboards, and app specific features (e.g. customers, admin, sales). + + *¿Por qué?*: Self contained modules can be added to the application with little or no friction. + + *¿Por qué?*: Sprints or iterations can focus on feature areas and turn them on at the end of the sprint or iteration. + + *¿Por qué?*: Separating feature areas into modules makes it easier to test the modules in isolation and reuse code. + +### Reusable Blocks are Modules +###### [Style [Y164](#style-y164)] + + - Create modules that represent reusable application blocks for common services such as exception handling, logging, diagnostics, security, and local data stashing. + + *¿Por qué?*: These types of features are needed in many applications, so by keeping them separated in their own modules they can be application generic and be reused across applications. + +### Module Dependencies +###### [Style [Y165](#style-y165)] + + - The application root module depends on the app specific feature modules and any shared or reusable modules. + + ![Modularity and Dependencies](https://raw.githubusercontent.com/johnpapa/angularjs-styleguide/master/assets/modularity-1.png) + + *¿Por qué?*: The main app module contains a quickly identifiable manifest of the application's features. + + *¿Por qué?*: Each feature area contains a manifest of what it depends on, so it can be pulled in as a dependency in other applications and still work. + + *¿Por qué?*: Intra-App features such as shared data services become easy to locate and share from within `app.core` (choose your favorite name for this module). + + Note: This is a strategy for consistency. There are many good options here. Choose one that is consistent, follows AngularJS's dependency rules, and is easy to maintain and scale. + + > My structures vary slightly between projects but they all follow these guidelines for structure and modularity. The implementation may vary depending on the features and the team. In other words, don't get hung up on an exact like-for-like structure but do justify your structure using consistency, maintainability, and efficiency in mind. + + > In a small app, you can also consider putting all the shared dependencies in the app module where the feature modules have no direct dependencies. This makes it easier to maintain the smaller application, but makes it harder to reuse modules outside of this application. + +**[Volver arriba](#table-of-contents)** + +## Startup Logic + +### Configuration +###### [Style [Y170](#style-y170)] + + - Inject code into [module configuration](https://docs.angularjs.org/guide/module#module-loading-dependencies) that must be configured before running the angular app. Ideal candidates include providers and constants. + + *¿Por qué?*: This makes it easier to have a less places for configuration. + + ```javascript + angular + .module('app') + .config(configure); + + configure.$inject = + ['routerHelperProvider', 'exceptionHandlerProvider', 'toastr']; + + function configure (routerHelperProvider, exceptionHandlerProvider, toastr) { + exceptionHandlerProvider.configure(config.appErrorPrefix); + configureStateHelper(); + + toastr.options.timeOut = 4000; + toastr.options.positionClass = 'toast-bottom-right'; + + //////////////// + + function configureStateHelper() { + routerHelperProvider.configure({ + docTitle: 'NG-Modular: ' + }); + } + } + ``` + +### Run Blocks +###### [Style [Y171](#style-y171)] + + - Any code that needs to run when an application starts should be declared in a factory, exposed via a function, and injected into the [run block](https://docs.angularjs.org/guide/module#module-loading-dependencies). + + *¿Por qué?*: Code directly in a run block can be difficult to test. Placing in a factory makes it easier to abstract and mock. + + ```javascript + angular + .module('app') + .run(runBlock); + + runBlock.$inject = ['authenticator', 'translator']; + + function runBlock(authenticator, translator) { + authenticator.initialize(); + translator.initialize(); + } + ``` + +**[Volver arriba](#table-of-contents)** + +## Angular $ Wrapper Services + +### $document and $window +###### [Style [Y180](#style-y180)] + + - Use [`$document`](https://docs.angularjs.org/api/ng/service/$document) and [`$window`](https://docs.angularjs.org/api/ng/service/$window) instead of `document` and `window`. + + *¿Por qué?*: These services are wrapped by Angular and more easily testable than using document and window in tests. This helps you avoid having to mock document and window yourself. + +### $timeout and $interval +###### [Style [Y181](#style-y181)] + + - Use [`$timeout`](https://docs.angularjs.org/api/ng/service/$timeout) and [`$interval`](https://docs.angularjs.org/api/ng/service/$interval) instead of `setTimeout` and `setInterval` . + + *¿Por qué?*: These services are wrapped by Angular and more easily testable and handle AngularJS's digest cycle thus keeping data binding in sync. + +**[Volver arriba](#table-of-contents)** + +## Testing +Unit testing helps maintain clean code, as such I included some of my recommendations for unit testing foundations with links for more information. + +### Write Tests with Stories +###### [Style [Y190](#style-y190)] + + - Write a set of tests for every story. Start with an empty test and fill them in as you write the code for the story. + + *¿Por qué?*: Writing the test descriptions helps clearly define what your story will do, will not do, and how you can measure success. + + ```javascript + it('should have Avengers controller', function() { + // TODO + }); + + it('should find 1 Avenger when filtered by name', function() { + // TODO + }); + + it('should have 10 Avengers', function() { + // TODO (mock data?) + }); + + it('should return Avengers via XHR', function() { + // TODO ($httpBackend?) + }); + + // and so on + ``` + +### Testing Library +###### [Style [Y191](#style-y191)] + + - Use [Jasmine](http://jasmine.github.io/) or [Mocha](http://mochajs.org) for unit testing. + + *¿Por qué?*: Both Jasmine and Mocha are widely used in the AngularJS community. Both are stable, well maintained, and provide robust testing features. + + Note: When using Mocha, also consider choosing an assert library such as [Chai](http://chaijs.com). + +### Test Runner +###### [Style [Y192](#style-y192)] + + - Use [Karma](http://karma-runner.github.io) as a test runner. + + *¿Por qué?*: Karma is easy to configure to run once or automatically when you change your code. + + *¿Por qué?*: Karma hooks into your Continuous Integration process easily on its own or through Grunt or Gulp. + + *¿Por qué?*: Some IDE's are beginning to integrate with Karma, such as [WebStorm](http://www.jetbrains.com/webstorm/) and [Visual Studio](http://visualstudiogallery.msdn.microsoft.com/02f47876-0e7a-4f6c-93f8-1af5d5189225). + + *¿Por qué?*: Karma works well with task automation leaders such as [Grunt](http://www.gruntjs.com) (with [grunt-karma](https://github.com/karma-runner/grunt-karma)) and [Gulp](http://www.gulpjs.com) (with [gulp-karma](https://github.com/lazd/gulp-karma)). + +### Stubbing and Spying +###### [Style [Y193](#style-y193)] + + - Use [Sinon](http://sinonjs.org/) for stubbing and spying. + + *¿Por qué?*: Sinon works well with both Jasmine and Mocha and extends the stubbing and spying features they offer. + + *¿Por qué?*: Sinon makes it easier to toggle between Jasmine and Mocha, if you want to try both. + +### Headless Browser +###### [Style [Y194](#style-y194)] + + - Use [PhantomJS](http://phantomjs.org/) to run your tests on a server. + + *¿Por qué?*: PhantomJS is a headless browser that helps run your tests without needing a "visual" browser. So you do not have to install Chrome, Safari, IE, or other browsers on your server. + + Note: You should still test on all browsers in your environment, as appropriate for your target audience. + +### Code Analysis +###### [Style [Y195](#style-y195)] + + - Run JSHint on your tests. + + *¿Por qué?*: Tests are code. JSHint can help identify code quality issues that may cause the test to work improperly. + +### Alleviate Globals for JSHint Rules on Tests +###### [Style [Y196](#style-y196)] + + - Relax the rules on your test code to allow for common globals such as `describe` and `expect`. + + *¿Por qué?*: Your tests are code and require the same attention and code quality rules as all of your production code. However, global variables used by the testing framework, for example, can be relaxed by including this in your test specs. + + ```javascript + /* global sinon, describe, it, afterEach, beforeEach, expect, inject */ + ``` + + ![Testing Tools](https://raw.githubusercontent.com/johnpapa/angularjs-styleguide/master/assets/testing-tools.png) + +### Organizing Tests +###### [Style [Y197](#style-y197)] + + - Place unit test files (specs) side-by-side with your client code. Place specs that cover server integration or test multiple components in a separate `tests` folder. + + *¿Por qué?*: Unit tests have a direct correlation to a specific component and file in source code. + + *¿Por qué?*: It is easier to keep them up to date since they are always in sight. When coding whether you do TDD or test during development or test after development, the specs are side-by-side and never out of sight nor mind, and thus more likely to be maintained which also helps maintain code coverage. + + *¿Por qué?*: When you update source code it is easier to go update the tests at the same time. + + *¿Por qué?*: Placing them side-by-side makes it easy to find them and easy to move them with the source code if you move the source. + + *¿Por qué?*: Having the spec nearby makes it easier for the source code reader to learn how the component is supposed to be used and to discover its known limitations. + + *¿Por qué?*: Separating specs so they are not in a distributed build is easy with grunt or gulp. + + ``` + /src/client/app/customers/customer-detail.controller.js + /customer-detail.controller.spec.js + /customers.controller.spec.js + /customers.controller-detail.spec.js + /customers.module.js + /customers.route.js + /customers.route.spec.js + ``` + +**[Volver arriba](#table-of-contents)** + +## Animations + +### Usage +###### [Style [Y210](#style-y210)] + + - Use subtle [animations with AngularJS](https://docs.angularjs.org/guide/animations) to transition between states for views and primary visual elements. Include the [ngAnimate module](https://docs.angularjs.org/api/ngAnimate). The 3 keys are subtle, smooth, seamless. + + *¿Por qué?*: Subtle animations can improve User Experience when used appropriately. + + *¿Por qué?*: Subtle animations can improve perceived performance as views transition. + +### Sub Second +###### [Style [Y211](#style-y211)] + + - Use short durations for animations. I generally start with 300ms and adjust until appropriate. + + *¿Por qué?*: Long animations can have the reverse affect on User Experience and perceived performance by giving the appearance of a slow application. + +### animate.css +###### [Style [Y212](#style-y212)] + + - Use [animate.css](http://daneden.github.io/animate.css/) for conventional animations. + + *¿Por qué?*: The animations that animate.css provides are fast, smooth, and easy to add to your application. + + *¿Por qué?*: Provides consistency in your animations. + + *¿Por qué?*: animate.css is widely used and tested. + + Note: See this [great post by Matias Niemelä on AngularJS animations](http://www.yearofmoo.com/2013/08/remastered-animation-in-angularjs-1-2.html) + +**[Volver arriba](#table-of-contents)** + +## Comments + +### jsDoc +###### [Style [Y220](#style-y220)] + + - If planning to produce documentation, use [`jsDoc`](http://usejsdoc.org/) syntax to document function names, description, params and returns. Use `@namespace` and `@memberOf` to match your app structure. + + *¿Por qué?*: You can generate (and regenerate) documentation from your code, instead of writing it from scratch. + + *¿Por qué?*: Provides consistency using a common industry tool. + + ```javascript + /** + * Logger Factory + * @namespace Factories + */ + (function() { + angular + .module('app') + .factory('logger', logger); + + /** + * @namespace Logger + * @desc Application wide logger + * @memberOf Factories + */ + function logger($log) { + var service = { + logError: logError + }; + return service; + + //////////// + + /** + * @name logError + * @desc Logs errors + * @param {String} msg Message to log + * @returns {String} + * @memberOf Factories.Logger + */ + function logError(msg) { + var loggedMsg = 'Error: ' + msg; + $log.error(loggedMsg); + return loggedMsg; + }; + } + })(); + ``` + +**[Volver arriba](#table-of-contents)** + +## JS Hint + +### Use an Options File +###### [Style [Y230](#style-y230)] + + - Use JS Hint for linting your JavaScript and be sure to customize the JS Hint options file and include in source control. See the [JS Hint docs](http://www.jshint.com/docs/) for details on the options. + + *¿Por qué?*: Provides a first alert prior to committing any code to source control. + + *¿Por qué?*: Provides consistency across your team. + + ```javascript + { + "bitwise": true, + "camelcase": true, + "curly": true, + "eqeqeq": true, + "es3": false, + "forin": true, + "freeze": true, + "immed": true, + "indent": 4, + "latedef": "nofunc", + "newcap": true, + "noarg": true, + "noempty": true, + "nonbsp": true, + "nonew": true, + "plusplus": false, + "quotmark": "single", + "undef": true, + "unused": false, + "strict": false, + "maxparams": 10, + "maxdepth": 5, + "maxstatements": 40, + "maxcomplexity": 8, + "maxlen": 120, + + "asi": false, + "boss": false, + "debug": false, + "eqnull": true, + "esnext": false, + "evil": false, + "expr": false, + "funcscope": false, + "globalstrict": false, + "iterator": false, + "lastsemic": false, + "laxbreak": false, + "laxcomma": false, + "loopfunc": true, + "maxerr": false, + "moz": false, + "multistr": false, + "notypeof": false, + "proto": false, + "scripturl": false, + "shadow": false, + "sub": true, + "supernew": false, + "validthis": false, + "noyield": false, + + "browser": true, + "node": true, + + "globals": { + "angular": false, + "$": false + } + } + ``` + +**[Volver arriba](#table-of-contents)** + +## Constants + +### Vendor Globals +###### [Style [Y240](#style-y240)] + + - Create an AngularJS Constant for vendor libraries' global variables. + + *¿Por qué?*: Provides a way to inject vendor libraries that otherwise are globals. This improves code testability by allowing you to more easily know what the dependencies of your components are (avoids leaky abstractions). It also allows you to mock these dependencies, where it makes sense. + + ```javascript + // constants.js + + /* global toastr:false, moment:false */ + (function() { + 'use strict'; + + angular + .module('app.core') + .constant('toastr', toastr) + .constant('moment', moment); + })(); + ``` + +###### [Style [Y241](#style-y241)] + + - Use constants for values that do not change and do not come from another service. When constants are used only for a module that may be reused in multiple applications, place constants in a file per module named after the module. Until this is required, keep constants in the main module in a `constants.js` file. + + *¿Por qué?*: A value that may change, even infrequently, should be retrieved from a service so you do not have to change the source code. For example, a url for a data service could be placed in a constants but a better place would be to load it from a web service. + + *¿Por qué?*: Constants can be injected into any angular component, including providers. + + *¿Por qué?*: When an application is separated into modules that may be reused in other applications, each stand-alone module should be able to operate on its own including any dependent constants. + + ```javascript + // Constants used by the entire app + angular + .module('app.core') + .constant('moment', moment); + + // Constants used only by the sales module + angular + .module('app.sales') + .constant('events', { + ORDER_CREATED: 'event_order_created', + INVENTORY_DEPLETED: 'event_inventory_depleted' + }); + ``` + +**[Volver arriba](#table-of-contents)** + +## File Templates and Snippets +Use file templates or snippets to help follow consistent styles and patterns. Here are templates and/or snippets for some of the web development editors and IDEs. + +### Sublime Text +###### [Style [Y250](#style-y250)] + + - AngularJS snippets that follow these styles and guidelines. + + - Download the [Sublime Angular snippets](assets/sublime-angular-snippets.zip?raw=true) + - Place it in your Packages folder + - Restart Sublime + - In a JavaScript file type these commands followed by a `TAB` + + ```javascript + ngcontroller // creates an Angular controller + ngdirective // creates an Angular directive + ngfactory // creates an Angular factory + ngmodule // creates an Angular module + ``` + +### Visual Studio +###### [Style [Y251](#style-y251)] + + - AngularJS file templates that follow these styles and guidelines can be found at [SideWaffle](http://www.sidewaffle.com) + + - Download the [SideWaffle](http://www.sidewaffle.com) Visual Studio extension (vsix file) + - Run the vsix file + - Restart Visual Studio + +### WebStorm +###### [Style [Y252](#style-y252)] + + - AngularJS snippets and file templates that follow these styles and guidelines. You can import them into your WebStorm settings: + + - Download the [WebStorm AngularJS file templates and snippets](assets/webstorm-angular-file-template.settings.jar?raw=true) + - Open WebStorm and go to the `File` menu + - Choose the `Import Settings` menu option + - Select the file and click `OK` + - In a JavaScript file type these commands followed by a `TAB`: + + ```javascript + ng-c // creates an Angular controller + ng-f // creates an Angular factory + ng-m // creates an Angular module + ``` + +**[Volver arriba](#table-of-contents)** + +## Yeoman Generator +###### [Style [Y260](#style-y260)] + +You can use the [HotTowel yeoman generator](http://jpapa.me/yohottowel) to create an app that serves as a starting point for Angular that follows this style guide. + +1. Install generator-hottowel + + ``` + npm install -g generator-hottowel + ``` + +2. Create a new folder and change directory to it + + ``` + mkdir myapp + cd myapp + ``` + +3. Run the generator + + ``` + yo hottowel helloWorld + ``` + +**[Volver arriba](#table-of-contents)** + +## Routing +Client-side routing is important for creating a navigation flow between views and composing views that are made of many smaller templates and directives. + +###### [Style [Y270](#style-y270)] + + - Use the [AngularUI Router](http://angular-ui.github.io/ui-router/) for client-side routing. + + *¿Por qué?*: UI Router offers all the features of the Angular router plus a few additional ones including nested routes and states. + + *¿Por qué?*: The syntax is quite similar to the Angular router and is easy to migrate to UI Router. + +###### [Style [Y271](#style-y271)] + + - Define routes for views in the module where they exist. Each module should contain the routes for the views in the module. + + *¿Por qué?*: Each module should be able to stand on its own. + + *¿Por qué?*: When removing a module or adding a module, the app will only contain routes that point to existing views. + + *¿Por qué?*: This makes it easy to enable or disable portions of an application without concern over orphaned routes. + +**[Volver arriba](#table-of-contents)** + +## Task Automation +Use [Gulp](http://gulpjs.com) or [Grunt](http://gruntjs.com) for creating automated tasks. Gulp leans to code over configuration while Grunt leans to configuration over code. I personally prefer Gulp as I feel it is easier to read and write, but both are excellent. + +###### [Style [Y400](#style-y400)] + + - Use task automation to list module definition files `*.module.js` before all other application JavaScript files. + + *¿Por qué?*: Angular needs the module definitions to be registered before they are used. + + *¿Por qué?*: Naming modules with a specific pattern such as `*.module.js` makes it easy to grab them with a glob and list them first. + + ```javascript + var clientApp = './src/client/app/'; + + // Always grab module files first + var files = [ + clientApp + '**/*.module.js', + clientApp + '**/*.js' + ]; + ``` + +**[Volver arriba](#table-of-contents)** + +## AngularJS docs +For anything else, API reference, check the [Angular documentation](//docs.angularjs.org/api). + +## Contributing + +Open an issue first to discuss potential changes/additions. If you have questions with the guide, feel free to leave them as issues in the repository. If you find a typo, create a pull request. The idea is to keep the content up to date and use github’s native feature to help tell the story with issues and PR’s, which are all searchable via google. Why? Because odds are if you have a question, someone else does too! You can learn more here at about how to contribute. + +*By contributing to this repository you are agreeing to make your content available subject to the license of this repository.* + +### Process + 1. Discuss the changes in a GitHub issue. + 2. Open a Pull Request against the develop branch, reference the issue, and explain the change and why it adds value. + 3. The Pull Request will be evaluated and either merged or declined. + +## License + +_tldr; Use this guide. Attributions are appreciated._ + +### (The MIT License) + +Copyright (c) 2014 [John Papa](http://johnpapa.net) + +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. + +**[Volver arriba](#table-of-contents)** From 0f5758760fb79bb99cda9cc0c36296990c821c2b Mon Sep 17 00:00:00 2001 From: Mike Luby Date: Fri, 6 Feb 2015 23:21:42 -0800 Subject: [PATCH 140/567] typofix --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index e2f75d48..dc406ba9 100644 --- a/README.md +++ b/README.md @@ -729,7 +729,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see ### Accessible Members Up Top ###### [Style [Y052](#style-y052)] - - Expose the callable members of the service (it's interface) at the top, using a technique derived from the [Revealing Module Pattern](http://addyosmani.com/resources/essentialjsdesignpatterns/book/#revealingmodulepatternjavascript). + - Expose the callable members of the service (its interface) at the top, using a technique derived from the [Revealing Module Pattern](http://addyosmani.com/resources/essentialjsdesignpatterns/book/#revealingmodulepatternjavascript). *Why?*: Placing the callable members at the top makes it easy to read and helps you instantly identify which members of the service can be called and must be unit tested (and/or mocked). @@ -1119,7 +1119,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see ### Restrict to Elements and Attributes ###### [Style [Y074](#style-y074)] - - When creating a directive that makes sense as a stand-alone element, allow restrict `E` (custom element) and optionally restrict `A` (custom attribute). Generally, if it could be its own control, `E` is appropriate. General guideline is allow `EA` but lean towards implementing as an element when its stand-alone and as an attribute when it enhances its existing DOM element. + - When creating a directive that makes sense as a stand-alone element, allow restrict `E` (custom element) and optionally restrict `A` (custom attribute). Generally, if it could be its own control, `E` is appropriate. General guideline is allow `EA` but lean towards implementing as an element when it's stand-alone and as an attribute when it enhances its existing DOM element. *Why?*: It makes sense. From 0e9ffab7e56019ebd09b1ee03bcd0249bcaa057b Mon Sep 17 00:00:00 2001 From: Vinicius Date: Tue, 10 Feb 2015 23:57:53 -0200 Subject: [PATCH 141/567] Translate Testing to pt-BR --- i18n/PT-BR.md | 52 +++++++++++++++++++++++++-------------------------- 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/i18n/PT-BR.md b/i18n/PT-BR.md index 8031d586..04829f2c 100644 --- a/i18n/PT-BR.md +++ b/i18n/PT-BR.md @@ -2125,14 +2125,14 @@ ou *Coletores de exceção* **[⬆ De volta ao topo ⬆](#tabela-de-conte%C3%BAdo)** -## Testing -Unit testing helps maintain clean code, as such I included some of my recommendations for unit testing foundations with links for more information. +## Testando +Testes unitários ajudam a manter o código limpo, tal como, eu inclui algumas recomendações de fundamentos para testes unitários com links para mais informações. -### Write Tests with Stories +### Escreva testes com Histórias(Stories) - - Write a set of tests for every story. Start with an empty test and fill them in as you write the code for the story. + - Escreva um grupo de testes para cada história. Comece com um teste em branco e preencha-o conforme você vai escrevendo o código para a história. - *Why?*: Writing the test descriptions helps clearly define what your story will do, will not do, and how you can measure success. + *Por que?*: Escrevendo uma descrição de teste ajuda a definir claramente o que a sua história vai fazer, não vai fazer, e como você pode mensurar o sucesso. ```javascript it('should have Avengers controller', function() { @@ -2154,53 +2154,53 @@ Unit testing helps maintain clean code, as such I included some of my recommenda // and so on ``` -### Testing Library +### Library para Testes - - Use [Jasmine](http://jasmine.github.io/) or [Mocha](http://visionmedia.github.io/mocha/) for unit testing. + - Para teste unitários use [Jasmine](http://jasmine.github.io/) ou [Mocha](http://visionmedia.github.io/mocha/). - *Why?*: Both Jasmine and Mocha are widely used in the AngularJS community. Both are stable, well maintained, and provide robust testing features. + *Por que?*: Ambos, Jasmine e Mocha são amplamente utilizados na comunidade AngularJS. Ambos são estáveis, são mantidos e provém features de teste robustas. - Note: When using Mocha, also consider choosing an assert library such as [Chai](http://chaijs.com). + Nota: Se escolher Mocha, também considere a escolha de uma Assert Library como [Chai](http://chaijs.com). ### Test Runner - - Use [Karma](http://karma-runner.github.io) as a test runner. + - Use [Karma](http://karma-runner.github.io) como seu test runner. - *Why?*: Karma is easy to configure to run once or automatically when you change your code. + *Por que?*: Karma é fácil de configurar para executar apenas uma vez ou automaticamente enquanto você altera seu código. - *Why?*: Karma hooks into your Continuous Integration process easily on its own or through Grunt or Gulp. + *Por que?*: Karma se integra facilmente com seu processo de Integração Contínua ou através do Grunt ou Gulp. - *Why?*: Some IDE's are beginning to integrate with Karma, such as [WebStorm](http://www.jetbrains.com/webstorm/) and [Visual Studio](http://visualstudiogallery.msdn.microsoft.com/02f47876-0e7a-4f6c-93f8-1af5d5189225). + *Por que?*: Algumas IDE's estão começando a se integrar com o Karma, como [WebStorm](http://www.jetbrains.com/webstorm/) e [Visual Studio](http://visualstudiogallery.msdn.microsoft.com/02f47876-0e7a-4f6c-93f8-1af5d5189225). - *Why?*: Karma works well with task automation leaders such as [Grunt](http://www.gruntjs.com) (with [grunt-karma](https://github.com/karma-runner/grunt-karma)) and [Gulp](http://www.gulpjs.com) (with [gulp-karma](https://github.com/lazd/gulp-karma)). + *Por que?*: Karma funciona muito bem com os líderes de automação de tarefas, como [Grunt](http://www.gruntjs.com) (com [grunt-karma](https://github.com/karma-runner/grunt-karma)) e [Gulp](http://www.gulpjs.com) (com [gulp-karma](https://github.com/lazd/gulp-karma)). ### Stubbing and Spying - - Use Sinon for stubbing and spying. + - Utilize Sinon para stubbing e spying. - *Why?*: Sinon works well with both Jasmine and Mocha and extends the stubbing and spying features they offer. + *Por que?*: Sinon funciona bem tanto com Jasmine quanto com Mocha e amplia as features de stubbing e spying que eles oferecem. - *Why?*: Sinon makes it easier to toggle between Jasmine and Mocha, if you want to try both. + *Por que?*: Sinon faz ficar mais fácil alternar entre Jasmine e Mocha, se você quiser tentar ambos. ### Headless Browser - - Use [PhantomJS](http://phantomjs.org/) to run your tests on a server. + - Use [PhantomJS](http://phantomjs.org/) para executar seus testes no servidor. - *Why?*: PhantomJS is a headless browser that helps run your tests without needing a "visual" browser. So you do not have to install Chrome, Safari, IE, or other browsers on your server. + *Por que?*: PhantomJS é um headless browser que executa os testes sem um navegador "visual". Ou seja, você não precisa instalar Chrome, Safari, IE ou outros navegadores no seu servidor. - Note: You should still test on all browsers in your environment, as appropriate for your target audience. + Nota: Você deve continuar testando em todos os navegadores em seu ambiente, conforme apropriado para seu público alvo. -### Code Analysis +### Análise de Código - - Run JSHint on your tests. + - Execute JSHint no seus testes. - *Why?*: Tests are code. JSHint can help identify code quality issues that may cause the test to work improperly. + *Por que?*: Testes são códigos. JSHint ajuda a identificar problemas de qualidade de código que podem fazer com que o teste execute de maneira errada. -### Alleviate Globals for JSHint Rules on Tests +### Ignore algumas regras globais do JSHint no seus testes - - Relax the rules on your test code to allow for common globals such as `describe` and `expect`. + - Faça com que as regras de teste permitam globais comuns, tais como `describe` e `expect`. - *Why?*: Your tests are code and require the same attention and code quality rules as all of your production code. However, global variables used by the testing framework, for example, can be relaxed by including this in your test specs. + *Por que?*: Seus testes são codigos e necessitam da mesma atenção e regras de qualidade que todo o seu código de produção. No entando, as variáveis globais usadas pelo framework de teste, por exemplo, podem ser ignoradas para inclui-las em seus testes. ```javascript /* global sinon, describe, it, afterEach, beforeEach, expect, inject */ From b063b9b205a2521376557c5ca201cccb5d1397a7 Mon Sep 17 00:00:00 2001 From: Vinicius Date: Wed, 11 Feb 2015 00:00:43 -0200 Subject: [PATCH 142/567] Translate Testing to pt-BR --- i18n/PT-BR.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/i18n/PT-BR.md b/i18n/PT-BR.md index 04829f2c..0bb35d6a 100644 --- a/i18n/PT-BR.md +++ b/i18n/PT-BR.md @@ -2125,7 +2125,7 @@ ou *Coletores de exceção* **[⬆ De volta ao topo ⬆](#tabela-de-conte%C3%BAdo)** -## Testando +## Testing Testes unitários ajudam a manter o código limpo, tal como, eu inclui algumas recomendações de fundamentos para testes unitários com links para mais informações. ### Escreva testes com Histórias(Stories) From e655f2937d799d49ad722a00770fa32d818501c2 Mon Sep 17 00:00:00 2001 From: Vinicius Date: Wed, 11 Feb 2015 00:03:22 -0200 Subject: [PATCH 143/567] Translate Testing to pt-BR --- i18n/PT-BR.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/i18n/PT-BR.md b/i18n/PT-BR.md index 0bb35d6a..770b75a5 100644 --- a/i18n/PT-BR.md +++ b/i18n/PT-BR.md @@ -2130,9 +2130,9 @@ Testes unitários ajudam a manter o código limpo, tal como, eu inclui algumas r ### Escreva testes com Histórias(Stories) - - Escreva um grupo de testes para cada história. Comece com um teste em branco e preencha-o conforme você vai escrevendo o código para a história. + - Escreva um grupo de testes para cada história. Comece com um teste em branco e preencha-o conforme você for escrevendo o código para a história. - *Por que?*: Escrevendo uma descrição de teste ajuda a definir claramente o que a sua história vai fazer, não vai fazer, e como você pode mensurar o sucesso. + *Por que?*: Escrevendo uma descrição de teste te ajudará a definir claramente o que a sua história vai fazer ou não vai fazer e como você pode mensurar o sucesso. ```javascript it('should have Avengers controller', function() { From 0caa8b8c3414fb43b7280b2dd03998b0c2601663 Mon Sep 17 00:00:00 2001 From: Vinicius Date: Wed, 11 Feb 2015 00:08:33 -0200 Subject: [PATCH 144/567] Translate Testing to pt-BR --- i18n/PT-BR.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/i18n/PT-BR.md b/i18n/PT-BR.md index 770b75a5..416e6d16 100644 --- a/i18n/PT-BR.md +++ b/i18n/PT-BR.md @@ -2132,7 +2132,7 @@ Testes unitários ajudam a manter o código limpo, tal como, eu inclui algumas r - Escreva um grupo de testes para cada história. Comece com um teste em branco e preencha-o conforme você for escrevendo o código para a história. - *Por que?*: Escrevendo uma descrição de teste te ajudará a definir claramente o que a sua história vai fazer ou não vai fazer e como você pode mensurar o sucesso. + *Por que?*: Escrevendo uma descrição de teste te ajudará a definir claramente o que a sua história vai fazer ou não vai fazer e como você poderá mensurar o sucesso. ```javascript it('should have Avengers controller', function() { @@ -2174,7 +2174,7 @@ Testes unitários ajudam a manter o código limpo, tal como, eu inclui algumas r *Por que?*: Karma funciona muito bem com os líderes de automação de tarefas, como [Grunt](http://www.gruntjs.com) (com [grunt-karma](https://github.com/karma-runner/grunt-karma)) e [Gulp](http://www.gulpjs.com) (com [gulp-karma](https://github.com/lazd/gulp-karma)). -### Stubbing and Spying +### Stubbing e Spying - Utilize Sinon para stubbing e spying. @@ -2200,7 +2200,7 @@ Testes unitários ajudam a manter o código limpo, tal como, eu inclui algumas r - Faça com que as regras de teste permitam globais comuns, tais como `describe` e `expect`. - *Por que?*: Seus testes são codigos e necessitam da mesma atenção e regras de qualidade que todo o seu código de produção. No entando, as variáveis globais usadas pelo framework de teste, por exemplo, podem ser ignoradas para inclui-las em seus testes. + *Por que?*: Seus testes são codigos e como tal necessitam da mesma atenção e regras de qualidade que todo o seu código de produção. No entanto, as variáveis globais usadas pelo framework de teste, por exemplo, podem ser ignoradas para você utilizá-las em seus testes. ```javascript /* global sinon, describe, it, afterEach, beforeEach, expect, inject */ From 7864ba244e6fd5822253c5396dd4b0bedb000c58 Mon Sep 17 00:00:00 2001 From: Vinicius Date: Wed, 11 Feb 2015 00:10:49 -0200 Subject: [PATCH 145/567] Translate Testing to pt-BR --- i18n/PT-BR.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/i18n/PT-BR.md b/i18n/PT-BR.md index 416e6d16..e8c577a9 100644 --- a/i18n/PT-BR.md +++ b/i18n/PT-BR.md @@ -2200,7 +2200,7 @@ Testes unitários ajudam a manter o código limpo, tal como, eu inclui algumas r - Faça com que as regras de teste permitam globais comuns, tais como `describe` e `expect`. - *Por que?*: Seus testes são codigos e como tal necessitam da mesma atenção e regras de qualidade que todo o seu código de produção. No entanto, as variáveis globais usadas pelo framework de teste, por exemplo, podem ser ignoradas para você utilizá-las em seus testes. + *Por que?*: Seus testes são codigos e como tal necessitam da mesma atenção e regras de qualidade que todo o seu código de produção. No entanto, as variáveis globais usadas pelo framework de teste, por exemplo, podem ser ignoradas para que você as utilize em seus testes. ```javascript /* global sinon, describe, it, afterEach, beforeEach, expect, inject */ From afa1caf277082b0d7cc4b329b661e01fa40422c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89ric=20Le=20Merdy?= Date: Fri, 19 Dec 2014 03:09:48 +0100 Subject: [PATCH 146/567] [FR] First french version --- i18n/fr-FR.md | 2616 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 2616 insertions(+) create mode 100644 i18n/fr-FR.md diff --git a/i18n/fr-FR.md b/i18n/fr-FR.md new file mode 100644 index 00000000..4269cae8 --- /dev/null +++ b/i18n/fr-FR.md @@ -0,0 +1,2616 @@ +# Le Guide Stylistique AngularJS + +*Le guide d'un certain point de vue stylistique sur AngularJS par [@john_papa](//twitter.com/john_papa)* + +Si vous cherchez un guide d'un certain point de vue stylistique pour la syntaxe, les conventions, et la structuration +d'application AngularJS, alors vous êtes au bon endroit. Ces styles sont basés sur mon expérience de dévelopement avec +[AngularJS](//angularjs.org), mes présentations, [mes cours sur Pluralsight](http://pluralsight.com/training/Authors/Details/john-papa) +et mon travail au sein des équipes. + +>Si vous appréciez ce guide, visitez mon cours [AngularJS Patterns: Clean Code](http://jpapa.me/ngclean) sur Pluralsight. + +Le but de ce guide stylistique est de proposer des conseils sur le développement d'applications AngularJS en montrant +les conventions que j'utilise et, plus important encore, les raisons des choix que j'ai pris. + +## Supprématie de la Communauté et Remerciements +Ne jamais travailler dans le vide. J'ai trouvé que la communauté AngularJS est un incroyable groupe dont les membres ont à coeur de partager leurs expériences. Ainsi, un ami et expert AngularJS Todd Motto et moi avons collaboré sur de nombreux styles et conventions. Nous sommes d'accord sur la plupart, et nous divergeons sur d'autres. Je vous encourage à visiter [les guideslines de Todd](https://github.com/toddmotto/angularjs-styleguide) pour vous faire un sentiment sur son approche et en quoi elle est comparable. + +De nombreux de mes styles proviennent des maintes scéances de pair programming que [Ward Bell](http://twitter.com/wardbell) et moi avons eu. Même si nous n'étions pas toujours d'accord, mon ami Ward a assurément contribué à influencer l'évolution ultime de ce guide. + +## Visualiser les Styles dans une Application d'Exemple +Alors que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'a été utile de les visualiser dans la +pratique. Ce guide est accompagné par une application d'exemple qui suit ces styles et ces motifs. Vous pouvez trouver +l'[application d'exemple (appellée modular) ici](https://github.com/johnpapa/ng-demos) dans le répertoire `modular`. +Vous pouvez librement le récupérer, le cloner, ou le dupliquer pour le modifier. [Les instructions pour l'éxécuter sont +contenues dans ce readme](https://github.com/johnpapa/ng-demos/tree/master/modular). + +## Traductions +[Des traductions de ce guide stylistique Angular](https://github.com/johnpapa/angularjs-styleguide/tree/master/i18n) +sont maintenues par la communauté et peuvent être trouvées ici. + +## Table des matières + + 1. [Responsabilité Unique](#responsabilité-unique) + 1. [IIFE](#iife) + 1. [Modules](#modules) + 1. [Controllers](#controllers) + 1. [Services](#services) + 1. [Factories](#factories) + 1. [Data Services](#data-services) + 1. [Directives](#directives) + 1. [Resolving Promises for a Controller](#resolving-promises-for-a-controller) + 1. [Manual Annotating for Dependency Injection](#manual-annotating-for-dependency-injection) + 1. [Minification and Annotation](#minification-and-annotation) + 1. [Exception Handling](#exception-handling) + 1. [Naming](#naming) + 1. [Application Structure LIFT Principle](#application-structure-lift-principle) + 1. [Application Structure](#application-structure) + 1. [Modularity](#modularity) + 1. [Startup Logic](#startup-logic) + 1. [Angular $ Wrapper Services](#angular--wrapper-services) + 1. [Testing](#testing) + 1. [Animations](#animations) + 1. [Comments](#comments) + 1. [JSHint](#js-hint) + 1. [Constants](#constants) + 1. [File Templates and Snippets](#file-templates-and-snippets) + 1. [AngularJS Docs](#angularjs-docs) + 1. [Contributing](#contributing) + 1. [License](#license) + +## Responsabilité Unique + +### La règle de l'unicité +###### [Style [Y001](#style-y001)] + + - Définir 1 composant par fichier. + + L'exemple suivant définit le module `app` et ses dépendances, définit un controlleur, et définit une factory le tout + dans le même fichier. + + ```javascript + /* éviter */ + angular + .module('app', ['ngRoute']) + .controller('SomeController', SomeController) + .factory('someFactory', someFactory); + + function SomeController() { } + + function someFactory() { } + ``` + + Les même composants sont maintenant séparés dans leurs propres fichiers. + + ```javascript + /* recommandé */ + + // app.module.js + angular + .module('app', ['ngRoute']); + ``` + + ```javascript + /* recommandé */ + + // someController.js + angular + .module('app') + .controller('SomeController', SomeController); + + function SomeController() { } + ``` + + ```javascript + /* recommandé */ + + // someFactory.js + angular + .module('app') + .factory('someFactory', someFactory); + + function someFactory() { } + ``` + +**[Retour en haut de page](#table-des-matières)** + +## IIFE +### Les Closures JavaScript +###### [Style [Y010](#style-y010)] + + - Wrap AngularJS components in an Immediately Invoked Function Expression (IIFE). + + *Why?*: An IIFE removes variables from the global scope. This helps prevent variables and function declarations from living longer than expected in the global scope, which also helps avoid variable collisions. + + *Why?*: When your code is minified and bundled into a single file for deployment to a production server, you could have collisions of variables and many global variables. An IIFE protects you against both of these by providing variable scope for each file. + + ```javascript + /* avoid */ + // logger.js + angular + .module('app') + .factory('logger', logger); + + // logger function is added as a global variable + function logger() { } + + // storage.js + angular + .module('app') + .factory('storage', storage); + + // storage function is added as a global variable + function storage() { } + ``` + + + ```javascript + /** + * recommended + * + * no globals are left behind + */ + + // logger.js + (function() { + 'use strict'; + + angular + .module('app') + .factory('logger', logger); + + function logger() { } + })(); + + // storage.js + (function() { + 'use strict'; + + angular + .module('app') + .factory('storage', storage); + + function storage() { } + })(); + ``` + + - Note: For brevity only, the rest of the examples in this guide may omit the IIFE syntax. + + - Note: IIFE's prevent test code from reaching private members like regular expressions or helper functions which are often good to unit test directly on their own. However you can test these through accessible members or by exposing them through their own component. For example placing helper functions, regular expressions or constants in their own factory or constant. + +**[Back to top](#table-of-contents)** + +## Modules + +### Avoid Naming Collisions +###### [Style [Y020](#style-y020)] + + - Use unique naming conventions with separators for sub-modules. + + *Why?*: Unique names help avoid module name collisions. Separators help define modules and their submodule hierarchy. For example `app` may be your root module while `app.dashboard` and `app.users` may be modules that are used as dependencies of `app`. + +### Definitions (aka Setters) +###### [Style [Y021](#style-y021)] + + - Declare modules without a variable using the setter syntax. + + *Why?*: With 1 component per file, there is rarely a need to introduce a variable for the module. + + ```javascript + /* avoid */ + var app = angular.module('app', [ + 'ngAnimate', + 'ngRoute', + 'app.shared', + 'app.dashboard' + ]); + ``` + + Instead use the simple setter syntax. + + ```javascript + /* recommended */ + angular + .module('app', [ + 'ngAnimate', + 'ngRoute', + 'app.shared', + 'app.dashboard' + ]); + ``` + +### Getters +###### [Style [Y022](#style-y022)] + + - When using a module, avoid using a variable and instead use chaining with the getter syntax. + + *Why?* : This produces more readable code and avoids variable collisions or leaks. + + ```javascript + /* avoid */ + var app = angular.module('app'); + app.controller('SomeController', SomeController); + + function SomeController() { } + ``` + + ```javascript + /* recommended */ + angular + .module('app') + .controller('SomeController', SomeController); + + function SomeController() { } + ``` + +### Setting vs Getting +###### [Style [Y023](#style-y023)] + + - Only set once and get for all other instances. + + *Why?*: A module should only be created once, then retrieved from that point and after. + + - Use `angular.module('app', []);` to set a module. + - Use `angular.module('app');` to get a module. + +### Named vs Anonymous Functions +###### [Style [Y024](#style-y024)] + + - Use named functions instead of passing an anonymous function in as a callback. + + *Why?*: This produces more readable code, is much easier to debug, and reduces the amount of nested callback code. + + ```javascript + /* avoid */ + angular + .module('app') + .controller('Dashboard', function() { }) + .factory('logger', function() { }); + ``` + + ```javascript + /* recommended */ + + // dashboard.js + angular + .module('app') + .controller('Dashboard', Dashboard); + + function Dashboard() { } + ``` + + ```javascript + // logger.js + angular + .module('app') + .factory('logger', logger); + + function logger() { } + ``` + +**[Back to top](#table-of-contents)** + +## Controllers + +### controllerAs View Syntax +###### [Style [Y030](#style-y030)] + + - Use the [`controllerAs`](http://www.johnpapa.net/do-you-like-your-angular-controllers-with-or-without-sugar/) syntax over the `classic controller with $scope` syntax. + + *Why?*: Controllers are constructed, "newed" up, and provide a single new instance, and the `controllerAs` syntax is closer to that of a JavaScript constructor than the `classic $scope syntax`. + + *Why?*: It promotes the use of binding to a "dotted" object in the View (e.g. `customer.name` instead of `name`), which is more contextual, easier to read, and avoids any reference issues that may occur without "dotting". + + *Why?*: Helps avoid using `$parent` calls in Views with nested controllers. + + ```html + +
+ {{ name }} +
+ ``` + + ```html + +
+ {{ customer.name }} +
+ ``` + +### controllerAs Controller Syntax +###### [Style [Y031](#style-y031)] + + - Use the `controllerAs` syntax over the `classic controller with $scope` syntax. + + - The `controllerAs` syntax uses `this` inside controllers which gets bound to `$scope` + + *Why?*: `controllerAs` is syntactic sugar over `$scope`. You can still bind to the View and still access `$scope` methods. + + *Why?*: Helps avoid the temptation of using `$scope` methods inside a controller when it may otherwise be better to avoid them or move them to a factory. Consider using `$scope` in a factory, or if in a controller just when needed. For example when publishing and subscribing events using [`$emit`](https://docs.angularjs.org/api/ng/type/$rootScope.Scope#$emit), [`$broadcast`](https://docs.angularjs.org/api/ng/type/$rootScope.Scope#$broadcast), or [`$on`](https://docs.angularjs.org/api/ng/type/$rootScope.Scope#$on) consider moving these uses to a factory and invoke from the controller. + + ```javascript + /* avoid */ + function Customer($scope) { + $scope.name = {}; + $scope.sendMessage = function() { }; + } + ``` + + ```javascript + /* recommended - but see next section */ + function Customer() { + this.name = {}; + this.sendMessage = function() { }; + } + ``` + +### controllerAs with vm +###### [Style [Y032](#style-y032)] + + - Use a capture variable for `this` when using the `controllerAs` syntax. Choose a consistent variable name such as `vm`, which stands for ViewModel. + + *Why?*: The `this` keyword is contextual and when used within a function inside a controller may change its context. Capturing the context of `this` avoids encountering this problem. + + ```javascript + /* avoid */ + function Customer() { + this.name = {}; + this.sendMessage = function() { }; + } + ``` + + ```javascript + /* recommended */ + function Customer() { + var vm = this; + vm.name = {}; + vm.sendMessage = function() { }; + } + ``` + + Note: You can avoid any [jshint](http://www.jshint.com/) warnings by placing the comment below above the line of code. However it is not needed when the function is named using UpperCasing, as this convention means it is a constructor function, which is what a controller is in Angular. + + ```javascript + /* jshint validthis: true */ + var vm = this; + ``` + + Note: When creating watches in a controller using `controller as`, you can watch the `vm.*` member using the following syntax. (Create watches with caution as they add more load to the digest cycle.) + + ```html + + ``` + + ```javascript + function SomeController($scope, $log) { + var vm = this; + vm.title = 'Some Title'; + + $scope.$watch('vm.title', function(current, original) { + $log.info('vm.title was %s', original); + $log.info('vm.title is now %s', current); + }); + } + ``` + +### Bindable Members Up Top +###### [Style [Y033](#style-y033)] + + - Place bindable members at the top of the controller, alphabetized, and not spread through the controller code. + + *Why?*: Placing bindable members at the top makes it easy to read and helps you instantly identify which members of the controller can be bound and used in the View. + + *Why?*: Setting anonymous functions in-line can be easy, but when those functions are more than 1 line of code they can reduce the readability. Defining the functions below the bindable members (the functions will be hoisted) moves the implementation details down, keeps the bindable members up top, and makes it easier to read. + + ```javascript + /* avoid */ + function Sessions() { + var vm = this; + + vm.gotoSession = function() { + /* ... */ + }; + vm.refresh = function() { + /* ... */ + }; + vm.search = function() { + /* ... */ + }; + vm.sessions = []; + vm.title = 'Sessions'; + ``` + + ```javascript + /* recommended */ + function Sessions() { + var vm = this; + + vm.gotoSession = gotoSession; + vm.refresh = refresh; + vm.search = search; + vm.sessions = []; + vm.title = 'Sessions'; + + //////////// + + function gotoSession() { + /* */ + } + + function refresh() { + /* */ + } + + function search() { + /* */ + } + ``` + + ![Controller Using "Above the Fold"](https://raw.githubusercontent.com/johnpapa/angularjs-styleguide/master/assets/above-the-fold-1.png) + + Note: If the function is a 1 liner consider keeping it right up top, as long as readability is not affected. + + ```javascript + /* avoid */ + function Sessions(data) { + var vm = this; + + vm.gotoSession = gotoSession; + vm.refresh = function() { + /** + * lines + * of + * code + * affects + * readability + */ + }; + vm.search = search; + vm.sessions = []; + vm.title = 'Sessions'; + ``` + + ```javascript + /* recommended */ + function Sessions(dataservice) { + var vm = this; + + vm.gotoSession = gotoSession; + vm.refresh = dataservice.refresh; // 1 liner is OK + vm.search = search; + vm.sessions = []; + vm.title = 'Sessions'; + ``` + +### Function Declarations to Hide Implementation Details +###### [Style [Y034](#style-y034)] + + - Use function declarations to hide implementation details. Keep your bindable members up top. When you need to bind a function in a controller, point it to a function declaration that appears later in the file. This is tied directly to the section Bindable Members Up Top. For more details see [this post](http://www.johnpapa.net/angular-function-declarations-function-expressions-and-readable-code). + + *Why?*: Placing bindable members at the top makes it easy to read and helps you instantly identify which members of the controller can be bound and used in the View. (Same as above.) + + *Why?*: Placing the implementation details of a function later in the file moves that complexity out of view so you can see the important stuff up top. + + *Why?*: Function declaration are hoisted so there are no concerns over using a function before it is defined (as there would be with function expressions). + + *Why?*: You never have to worry with function declarations that moving `var a` before `var b` will break your code because `a` depends on `b`. + + *Why?*: Order is critical with function expressions + + ```javascript + /** + * avoid + * Using function expressions. + */ + function Avengers(dataservice, logger) { + var vm = this; + vm.avengers = []; + vm.title = 'Avengers'; + + var activate = function() { + return getAvengers().then(function() { + logger.info('Activated Avengers View'); + }); + } + + var getAvengers = function() { + return dataservice.getAvengers().then(function(data) { + vm.avengers = data; + return vm.avengers; + }); + } + + vm.getAvengers = getAvengers; + + activate(); + } + ``` + + Notice that the important stuff is scattered in the preceding example. In the example below, notice that the important stuff is up top. For example, the members bound to the controller such as `vm.avengers` and `vm.title`. The implementation details are down below. This is just easier to read. + + ```javascript + /* + * recommend + * Using function declarations + * and bindable members up top. + */ + function Avengers(dataservice, logger) { + var vm = this; + vm.avengers = []; + vm.getAvengers = getAvengers; + vm.title = 'Avengers'; + + activate(); + + function activate() { + return getAvengers().then(function() { + logger.info('Activated Avengers View'); + }); + } + + function getAvengers() { + return dataservice.getAvengers().then(function(data) { + vm.avengers = data; + return vm.avengers; + }); + } + } + ``` + +### Defer Controller Logic +###### [Style [Y035](#style-y035)] + + - Defer logic in a controller by delegating to services and factories. + + *Why?*: Logic may be reused by multiple controllers when placed within a service and exposed via a function. + + *Why?*: Logic in a service can more easily be isolated in a unit test, while the calling logic in the controller can be easily mocked. + + *Why?*: Removes dependencies and hides implementation details from the controller. + + ```javascript + + /* avoid */ + function Order($http, $q, config, userInfo) { + var vm = this; + vm.checkCredit = checkCredit; + vm.isCreditOk; + vm.total = 0; + + function checkCredit() { + var settings = {}; + // Get the credit service base URL from config + // Set credit service required headers + // Prepare URL query string or data object with request data + // Add user-identifying info so service gets the right credit limit for this user. + // Use JSONP for this browser if it doesn't support CORS + return $http.get(settings) + .then(function(data) { + // Unpack JSON data in the response object + // to find maxRemainingAmount + vm.isCreditOk = vm.total <= maxRemainingAmount + }) + .catch(function(error) { + // Interpret error + // Cope w/ timeout? retry? try alternate service? + // Re-reject with appropriate error for a user to see + }); + }; + } + ``` + + ```javascript + + /* recommended */ + function Order(creditService) { + var vm = this; + vm.checkCredit = checkCredit; + vm.isCreditOk; + vm.total = 0; + + function checkCredit() { + return creditService.isOrderTotalOk(vm.total) + .then(function(isOk) { vm.isCreditOk = isOk; }) + .catch(showServiceError); + }; + } + ``` + +### Keep Controllers Focused +###### [Style [Y037](#style-y037)] + + - Define a controller for a view, and try not to reuse the controller for other views. Instead, move reusable logic to factories and keep the controller simple and focused on its view. + + *Why?*: Reusing controllers with several views is brittle and good end to end (e2e) test coverage is required to ensure stability across large applications. + +### Assigning Controllers +###### [Style [Y038](#style-y038)] + + - When a controller must be paired with a view and either component may be re-used by other controllers or views, define controllers along with their routes. + + Note: If a View is loaded via another means besides a route, then use the `ng-controller="Avengers as vm"` syntax. + + *Why?*: Pairing the controller in the route allows different routes to invoke different pairs of controllers and views. When controllers are assigned in the view using [`ng-controller`](https://docs.angularjs.org/api/ng/directive/ngController), that view is always associated with the same controller. + + ```javascript + /* avoid - when using with a route and dynamic pairing is desired */ + + // route-config.js + angular + .module('app') + .config(config); + + function config($routeProvider) { + $routeProvider + .when('/avengers', { + templateUrl: 'avengers.html' + }); + } + ``` + + ```html + +
+
+ ``` + + ```javascript + /* recommended */ + + // route-config.js + angular + .module('app') + .config(config); + + function config($routeProvider) { + $routeProvider + .when('/avengers', { + templateUrl: 'avengers.html', + controller: 'Avengers', + controllerAs: 'vm' + }); + } + ``` + + ```html + +
+
+ ``` + +**[Back to top](#table-of-contents)** + +## Services + +### Singletons +###### [Style [Y040](#style-y040)] + + - Services are instantiated with the `new` keyword, use `this` for public methods and variables. Since these are so similar to factories, use a factory instead for consistency. + + Note: [All AngularJS services are singletons](https://docs.angularjs.org/guide/services). This means that there is only one instance of a given service per injector. + + ```javascript + // service + angular + .module('app') + .service('logger', logger); + + function logger() { + this.logError = function(msg) { + /* */ + }; + } + ``` + + ```javascript + // factory + angular + .module('app') + .factory('logger', logger); + + function logger() { + return { + logError: function(msg) { + /* */ + } + }; + } + ``` + +**[Back to top](#table-of-contents)** + +## Factories + +### Single Responsibility +###### [Style [Y050](#style-y050)] + + - Factories should have a [single responsibility](http://en.wikipedia.org/wiki/Single_responsibility_principle), that is encapsulated by its context. Once a factory begins to exceed that singular purpose, a new factory should be created. + +### Singletons +###### [Style [Y051](#style-y051)] + + - Factories are singletons and return an object that contains the members of the service. + + Note: [All AngularJS services are singletons](https://docs.angularjs.org/guide/services). + +### Accessible Members Up Top +###### [Style [Y052](#style-y052)] + + - Expose the callable members of the service (it's interface) at the top, using a technique derived from the [Revealing Module Pattern](http://addyosmani.com/resources/essentialjsdesignpatterns/book/#revealingmodulepatternjavascript). + + *Why?*: Placing the callable members at the top makes it easy to read and helps you instantly identify which members of the service can be called and must be unit tested (and/or mocked). + + *Why?*: This is especially helpful when the file gets longer as it helps avoid the need to scroll to see what is exposed. + + *Why?*: Setting functions as you go can be easy, but when those functions are more than 1 line of code they can reduce the readability and cause more scrolling. Defining the callable interface via the returned service moves the implementation details down, keeps the callable interface up top, and makes it easier to read. + + ```javascript + /* avoid */ + function dataService() { + var someValue = ''; + function save() { + /* */ + }; + function validate() { + /* */ + }; + + return { + save: save, + someValue: someValue, + validate: validate + }; + } + ``` + + ```javascript + /* recommended */ + function dataService() { + var someValue = ''; + var service = { + save: save, + someValue: someValue, + validate: validate + }; + return service; + + //////////// + + function save() { + /* */ + }; + + function validate() { + /* */ + }; + } + ``` + + This way bindings are mirrored across the host object, primitive values cannot update alone using the revealing module pattern + + ![Factories Using "Above the Fold"](https://raw.githubusercontent.com/johnpapa/angularjs-styleguide/master/assets/above-the-fold-2.png) + +### Function Declarations to Hide Implementation Details +###### [Style [Y053](#style-y053)] + + - Use function declarations to hide implementation details. Keep your accessible members of the factory up top. Point those to function declarations that appears later in the file. For more details see [this post](http://www.johnpapa.net/angular-function-declarations-function-expressions-and-readable-code). + + *Why?*: Placing accessible members at the top makes it easy to read and helps you instantly identify which functions of the factory you can access externally. + + *Why?*: Placing the implementation details of a function later in the file moves that complexity out of view so you can see the important stuff up top. + + *Why?*: Function declaration are hoisted so there are no concerns over using a function before it is defined (as there would be with function expressions). + + *Why?*: You never have to worry with function declarations that moving `var a` before `var b` will break your code because `a` depends on `b`. + + *Why?*: Order is critical with function expressions + + ```javascript + /** + * avoid + * Using function expressions + */ + function dataservice($http, $location, $q, exception, logger) { + var isPrimed = false; + var primePromise; + + var getAvengers = function() { + // implementation details go here + }; + + var getAvengerCount = function() { + // implementation details go here + }; + + var getAvengersCast = function() { + // implementation details go here + }; + + var prime = function() { + // implementation details go here + }; + + var ready = function(nextPromises) { + // implementation details go here + }; + + var service = { + getAvengersCast: getAvengersCast, + getAvengerCount: getAvengerCount, + getAvengers: getAvengers, + ready: ready + }; + + return service; + } + ``` + + ```javascript + /** + * recommended + * Using function declarations + * and accessible members up top. + */ + function dataservice($http, $location, $q, exception, logger) { + var isPrimed = false; + var primePromise; + + var service = { + getAvengersCast: getAvengersCast, + getAvengerCount: getAvengerCount, + getAvengers: getAvengers, + ready: ready + }; + + return service; + + //////////// + + function getAvengers() { + // implementation details go here + } + + function getAvengerCount() { + // implementation details go here + } + + function getAvengersCast() { + // implementation details go here + } + + function prime() { + // implementation details go here + } + + function ready(nextPromises) { + // implementation details go here + } + } + ``` + +**[Back to top](#table-of-contents)** + +## Data Services + +### Separate Data Calls +###### [Style [Y060](#style-y060)] + + - Refactor logic for making data operations and interacting with data to a factory. Make data services responsible for XHR calls, local storage, stashing in memory, or any other data operations. + + *Why?*: The controller's responsibility is for the presentation and gathering of information for the view. It should not care how it gets the data, just that it knows who to ask for it. Separating the data services moves the logic on how to get it to the data service, and lets the controller be simpler and more focused on the view. + + *Why?*: This makes it easier to test (mock or real) the data calls when testing a controller that uses a data service. + + *Why?*: Data service implementation may have very specific code to handle the data repository. This may include headers, how to talk to the data, or other services such as $http. Separating the logic into a data service encapsulates this logic in a single place hiding the implementation from the outside consumers (perhaps a controller), also making it easier to change the implementation. + + ```javascript + /* recommended */ + + // dataservice factory + angular + .module('app.core') + .factory('dataservice', dataservice); + + dataservice.$inject = ['$http', 'logger']; + + function dataservice($http, logger) { + return { + getAvengers: getAvengers + }; + + function getAvengers() { + return $http.get('/api/maa') + .then(getAvengersComplete) + .catch(getAvengersFailed); + + function getAvengersComplete(response) { + return response.data.results; + } + + function getAvengersFailed(error) { + logger.error('XHR Failed for getAvengers.' + error.data); + } + } + } + ``` + + Note: The data service is called from consumers, such as a controller, hiding the implementation from the consumers, as shown below. + + ```javascript + /* recommended */ + + // controller calling the dataservice factory + angular + .module('app.avengers') + .controller('Avengers', Avengers); + + Avengers.$inject = ['dataservice', 'logger']; + + function Avengers(dataservice, logger) { + var vm = this; + vm.avengers = []; + + activate(); + + function activate() { + return getAvengers().then(function() { + logger.info('Activated Avengers View'); + }); + } + + function getAvengers() { + return dataservice.getAvengers() + .then(function(data) { + vm.avengers = data; + return vm.avengers; + }); + } + } + ``` + +### Return a Promise from Data Calls +###### [Style [Y061](#style-y061)] + + - When calling a data service that returns a promise such as $http, return a promise in your calling function too. + + *Why?*: You can chain the promises together and take further action after the data call completes and resolves or rejects the promise. + + ```javascript + /* recommended */ + + activate(); + + function activate() { + /** + * Step 1 + * Ask the getAvengers function for the + * avenger data and wait for the promise + */ + return getAvengers().then(function() { + /** + * Step 4 + * Perform an action on resolve of final promise + */ + logger.info('Activated Avengers View'); + }); + } + + function getAvengers() { + /** + * Step 2 + * Ask the data service for the data and wait + * for the promise + */ + return dataservice.getAvengers() + .then(function(data) { + /** + * Step 3 + * set the data and resolve the promise + */ + vm.avengers = data; + return vm.avengers; + }); + } + ``` + + **[Back to top](#table-of-contents)** + +## Directives +### Limit 1 Per File +###### [Style [Y070](#style-y070)] + + - Create one directive per file. Name the file for the directive. + + *Why?*: It is easy to mash all the directives in one file, but difficult to then break those out so some are shared across apps, some across modules, some just for one module. + + *Why?*: One directive per file is easy to maintain. + + ```javascript + /* avoid */ + /* directives.js */ + + angular + .module('app.widgets') + + /* order directive that is specific to the order module */ + .directive('orderCalendarRange', orderCalendarRange) + + /* sales directive that can be used anywhere across the sales app */ + .directive('salesCustomerInfo', salesCustomerInfo) + + /* spinner directive that can be used anywhere across apps */ + .directive('sharedSpinner', sharedSpinner); + + + function orderCalendarRange() { + /* implementation details */ + } + + function salesCustomerInfo() { + /* implementation details */ + } + + function sharedSpinner() { + /* implementation details */ + } + ``` + + ```javascript + /* recommended */ + /* calendarRange.directive.js */ + + /** + * @desc order directive that is specific to the order module at a company named Acme + * @example
+ */ + angular + .module('sales.order') + .directive('acmeOrderCalendarRange', orderCalendarRange); + + function orderCalendarRange() { + /* implementation details */ + } + ``` + + ```javascript + /* recommended */ + /* customerInfo.directive.js */ + + /** + * @desc spinner directive that can be used anywhere across the sales app at a company named Acme + * @example
+ */ + angular + .module('sales.widgets') + .directive('acmeSalesCustomerInfo', salesCustomerInfo); + + function salesCustomerInfo() { + /* implementation details */ + } + ``` + + ```javascript + /* recommended */ + /* spinner.directive.js */ + + /** + * @desc spinner directive that can be used anywhere across apps at a company named Acme + * @example
+ */ + angular + .module('shared.widgets') + .directive('acmeSharedSpinner', sharedSpinner); + + function sharedSpinner() { + /* implementation details */ + } + ``` + + Note: There are many naming options for directives, especially since they can be used in narrow or wide scopes. Choose one that makes the directive and it's file name distinct and clear. Some examples are below, but see the naming section for more recommendations. + +### Manipulate DOM in a Directive +###### [Style [Y072](#style-y072)] + + - When manipulating the DOM directly, use a directive. If alternative ways can be used such as using CSS to set styles or the [animation services](https://docs.angularjs.org/api/ngAnimate), Angular templating, [`ngShow`](https://docs.angularjs.org/api/ng/directive/ngShow) or [`ngHide`](https://docs.angularjs.org/api/ng/directive/ngHide), then use those instead. For example, if the directive simply hides and shows, use ngHide/ngShow. + + *Why?*: DOM manipulation can be difficult to test, debug, and there are often better ways (e.g. CSS, animations, templates) + +### Provide a Unique Directive Prefix +###### [Style [Y073](#style-y073)] + + - Provide a short, unique and descriptive directive prefix such as `acmeSalesCustomerInfo` which is declared in HTML as `acme-sales-customer-info`. + + *Why?*: The unique short prefix identifies the directive's context and origin. For example a prefix of `cc-` may indicate that the directive is part of a CodeCamper app while `acme-` may indicate a directive for the Acme company. + + Note: Avoid `ng-` as these are reserved for AngularJS directives.Research widely used directives to avoid naming conflicts, such as `ion-` for the [Ionic Framework](http://ionicframework.com/). + +### Restrict to Elements and Attributes +###### [Style [Y074](#style-y074)] + + - When creating a directive that makes sense as a standalone element, allow restrict `E` (custom element) and optionally restrict `A` (custom attribute). Generally, if it could be its own control, `E` is appropriate. General guideline is allow `EA` but lean towards implementing as an element when its standalone and as an attribute when it enhances its existing DOM element. + + *Why?*: It makes sense. + + *Why?*: While we can allow the directive to be used as a class, if the directive is truly acting as an element it makes more sense as an element or at least as an attribute. + + Note: EA is the default for AngularJS 1.3 + + + ```html + +
+ ``` + + ```javascript + /* avoid */ + angular + .module('app.widgets') + .directive('myCalendarRange', myCalendarRange); + + function myCalendarRange() { + var directive = { + link: link, + templateUrl: '/template/is/located/here.html', + restrict: 'C' + }; + return directive; + + function link(scope, element, attrs) { + /* */ + } + } + ``` + + ```html + + +
+ ``` + + ```javascript + /* recommended */ + angular + .module('app.widgets') + .directive('myCalendarRange', myCalendarRange); + + function myCalendarRange() { + var directive = { + link: link, + templateUrl: '/template/is/located/here.html', + restrict: 'EA' + }; + return directive; + + function link(scope, element, attrs) { + /* */ + } + } + ``` + +### Directives and ControllerAs +###### [Style [Y075](#style-y075)] + + - Use `controller as` syntax with a directive to be consistent with using `controller as` with view and controller pairings. + + *Why?*: It makes sense and it's not difficult. + + Note: The directive below demonstrates some of the ways you can use scope inside of link and directive controllers, using controllerAs. I in-lined the template just to keep it all in one place. + + Note: Regarding dependency injection, see [Manually Identify Dependencies](#manual-annotating-for-dependency-injection). + + Note: Note that the directive's controller is outside the directive's closure. This style eliminates issues where the injection gets created as unreachable code after a `return`. + + ```html +
+ ``` + + ```javascript + angular + .module('app') + .directive('myExample', myExample); + + function myExample() { + var directive = { + restrict: 'EA', + templateUrl: 'app/feature/example.directive.html', + scope: { + max: '=' + }, + link: linkFunc, + controller : ExampleController, + controllerAs: 'vm' + }; + + return directive; + + function linkFunc(scope, el, attr, ctrl) { + console.log('LINK: scope.max = %i', scope.max); + console.log('LINK: scope.vm.min = %i', scope.vm.min); + console.log('LINK: scope.vm.max = %i', scope.vm.max); + } + } + + ExampleController.$inject = ['$scope']; + + function ExampleController($scope) { + // Injecting $scope just for comparison + var vm = this; + + vm.min = 3; + vm.max = $scope.max; + console.log('CTRL: $scope.max = %i', $scope.max); + console.log('CTRL: vm.min = %i', vm.min); + console.log('CTRL: vm.max = %i', vm.max); + } + ``` + + ```html + /* example.directive.html */ +
hello world
+
max={{vm.max}}
+
min={{vm.min}}
+ ``` + +**[Back to top](#table-of-contents)** + +## Resolving Promises for a Controller + +### Controller Activation Promises +###### [Style [Y080](#style-y080)] + + - Resolve start-up logic for a controller in an `activate` function. + + *Why?*: Placing start-up logic in a consistent place in the controller makes it easier to locate, more consistent to test, and helps avoid spreading out the activation logic across the controller. + + Note: If you need to conditionally cancel the route before you start use the controller, use a route resolve instead. + + ```javascript + /* avoid */ + function Avengers(dataservice) { + var vm = this; + vm.avengers = []; + vm.title = 'Avengers'; + + dataservice.getAvengers().then(function(data) { + vm.avengers = data; + return vm.avengers; + }); + } + ``` + + ```javascript + /* recommended */ + function Avengers(dataservice) { + var vm = this; + vm.avengers = []; + vm.title = 'Avengers'; + + activate(); + + //////////// + + function activate() { + return dataservice.getAvengers().then(function(data) { + vm.avengers = data; + return vm.avengers; + }); + } + } + ``` + +### Route Resolve Promises +###### [Style [Y081](#style-y081)] + + - When a controller depends on a promise to be resolved, resolve those dependencies in the `$routeProvider` before the controller logic is executed. If you need to conditionally cancel a route before the controller is activated, use a route resolver. + + *Why?*: A controller may require data before it loads. That data may come from a promise via a custom factory or [$http](https://docs.angularjs.org/api/ng/service/$http). Using a [route resolve](https://docs.angularjs.org/api/ngRoute/provider/$routeProvider) allows the promise to resolve before the controller logic executes, so it might take action based on that data from the promise. + + ```javascript + /* avoid */ + angular + .module('app') + .controller('Avengers', Avengers); + + function Avengers(movieService) { + var vm = this; + // unresolved + vm.movies; + // resolved asynchronously + movieService.getMovies().then(function(response) { + vm.movies = response.movies; + }); + } + ``` + + ```javascript + /* better */ + + // route-config.js + angular + .module('app') + .config(config); + + function config($routeProvider) { + $routeProvider + .when('/avengers', { + templateUrl: 'avengers.html', + controller: 'Avengers', + controllerAs: 'vm', + resolve: { + moviesPrepService: function(movieService) { + return movieService.getMovies(); + } + } + }); + } + + // avengers.js + angular + .module('app') + .controller('Avengers', Avengers); + + Avengers.$inject = ['moviesPrepService']; + function Avengers(moviesPrepService) { + var vm = this; + vm.movies = moviesPrepService.movies; + } + ``` + + Note: The code example's dependency on `movieService` is not minification safe on its own. For details on how to make this code minification safe, see the sections on [dependency injection](#manual-annotating-for-dependency-injection) and on [minification and annotation](#minification-and-annotation). + +**[Back to top](#table-of-contents)** + +## Manual Annotating for Dependency Injection + +### UnSafe from Minification +###### [Style [Y090](#style-y090)] + + - Avoid using the shortcut syntax of declaring dependencies without using a minification-safe approach. + + *Why?*: The parameters to the component (e.g. controller, factory, etc) will be converted to mangled variables. For example, `common` and `dataservice` may become `a` or `b` and not be found by AngularJS. + + ```javascript + /* avoid - not minification-safe*/ + angular + .module('app') + .controller('Dashboard', Dashboard); + + function Dashboard(common, dataservice) { + } + ``` + + This code may produce mangled variables when minified and thus cause runtime errors. + + ```javascript + /* avoid - not minification-safe*/ + angular.module('app').controller('Dashboard', d);function d(a, b) { } + ``` + +### Manually Identify Dependencies +###### [Style [Y091](#style-y091)] + + - Use `$inject` to manually identify your dependencies for AngularJS components. + + *Why?*: This technique mirrors the technique used by [`ng-annotate`](https://github.com/olov/ng-annotate), which I recommend for automating the creation of minification safe dependencies. If `ng-annotate` detects injection has already been made, it will not duplicate it. + + *Why?*: This safeguards your dependencies from being vulnerable to minification issues when parameters may be mangled. For example, `common` and `dataservice` may become `a` or `b` and not be found by AngularJS. + + *Why?*: Avoid creating in-line dependencies as long lists can be difficult to read in the array. Also it can be confusing that the array is a series of strings while the last item is the component's function. + + ```javascript + /* avoid */ + angular + .module('app') + .controller('Dashboard', + ['$location', '$routeParams', 'common', 'dataservice', + function Dashboard($location, $routeParams, common, dataservice) {} + ]); + ``` + + ```javascript + /* avoid */ + angular + .module('app') + .controller('Dashboard', + ['$location', '$routeParams', 'common', 'dataservice', Dashboard]); + + function Dashboard($location, $routeParams, common, dataservice) { + } + ``` + + ```javascript + /* recommended */ + angular + .module('app') + .controller('Dashboard', Dashboard); + + Dashboard.$inject = ['$location', '$routeParams', 'common', 'dataservice']; + + function Dashboard($location, $routeParams, common, dataservice) { + } + ``` + + Note: When your function is below a return statement the $inject may be unreachable (this may happen in a directive). You can solve this by either moving the $inject above the return statement or by using the alternate array injection syntax. + + Note: [`ng-annotate 0.10.0`](https://github.com/olov/ng-annotate) introduced a feature where it moves the `$inject` to where it is reachable. + + ```javascript + // inside a directive definition + function outer() { + return { + controller: DashboardPanel, + }; + + DashboardPanel.$inject = ['logger']; // Unreachable + function DashboardPanel(logger) { + } + } + ``` + + ```javascript + // inside a directive definition + function outer() { + DashboardPanel.$inject = ['logger']; // reachable + return { + controller: DashboardPanel, + }; + + function DashboardPanel(logger) { + } + } + ``` + +### Manually Identify Route Resolver Dependencies +###### [Style [Y092](#style-y092)] + + - Use $inject to manually identify your route resolver dependencies for AngularJS components. + + *Why?*: This technique breaks out the anonymous function for the route resolver, making it easier to read. + + *Why?*: An `$inject` statement can easily precede the resolver to handle making any dependencies minification safe. + + ```javascript + /* recommended */ + function config($routeProvider) { + $routeProvider + .when('/avengers', { + templateUrl: 'avengers.html', + controller: 'Avengers', + controllerAs: 'vm', + resolve: { + moviesPrepService: moviePrepService + } + }); + } + + moviePrepService.$inject = ['movieService']; + function moviePrepService(movieService) { + return movieService.getMovies(); + } + ``` + +**[Back to top](#table-of-contents)** + +## Minification and Annotation + +### ng-annotate +###### [Style [Y100](#style-y100)] + + - Use [ng-annotate](//github.com/olov/ng-annotate) for [Gulp](http://gulpjs.com) or [Grunt](http://gruntjs.com) and comment functions that need automated dependency injection using `/** @ngInject */` + + *Why?*: This safeguards your code from any dependencies that may not be using minification-safe practices. + + *Why?*: [`ng-min`](https://github.com/btford/ngmin) is deprecated + + >I prefer Gulp as I feel it is easier to write, to read, and to debug. + + The following code is not using minification safe dependencies. + + ```javascript + angular + .module('app') + .controller('Avengers', Avengers); + + /* @ngInject */ + function Avengers(storageService, avengerService) { + var vm = this; + vm.heroSearch = ''; + vm.storeHero = storeHero; + + function storeHero(){ + var hero = avengerService.find(vm.heroSearch); + storageService.save(hero.name, hero); + } + } + ``` + + When the above code is run through ng-annotate it will produce the following output with the `$inject` annotation and become minification-safe. + + ```javascript + angular + .module('app') + .controller('Avengers', Avengers); + + /* @ngInject */ + function Avengers(storageService, avengerService) { + var vm = this; + vm.heroSearch = ''; + vm.storeHero = storeHero; + + function storeHero(){ + var hero = avengerService.find(vm.heroSearch); + storageService.save(hero.name, hero); + } + } + + Avengers.$inject = ['storageService', 'avengerService']; + ``` + + Note: If `ng-annotate` detects injection has already been made (e.g. `@ngInject` was detected), it will not duplicate the `$inject` code. + + Note: When using a route resolver you can prefix the resolver's function with `/* @ngInject */` and it will produce properly annotated code, keeping any injected dependencies minification safe. + + ```javascript + // Using @ngInject annotations + function config($routeProvider) { + $routeProvider + .when('/avengers', { + templateUrl: 'avengers.html', + controller: 'Avengers', + controllerAs: 'vm', + resolve: { /* @ngInject */ + moviesPrepService: function(movieService) { + return movieService.getMovies(); + } + } + }); + } + ``` + + > Note: Starting from AngularJS 1.3 use the [`ngApp`](https://docs.angularjs.org/api/ng/directive/ngApp) directive's `ngStrictDi` parameter. When present the injector will be created in "strict-di" mode causing the application to fail to invoke functions which do not use explicit function annotation (these may not be minification safe). Debugging info will be logged to the console to help track down the offending code. + `` + +### Use Gulp or Grunt for ng-annotate +###### [Style [Y101](#style-y101)] + + - Use [gulp-ng-annotate](https://www.npmjs.org/package/gulp-ng-annotate) or [grunt-ng-annotate](https://www.npmjs.org/package/grunt-ng-annotate) in an automated build task. Inject `/* @ngInject */` prior to any function that has dependencies. + + *Why?*: ng-annotate will catch most dependencies, but it sometimes requires hints using the `/* @ngInject */` syntax. + + The following code is an example of a gulp task using ngAnnotate + + ```javascript + gulp.task('js', ['jshint'], function() { + var source = pkg.paths.js; + return gulp.src(source) + .pipe(sourcemaps.init()) + .pipe(concat('all.min.js', {newLine: ';'})) + // Annotate before uglify so the code get's min'd properly. + .pipe(ngAnnotate({ + // true helps add where @ngInject is not used. It infers. + // Doesn't work with resolve, so we must be explicit there + add: true + })) + .pipe(bytediff.start()) + .pipe(uglify({mangle: true})) + .pipe(bytediff.stop()) + .pipe(sourcemaps.write('./')) + .pipe(gulp.dest(pkg.paths.dev)); + }); + + ``` + +**[Back to top](#table-of-contents)** + +## Exception Handling + +### decorators +###### [Style [Y110](#style-y110)] + + - Use a [decorator](https://docs.angularjs.org/api/auto/service/$provide#decorator), at config time using the [`$provide`](https://docs.angularjs.org/api/auto/service/$provide) service, on the [`$exceptionHandler`](https://docs.angularjs.org/api/ng/service/$exceptionHandler) service to perform custom actions when exceptions occur. + + *Why?*: Provides a consistent way to handle uncaught AngularJS exceptions for development-time or run-time. + + Note: Another option is to override the service instead of using a decorator. This is a fine option, but if you want to keep the default behavior and extend it a decorator is recommended. + + ```javascript + /* recommended */ + angular + .module('blocks.exception') + .config(exceptionConfig); + + exceptionConfig.$inject = ['$provide']; + + function exceptionConfig($provide) { + $provide.decorator('$exceptionHandler', extendExceptionHandler); + } + + extendExceptionHandler.$inject = ['$delegate', 'toastr']; + + function extendExceptionHandler($delegate, toastr) { + return function(exception, cause) { + $delegate(exception, cause); + var errorData = { + exception: exception, + cause: cause + }; + /** + * Could add the error to a service's collection, + * add errors to $rootScope, log errors to remote web server, + * or log locally. Or throw hard. It is entirely up to you. + * throw exception; + */ + toastr.error(exception.msg, errorData); + }; + } + ``` + +### Exception Catchers +###### [Style [Y111](#style-y111)] + + - Create a factory that exposes an interface to catch and gracefully handle exceptions. + + *Why?*: Provides a consistent way to catch exceptions that may be thrown in your code (e.g. during XHR calls or promise failures). + + Note: The exception catcher is good for catching and reacting to specific exceptions from calls that you know may throw one. For example, when making an XHR call to retrieve data from a remote web service and you want to catch any exceptions from that service and react uniquely. + + ```javascript + /* recommended */ + angular + .module('blocks.exception') + .factory('exception', exception); + + exception.$inject = ['logger']; + + function exception(logger) { + var service = { + catcher: catcher + }; + return service; + + function catcher(message) { + return function(reason) { + logger.error(message, reason); + }; + } + } + ``` + +### Route Errors +###### [Style [Y112](#style-y112)] + + - Handle and log all routing errors using [`$routeChangeError`](https://docs.angularjs.org/api/ngRoute/service/$route#$routeChangeError). + + *Why?*: Provides a consistent way handle all routing errors. + + *Why?*: Potentially provides a better user experience if a routing error occurs and you route them to a friendly screen with more details or recovery options. + + ```javascript + /* recommended */ + function handleRoutingErrors() { + /** + * Route cancellation: + * On routing error, go to the dashboard. + * Provide an exit clause if it tries to do it twice. + */ + $rootScope.$on('$routeChangeError', + function(event, current, previous, rejection) { + var destination = (current && (current.title || current.name || current.loadedTemplateUrl)) || + 'unknown target'; + var msg = 'Error routing to ' + destination + '. ' + (rejection.msg || ''); + /** + * Optionally log using a custom service or $log. + * (Don't forget to inject custom service) + */ + logger.warning(msg, [current]); + } + ); + } + ``` + +**[Back to top](#table-of-contents)** + +## Naming + +### Naming Guidelines +###### [Style [Y120](#style-y120)] + + - Use consistent names for all components following a pattern that describes the component's feature then (optionally) its type. My recommended pattern is `feature.type.js`. There are 2 names for most assets: + * the file name (`avengers.controller.js`) + * the registered component name with Angular (`AvengersController`) + + *Why?*: Naming conventions help provide a consistent way to find content at a glance. Consistency within the project is vital. Consistency with a team is important. Consistency across a company provides tremendous efficiency. + + *Why?*: The naming conventions should simply help you find your code faster and make it easier to understand. + +### Feature File Names +###### [Style [Y121](#style-y121)] + + - Use consistent names for all components following a pattern that describes the component's feature then (optionally) its type. My recommended pattern is `feature.type.js`. + + *Why?*: Provides a consistent way to quickly identify components. + + *Why?*: Provides pattern matching for any automated tasks. + + ```javascript + /** + * common options + */ + + // Controllers + avengers.js + avengers.controller.js + avengersController.js + + // Services/Factories + logger.js + logger.service.js + loggerService.js + ``` + + ```javascript + /** + * recommended + */ + + // controllers + avengers.controller.js + avengers.controller.spec.js + + // services/factories + logger.service.js + logger.service.spec.js + + // constants + constants.js + + // module definition + avengers.module.js + + // routes + avengers.routes.js + avengers.routes.spec.js + + // configuration + avengers.config.js + + // directives + avenger-profile.directive.js + avenger-profile.directive.spec.js + ``` + + Note: Another common convention is naming controller files without the word `controller` in the file name such as `avengers.js` instead of `avengers.controller.js`. All other conventions still hold using a suffix of the type. Controllers are the most common type of component so this just saves typing and is still easily identifiable. I recommend you choose 1 convention and be consistent for your team. + + ```javascript + /** + * recommended + */ + // Controllers + avengers.js + avengers.spec.js + ``` + +### Test File Names +###### [Style [Y122](#style-y122)] + + - Name test specifications similar to the component they test with a suffix of `spec`. + + *Why?*: Provides a consistent way to quickly identify components. + + *Why?*: Provides pattern matching for [karma](http://karma-runner.github.io/) or other test runners. + + ```javascript + /** + * recommended + */ + avengers.controller.spec.js + logger.service.spec.js + avengers.routes.spec.js + avenger-profile.directive.spec.js + ``` + +### Controller Names +###### [Style [Y123](#style-y123)] + + - Use consistent names for all controllers named after their feature. Use UpperCamelCase for controllers, as they are constructors. + + *Why?*: Provides a consistent way to quickly identify and reference controllers. + + *Why?*: UpperCamelCase is conventional for identifying object that can be instantiated using a constructor. + + ```javascript + /** + * recommended + */ + + // avengers.controller.js + angular + .module + .controller('HeroAvengers', HeroAvengers); + + function HeroAvengers(){ } + ``` + +### Controller Name Suffix +###### [Style [Y124](#style-y124)] + + - Append the controller name with the suffix `Controller` or with no suffix. Choose 1, not both. + + *Why?*: The `Controller` suffix is more commonly used and is more explicitly descriptive. + + *Why?*: Omitting the suffix is more succinct and the controller is often easily identifiable even without the suffix. + + ```javascript + /** + * recommended: Option 1 + */ + + // avengers.controller.js + angular + .module + .controller('Avengers', Avengers); + + function Avengers(){ } + ``` + + ```javascript + /** + * recommended: Option 2 + */ + + // avengers.controller.js + angular + .module + .controller('AvengersController', AvengersController); + + function AvengersController(){ } + ``` + +### Factory Names +###### [Style [Y125](#style-y125)] + + - Use consistent names for all factories named after their feature. Use camel-casing for services and factories. + + *Why?*: Provides a consistent way to quickly identify and reference factories. + + ```javascript + /** + * recommended + */ + + // logger.service.js + angular + .module + .factory('logger', logger); + + function logger(){ } + ``` + +### Directive Component Names +###### [Style [Y126](#style-y126)] + + - Use consistent names for all directives using camel-case. Use a short prefix to describe the area that the directives belong (some example are company prefix or project prefix). + + *Why?*: Provides a consistent way to quickly identify and reference components. + + ```javascript + /** + * recommended + */ + + // avenger-profile.directive.js + angular + .module + .directive('xxAvengerProfile', xxAvengerProfile); + + // usage is + + function xxAvengerProfile(){ } + ``` + +### Modules +###### [Style [Y127](#style-y127)] + + - When there are multiple modules, the main module file is named `app.module.js` while other dependent modules are named after what they represent. For example, an admin module is named `admin.module.js`. The respective registered module names would be `app` and `admin`. + + *Why?*: Provides consistency for multiple module apps, and for expanding to large applications. + + *Why?*: Provides easy way to use task automation to load all module definitions first, then all other angular files (for bundling). + +### Configuration +###### [Style [Y128](#style-y128)] + + - Separate configuration for a module into its own file named after the module. A configuration file for the main `app` module is named `app.config.js` (or simply `config.js`). A configuration for a module named `admin.module.js` is named `admin.config.js`. + + *Why?*: Separates configuration from module definition, components, and active code. + + *Why?*: Provides a identifiable place to set configuration for a module. + +### Routes +###### [Style [Y129](#style-y129)] + + - Separate route configuration into its own file. Examples might be `app.route.js` for the main module and `admin.route.js` for the `admin` module. Even in smaller apps I prefer this separation from the rest of the configuration. + +**[Back to top](#table-of-contents)** + +## Application Structure LIFT Principle +### LIFT +###### [Style [Y140](#style-y140)] + + - Structure your app such that you can `L`ocate your code quickly, `I`dentify the code at a glance, keep the `F`lattest structure you can, and `T`ry to stay DRY. The structure should follow these 4 basic guidelines. + + *Why LIFT?*: Provides a consistent structure that scales well, is modular, and makes it easier to increase developer efficiency by finding code quickly. Another way to check your app structure is to ask yourself: How quickly can you open and work in all of the related files for a feature? + + When I find my structure is not feeling comfortable, I go back and revisit these LIFT guidelines + + 1. `L`ocating our code is easy + 2. `I`dentify code at a glance + 3. `F`lat structure as long as we can + 4. `T`ry to stay DRY (Don’t Repeat Yourself) or T-DRY + +### Locate +###### [Style [Y141](#style-y141)] + + - Make locating your code intuitive, simple and fast. + + *Why?*: I find this to be super important for a project. If the team cannot find the files they need to work on quickly, they will not be able to work as efficiently as possible, and the structure needs to change. You may not know the file name or where its related files are, so putting them in the most intuitive locations and near each other saves a ton of time. A descriptive folder structure can help with this. + + ``` + /bower_components + /client + /app + /avengers + /blocks + /exception + /logger + /core + /dashboard + /data + /layout + /widgets + /content + index.html + .bower.json + ``` + +### Identify +###### [Style [Y142](#style-y142)] + + - When you look at a file you should instantly know what it contains and represents. + + *Why?*: You spend less time hunting and pecking for code, and become more efficient. If this means you want longer file names, then so be it. Be descriptive with file names and keeping the contents of the file to exactly 1 component. Avoid files with multiple controllers, multiple services, or a mixture. There are deviations of the 1 per file rule when I have a set of very small features that are all related to each other, they are still easily identifiable. + +### Flat +###### [Style [Y143](#style-y143)] + + - Keep a flat folder structure as long as possible. When you get to 7+ files, begin considering separation. + + *Why?*: Nobody wants to search 7 levels of folders to find a file. Think about menus on web sites … anything deeper than 2 should take serious consideration. In a folder structure there is no hard and fast number rule, but when a folder has 7-10 files, that may be time to create subfolders. Base it on your comfort level. Use a flatter structure until there is an obvious value (to help the rest of LIFT) in creating a new folder. + +### T-DRY (Try to Stick to DRY) +###### [Style [Y144](#style-y144)] + + - Be DRY, but don't go nuts and sacrifice readability. + + *Why?*: Being DRY is important, but not crucial if it sacrifices the others in LIFT, which is why I call it T-DRY. I don’t want to type session-view.html for a view because, well, it’s obviously a view. If it is not obvious or by convention, then I name it. + +**[Back to top](#table-of-contents)** + +## Application Structure + +### Overall Guidelines +###### [Style [Y150](#style-y150)] + + - Have a near term view of implementation and a long term vision. In other words, start small and but keep in mind on where the app is heading down the road. All of the app's code goes in a root folder named `app`. All content is 1 feature per file. Each controller, service, module, view is in its own file. All 3rd party vendor scripts are stored in another root folder and not in the `app` folder. I didn't write them and I don't want them cluttering my app (`bower_components`, `scripts`, `lib`). + + Note: Find more details and reasoning behind the structure at [this original post on application structure](http://www.johnpapa.net/angular-app-structuring-guidelines/). + +### Layout +###### [Style [Y151](#style-y151)] + + - Place components that define the overall layout of the application in a folder named `layout`. These may include a shell view and controller may act as the container for the app, navigation, menus, content areas, and other regions. + + *Why?*: Organizes all layout in a single place re-used throughout the application. + +### Folders-by-Feature Structure +###### [Style [Y152](#style-y152)] + + - Create folders named for the feature they represent. When a folder grows to contain more than 7 files, start to consider creating a folder for them. Your threshold may be different, so adjust as needed. + + *Why?*: A developer can locate the code, identify what each file represents at a glance, the structure is flat as can be, and there is no repetitive nor redundant names. + + *Why?*: The LIFT guidelines are all covered. + + *Why?*: Helps reduce the app from becoming cluttered through organizing the content and keeping them aligned with the LIFT guidelines. + + *Why?*: When there are a lot of files (10+) locating them is easier with a consistent folder structures and more difficult in flat structures. + + ```javascript + /** + * recommended + */ + + app/ + app.module.js + app.config.js + app.routes.js + components/ + calendar.directive.js + calendar.directive.html + user-profile.directive.js + user-profile.directive.html + layout/ + shell.html + shell.controller.js + topnav.html + topnav.controller.js + people/ + attendees.html + attendees.controller.js + speakers.html + speakers.controller.js + speaker-detail.html + speaker-detail.controller.js + services/ + data.service.js + localstorage.service.js + logger.service.js + spinner.service.js + sessions/ + sessions.html + sessions.controller.js + session-detail.html + session-detail.controller.js + ``` + + ![Sample App Structure](https://raw.githubusercontent.com/johnpapa/angularjs-styleguide/master/assets/modularity-2.png) + + Note: Do not use structuring using folders-by-type. This requires moving to multiple folders when working on a feature and gets unwieldy quickly as the app grows to 5, 10 or 25+ views and controllers (and other features), which makes it more difficult than folder-by-feature to locate files. + + ```javascript + /* + * avoid + * Alternative folders-by-type. + * I recommend "folders-by-feature", instead. + */ + + app/ + app.module.js + app.config.js + app.routes.js + controllers/ + attendees.js + session-detail.js + sessions.js + shell.js + speakers.js + speaker-detail.js + topnav.js + directives/ + calendar.directive.js + calendar.directive.html + user-profile.directive.js + user-profile.directive.html + services/ + dataservice.js + localstorage.js + logger.js + spinner.js + views/ + attendees.html + session-detail.html + sessions.html + shell.html + speakers.html + speaker-detail.html + topnav.html + ``` + +**[Back to top](#table-of-contents)** + +## Modularity + +### Many Small, Self Contained Modules +###### [Style [Y160](#style-y160)] + + - Create small modules that encapsulate one responsibility. + + *Why?*: Modular applications make it easy to plug and go as they allow the development teams to build vertical slices of the applications and roll out incrementally. This means we can plug in new features as we develop them. + +### Create an App Module +###### [Style [Y161](#style-y161)] + + - Create an application root module whose role is pull together all of the modules and features of your application. Name this for your application. + + *Why?*: AngularJS encourages modularity and separation patterns. Creating an application root module whose role is to tie your other modules together provides a very straightforward way to add or remove modules from your application. + +### Keep the App Module Thin +###### [Style [Y162](#style-y162)] + + - Only put logic for pulling together the app in the application module. Leave features in their own modules. + + *Why?*: Adding additional roles to the application root to get remote data, display views, or other logic not related to pulling the app together muddies the app module and make both sets of features harder to reuse or turn off. + + *Why?*: The app module becomes a manifest that describes which modules help define the application. + +### Feature Areas are Modules +###### [Style [Y163](#style-y163)] + + - Create modules that represent feature areas, such as layout, reusable and shared services, dashboards, and app specific features (e.g. customers, admin, sales). + + *Why?*: Self contained modules can be added to the application with little or no friction. + + *Why?*: Sprints or iterations can focus on feature areas and turn them on at the end of the sprint or iteration. + + *Why?*: Separating feature areas into modules makes it easier to test the modules in isolation and reuse code. + +### Reusable Blocks are Modules +###### [Style [Y164](#style-y164)] + + - Create modules that represent reusable application blocks for common services such as exception handling, logging, diagnostics, security, and local data stashing. + + *Why?*: These types of features are needed in many applications, so by keeping them separated in their own modules they can be application generic and be reused across applications. + +### Module Dependencies +###### [Style [Y165](#style-y165)] + + - The application root module depends on the app specific feature modules and any shared or reusable modules. + + ![Modularity and Dependencies](https://raw.githubusercontent.com/johnpapa/angularjs-styleguide/master/assets/modularity-1.png) + + *Why?*: The main app module contains a quickly identifiable manifest of the application's features. + + *Why?*: Each feature area contains a manifest of what it depends on, so it can be pulled in as a dependency in other applications and still work. + + *Why?*: Intra-App features such as shared data services become easy to locate and share from within `app.core` (choose your favorite name for this module). + + Note: This is a strategy for consistency. There are many good options here. Choose one that is consistent, follows AngularJS's dependency rules, and is easy to maintain and scale. + + > My structures vary slightly between projects but they all follow these guidelines for structure and modularity. The implementation may vary depending on the features and the team. In other words, don't get hung up on an exact like-for-like structure but do justify your structure using consistency, maintainability, and efficiency in mind. + + > In a small app, you can also consider putting all the shared dependencies in the app module where the feature modules have no direct dependencies. This makes it easier to maintain the smaller application, but makes it harder to reuse modules outside of this application. + +**[Back to top](#table-of-contents)** + +## Startup Logic + +### Configuration +###### [Style [Y170](#style-y170)] + + - Inject code into [module configuration](https://docs.angularjs.org/guide/module#module-loading-dependencies) that must be configured before running the angular app. Ideal candidaes include providers and constants. + + *Why?*: This makes it easier to have a less places for configuration. + + ```javascript + angular + .module('app') + .config(configure); + + configure.$inject = + ['routerHelperProvider', 'exceptionHandlerProvider', 'toastr']; + + function configure (routerHelperProvider, exceptionHandlerProvider, toastr) { + exceptionHandlerProvider.configure(config.appErrorPrefix); + configureStateHelper(); + + toastr.options.timeOut = 4000; + toastr.options.positionClass = 'toast-bottom-right'; + + //////////////// + + function configureStateHelper() { + routerHelperProvider.configure({ + docTitle: 'NG-Modular: ' + }); + } + } + ``` + +### Run Blocks +###### [Style [Y171](#style-y171)] + + - Any code that needs to run when an application starts should be declared in a factory, exposed via a function, and injected into the [run block](https://docs.angularjs.org/guide/module#module-loading-dependencies). + + *Why?*: Code directly in a run block can be difficult to test. Placing in a factory makes it easier to abstract and mock. + + ```javascript + angular + .module('app') + .run(runBlock); + + runBlock.$inject = ['authenticator', 'translator']; + + function runBlock(authenticator, translator) { + authenticator.initialize(); + translator.initialize(); + } + ``` + +**[Back to top](#table-of-contents)** + +## Angular $ Wrapper Services + +### $document and $window +###### [Style [Y180](#style-y180)] + + - Use [`$document`](https://docs.angularjs.org/api/ng/service/$document) and [`$window`](https://docs.angularjs.org/api/ng/service/$window) instead of `document` and `window`. + + *Why?*: These services are wrapped by Angular and more easily testable than using document and window in tests. This helps you avoid having to mock document and window yourself. + +### $timeout and $interval +###### [Style [Y181](#style-y181)] + + - Use [`$timeout`](https://docs.angularjs.org/api/ng/service/$timeout) and [`$interval`](https://docs.angularjs.org/api/ng/service/$interval) instead of `setTimeout` and `setInterval` . + + *Why?*: These services are wrapped by Angular and more easily testable and handle AngularJS's digest cycle thus keeping data binding in sync. + +**[Back to top](#table-of-contents)** + +## Testing +Unit testing helps maintain clean code, as such I included some of my recommendations for unit testing foundations with links for more information. + +### Write Tests with Stories +###### [Style [Y190](#style-y190)] + + - Write a set of tests for every story. Start with an empty test and fill them in as you write the code for the story. + + *Why?*: Writing the test descriptions helps clearly define what your story will do, will not do, and how you can measure success. + + ```javascript + it('should have Avengers controller', function() { + //TODO + }); + + it('should find 1 Avenger when filtered by name', function() { + //TODO + }); + + it('should have 10 Avengers', function() { + //TODO (mock data?) + }); + + it('should return Avengers via XHR', function() { + //TODO ($httpBackend?) + }); + + // and so on + ``` + +### Testing Library +###### [Style [Y191](#style-y191)] + + - Use [Jasmine](http://jasmine.github.io/) or [Mocha](http://visionmedia.github.io/mocha/) for unit testing. + + *Why?*: Both Jasmine and Mocha are widely used in the AngularJS community. Both are stable, well maintained, and provide robust testing features. + + Note: When using Mocha, also consider choosing an assert library such as [Chai](http://chaijs.com). + +### Test Runner +###### [Style [Y192](#style-y192)] + + - Use [Karma](http://karma-runner.github.io) as a test runner. + + *Why?*: Karma is easy to configure to run once or automatically when you change your code. + + *Why?*: Karma hooks into your Continuous Integration process easily on its own or through Grunt or Gulp. + + *Why?*: Some IDE's are beginning to integrate with Karma, such as [WebStorm](http://www.jetbrains.com/webstorm/) and [Visual Studio](http://visualstudiogallery.msdn.microsoft.com/02f47876-0e7a-4f6c-93f8-1af5d5189225). + + *Why?*: Karma works well with task automation leaders such as [Grunt](http://www.gruntjs.com) (with [grunt-karma](https://github.com/karma-runner/grunt-karma)) and [Gulp](http://www.gulpjs.com) (with [gulp-karma](https://github.com/lazd/gulp-karma)). + +### Stubbing and Spying +###### [Style [Y193](#style-y193)] + + - Use Sinon for stubbing and spying. + + *Why?*: Sinon works well with both Jasmine and Mocha and extends the stubbing and spying features they offer. + + *Why?*: Sinon makes it easier to toggle between Jasmine and Mocha, if you want to try both. + +### Headless Browser +###### [Style [Y194](#style-y194)] + + - Use [PhantomJS](http://phantomjs.org/) to run your tests on a server. + + *Why?*: PhantomJS is a headless browser that helps run your tests without needing a "visual" browser. So you do not have to install Chrome, Safari, IE, or other browsers on your server. + + Note: You should still test on all browsers in your environment, as appropriate for your target audience. + +### Code Analysis +###### [Style [Y195](#style-y195)] + + - Run JSHint on your tests. + + *Why?*: Tests are code. JSHint can help identify code quality issues that may cause the test to work improperly. + +### Alleviate Globals for JSHint Rules on Tests +###### [Style [Y196](#style-y196)] + + - Relax the rules on your test code to allow for common globals such as `describe` and `expect`. + + *Why?*: Your tests are code and require the same attention and code quality rules as all of your production code. However, global variables used by the testing framework, for example, can be relaxed by including this in your test specs. + + ```javascript + /* global sinon, describe, it, afterEach, beforeEach, expect, inject */ + ``` + + ![Testing Tools](https://raw.githubusercontent.com/johnpapa/angularjs-styleguide/master/assets/testing-tools.png) + +**[Back to top](#table-of-contents)** + +## Animations + +### Usage +###### [Style [Y210](#style-y210)] + + - Use subtle [animations with AngularJS](https://docs.angularjs.org/guide/animations) to transition between states for views and primary visual elements. Include the [ngAnimate module](https://docs.angularjs.org/api/ngAnimate). The 3 keys are subtle, smooth, seamless. + + *Why?*: Subtle animations can improve User Experience when used appropriately. + + *Why?*: Subtle animations can improve perceived performance as views transition. + +### Sub Second +###### [Style [Y211](#style-y211)] + + - Use short durations for animations. I generally start with 300ms and adjust until appropriate. + + *Why?*: Long animations can have the reverse affect on User Experience and perceived performance by giving the appearance of a slow application. + +### animate.css +###### [Style [Y212](#style-y212)] + + - Use [animate.css](http://daneden.github.io/animate.css/) for conventional animations. + + *Why?*: The animations that animate.css provides are fast, smooth, and easy to add to your application. + + *Why?*: Provides consistency in your animations. + + *Why?*: animate.css is widely used and tested. + + Note: See this [great post by Matias Niemelä on AngularJS animations](http://www.yearofmoo.com/2013/08/remastered-animation-in-angularjs-1-2.html) + +**[Back to top](#table-of-contents)** + +## Comments + +### jsDoc +###### [Style [Y220](#style-y220)] + + - If planning to produce documentation, use [`jsDoc`](http://usejsdoc.org/) syntax to document function names, description, params and returns. Use `@namespace` and `@memberOf` to match your app structure. + + *Why?*: You can generate (and regenerate) documentation from your code, instead of writing it from scratch. + + *Why?*: Provides consistency using a common industry tool. + + ```javascript + /** + * Logger Factory + * @namespace Factories + */ + (function() { + angular + .module('app') + .factory('logger', logger); + + /** + * @namespace Logger + * @desc Application wide logger + * @memberOf Factories + */ + function logger($log) { + var service = { + logError: logError + }; + return service; + + //////////// + + /** + * @name logError + * @desc Logs errors + * @param {String} msg Message to log + * @returns {String} + * @memberOf Factories.Logger + */ + function logError(msg) { + var loggedMsg = 'Error: ' + msg; + $log.error(loggedMsg); + return loggedMsg; + }; + } + })(); + ``` + +**[Back to top](#table-of-contents)** + +## JS Hint + +### Use an Options File +###### [Style [Y230](#style-y230)] + + - Use JS Hint for linting your JavaScript and be sure to customize the JS Hint options file and include in source control. See the [JS Hint docs](http://www.jshint.com/docs/) for details on the options. + + *Why?*: Provides a first alert prior to committing any code to source control. + + *Why?*: Provides consistency across your team. + + ```javascript + { + "bitwise": true, + "camelcase": true, + "curly": true, + "eqeqeq": true, + "es3": false, + "forin": true, + "freeze": true, + "immed": true, + "indent": 4, + "latedef": "nofunc", + "newcap": true, + "noarg": true, + "noempty": true, + "nonbsp": true, + "nonew": true, + "plusplus": false, + "quotmark": "single", + "undef": true, + "unused": false, + "strict": false, + "maxparams": 10, + "maxdepth": 5, + "maxstatements": 40, + "maxcomplexity": 8, + "maxlen": 120, + + "asi": false, + "boss": false, + "debug": false, + "eqnull": true, + "esnext": false, + "evil": false, + "expr": false, + "funcscope": false, + "globalstrict": false, + "iterator": false, + "lastsemic": false, + "laxbreak": false, + "laxcomma": false, + "loopfunc": true, + "maxerr": false, + "moz": false, + "multistr": false, + "notypeof": false, + "proto": false, + "scripturl": false, + "shadow": false, + "sub": true, + "supernew": false, + "validthis": false, + "noyield": false, + + "browser": true, + "node": true, + + "globals": { + "angular": false, + "$": false + } + } + ``` + +**[Back to top](#table-of-contents)** + +## Constants + +### Vendor Globals +###### [Style [Y240](#style-y240)] + + - Create an AngularJS Constant for vendor libraries' global variables. + + *Why?*: Provides a way to inject vendor libraries that otherwise are globals. This improves code testability by allowing you to more easily know what the dependencies of your components are (avoids leaky abstractions). It also allows you to mock these dependencies, where it makes sense. + + ```javascript + // constants.js + + /* global toastr:false, moment:false */ + (function() { + 'use strict'; + + angular + .module('app.core') + .constant('toastr', toastr) + .constant('moment', moment); + })(); + ``` + +**[Back to top](#table-of-contents)** + +## File Templates and Snippets +Use file templates or snippets to help follow consistent styles and patterns. Here are templates and/or snippets for some of the web development editors and IDEs. + +### Sublime Text +###### [Style [Y250](#style-y250)] + + - AngularJS snippets that follow these styles and guidelines. + + - Download the [Sublime Angular snippets](assets/sublime-angular-snippets.zip?raw=true) + - Place it in your Packages folder + - Restart Sublime + - In a JavaScript file type these commands followed by a `TAB` + + ```javascript + ngcontroller // creates an Angular controller + ngdirective // creates an Angular directive + ngfactory // creates an Angular factory + ngmodule // creates an Angular module + ``` + +### Visual Studio +###### [Style [Y251](#style-y251)] + + - AngularJS file templates that follow these styles and guidelines can be found at [SideWaffle](http://www.sidewaffle.com) + + - Download the [SideWaffle](http://www.sidewaffle.com) Visual Studio extension (vsix file) + - Run the vsix file + - Restart Visual Studio + +### WebStorm +###### [Style [Y252](#style-y252)] + + - AngularJS snippets and file templates that follow these styles and guidelines. You can import them into your WebStorm settings: + + - Download the [WebStorm AngularJS file templates and snippets](assets/webstorm-angular-file-template.settings.jar?raw=true) + - Open WebStorm and go to the `File` menu + - Choose the `Import Settings` menu option + - Select the file and click `OK` + - In a JavaScript file type these commands followed by a `TAB`: + + ```javascript + ng-c // creates an Angular controller + ng-f // creates an Angular factory + ng-m // creates an Angular module + ``` + +**[Back to top](#table-of-contents)** + +## AngularJS docs +For anything else, API reference, check the [Angular documentation](//docs.angularjs.org/api). + +## Contributing + +Open an issue first to discuss potential changes/additions. If you have questions with the guide, feel free to leave them as issues in the repository. If you find a typo, create a pull request. The idea is to keep the content up to date and use github’s native feature to help tell the story with issues and PR’s, which are all searchable via google. Why? Because odds are if you have a question, someone else does too! You can learn more here at about how to contribute. + +*By contributing to this repository you are agreeing to make your content available subject to the license of this repository.* + +### Process + 1. Discuss the changes in an Issue. + 2. Open a Pull Request, reference the issue, and explain the change and why it adds value. + 3. The Pull Request will be evaluated and either merged or declined. + +## License + +_tldr; Use this guide. Attributions are appreciated._ + +### (The MIT License) + +Copyright (c) 2014 [John Papa](http://johnpapa.net) + +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. + +**[Back to top](#table-of-contents)** From 19978c141182aad6b27131e85503e85fc3f9af39 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89ric=20Le=20Merdy?= Date: Fri, 19 Dec 2014 03:38:15 +0100 Subject: [PATCH 147/567] [FR] IIFE --- i18n/fr-FR.md | 31 ++++++++++++++++++++----------- 1 file changed, 20 insertions(+), 11 deletions(-) diff --git a/i18n/fr-FR.md b/i18n/fr-FR.md index 4269cae8..cb782a59 100644 --- a/i18n/fr-FR.md +++ b/i18n/fr-FR.md @@ -118,20 +118,25 @@ sont maintenues par la communauté et peuvent être trouvées ici. ### Les Closures JavaScript ###### [Style [Y010](#style-y010)] - - Wrap AngularJS components in an Immediately Invoked Function Expression (IIFE). + - Encapsuler les composants AngularJS dans une Immediately Invoked Function Expression (IIFE) ou Expression de + Fonction Immédiatement Invoquée. - *Why?*: An IIFE removes variables from the global scope. This helps prevent variables and function declarations from living longer than expected in the global scope, which also helps avoid variable collisions. + *Pourquoi ?* : Une IIFE supprime les variables du scope global. Cela aide à éviter que les déclarations de variables + et de fonctions ne vivent plus longtemps qu'attendu dans le scope global, ce qui aide aussi à éviter les collisions de + variables. - *Why?*: When your code is minified and bundled into a single file for deployment to a production server, you could have collisions of variables and many global variables. An IIFE protects you against both of these by providing variable scope for each file. + *Pourquoi ?* : Lorsque votre code est minifié et embarqué dans un unique fichier pour le déploiement dans un serveur + de production, vous pouvez avoir des collisions de variables et de nombreuses variables globales. Une IIFE protège + contre ces derniers en fournissant un scope de variable pour chaque fichier. ```javascript - /* avoid */ + /* éviter */ // logger.js angular .module('app') .factory('logger', logger); - // logger function is added as a global variable + // la fonction de logger est ajoutée en tant que variable globale function logger() { } // storage.js @@ -139,16 +144,16 @@ sont maintenues par la communauté et peuvent être trouvées ici. .module('app') .factory('storage', storage); - // storage function is added as a global variable + // la fonction storage est ajoutée en tant que variable globale function storage() { } ``` ```javascript /** - * recommended + * recommandé * - * no globals are left behind + * plus aucune variable globale ne reste après. */ // logger.js @@ -174,11 +179,15 @@ sont maintenues par la communauté et peuvent être trouvées ici. })(); ``` - - Note: For brevity only, the rest of the examples in this guide may omit the IIFE syntax. + - Note : Pour des raisons de concision seulement, le reste des examples de ce guide peuvent avoir omis la syntaxe + IIFE. - - Note: IIFE's prevent test code from reaching private members like regular expressions or helper functions which are often good to unit test directly on their own. However you can test these through accessible members or by exposing them through their own component. For example placing helper functions, regular expressions or constants in their own factory or constant. + - Note : Les IIFE empêchent le code code de test d'atteindre des membres privés comme des expressions régulières ou + des fonctions helper ce qui est bon pour tester unitairement directement indépendamment. Cependant, vous pouvez les + tester à travers des membres accessibles ou en les exposant à travers leur propre composant. Par exemple en plaçant + des fonctions helper, des expressions régulières ou des constantes dans leur propre factory ou contante. -**[Back to top](#table-of-contents)** +**[Retour en haut de page](#table-des-matières)** ## Modules From e2a2d3432ec05e5d84ad3eb702321b254f83e843 Mon Sep 17 00:00:00 2001 From: Eric Date: Fri, 19 Dec 2014 04:25:55 +0100 Subject: [PATCH 148/567] [FR] Module --- i18n/fr-FR.md | 91 ++++++++++++++++++++------------------------------- 1 file changed, 36 insertions(+), 55 deletions(-) diff --git a/i18n/fr-FR.md b/i18n/fr-FR.md index cb782a59..beddefcc 100644 --- a/i18n/fr-FR.md +++ b/i18n/fr-FR.md @@ -2,15 +2,11 @@ *Le guide d'un certain point de vue stylistique sur AngularJS par [@john_papa](//twitter.com/john_papa)* -Si vous cherchez un guide d'un certain point de vue stylistique pour la syntaxe, les conventions, et la structuration -d'application AngularJS, alors vous êtes au bon endroit. Ces styles sont basés sur mon expérience de dévelopement avec -[AngularJS](//angularjs.org), mes présentations, [mes cours sur Pluralsight](http://pluralsight.com/training/Authors/Details/john-papa) -et mon travail au sein des équipes. +Si vous cherchez un guide d'un certain point de vue stylistique pour la syntaxe, les conventions, et la structuration d'application AngularJS, alors vous êtes au bon endroit. Ces styles sont basés sur mon expérience de dévelopement avec [AngularJS](//angularjs.org), mes présentations, [mes cours sur Pluralsight](http://pluralsight.com/training/Authors/Details/john-papa) et mon travail au sein des équipes. >Si vous appréciez ce guide, visitez mon cours [AngularJS Patterns: Clean Code](http://jpapa.me/ngclean) sur Pluralsight. -Le but de ce guide stylistique est de proposer des conseils sur le développement d'applications AngularJS en montrant -les conventions que j'utilise et, plus important encore, les raisons des choix que j'ai pris. +Le but de ce guide stylistique est de proposer des conseils sur le développement d'applications AngularJS en montrant les conventions que j'utilise et, plus important encore, les raisons des choix que j'ai pris. ## Supprématie de la Communauté et Remerciements Ne jamais travailler dans le vide. J'ai trouvé que la communauté AngularJS est un incroyable groupe dont les membres ont à coeur de partager leurs expériences. Ainsi, un ami et expert AngularJS Todd Motto et moi avons collaboré sur de nombreux styles et conventions. Nous sommes d'accord sur la plupart, et nous divergeons sur d'autres. Je vous encourage à visiter [les guideslines de Todd](https://github.com/toddmotto/angularjs-styleguide) pour vous faire un sentiment sur son approche et en quoi elle est comparable. @@ -18,15 +14,10 @@ Ne jamais travailler dans le vide. J'ai trouvé que la communauté AngularJS est De nombreux de mes styles proviennent des maintes scéances de pair programming que [Ward Bell](http://twitter.com/wardbell) et moi avons eu. Même si nous n'étions pas toujours d'accord, mon ami Ward a assurément contribué à influencer l'évolution ultime de ce guide. ## Visualiser les Styles dans une Application d'Exemple -Alors que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'a été utile de les visualiser dans la -pratique. Ce guide est accompagné par une application d'exemple qui suit ces styles et ces motifs. Vous pouvez trouver -l'[application d'exemple (appellée modular) ici](https://github.com/johnpapa/ng-demos) dans le répertoire `modular`. -Vous pouvez librement le récupérer, le cloner, ou le dupliquer pour le modifier. [Les instructions pour l'éxécuter sont -contenues dans ce readme](https://github.com/johnpapa/ng-demos/tree/master/modular). +Alors que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'a été utile de les visualiser dans la pratique. Ce guide est accompagné par une application d'exemple qui suit ces styles et ces motifs. Vous pouvez trouver l'[application d'exemple (appellée modular) ici](https://github.com/johnpapa/ng-demos) dans le répertoire `modular`. Vous pouvez librement le récupérer, le cloner, ou le dupliquer pour le modifier. [Les instructions pour l'éxécuter sont contenues dans ce readme](https://github.com/johnpapa/ng-demos/tree/master/modular). ## Traductions -[Des traductions de ce guide stylistique Angular](https://github.com/johnpapa/angularjs-styleguide/tree/master/i18n) -sont maintenues par la communauté et peuvent être trouvées ici. +[Des traductions de ce guide stylistique Angular](https://github.com/johnpapa/angularjs-styleguide/tree/master/i18n) sont maintenues par la communauté et peuvent être trouvées ici. ## Table des matières @@ -65,11 +56,10 @@ sont maintenues par la communauté et peuvent être trouvées ici. - Définir 1 composant par fichier. - L'exemple suivant définit le module `app` et ses dépendances, définit un controlleur, et définit une factory le tout - dans le même fichier. + L'exemple suivant définit le module `app` et ses dépendances, définit un controlleur, et définit une factory le tout dans le même fichier. ```javascript - /* éviter */ + /* à éviter */ angular .module('app', ['ngRoute']) .controller('SomeController', SomeController) @@ -118,19 +108,14 @@ sont maintenues par la communauté et peuvent être trouvées ici. ### Les Closures JavaScript ###### [Style [Y010](#style-y010)] - - Encapsuler les composants AngularJS dans une Immediately Invoked Function Expression (IIFE) ou Expression de - Fonction Immédiatement Invoquée. + - Encapsuler les composants AngularJS dans une Immediately Invoked Function Expression (IIFE) ou Expression de Fonction Immédiatement Invoquée. - *Pourquoi ?* : Une IIFE supprime les variables du scope global. Cela aide à éviter que les déclarations de variables - et de fonctions ne vivent plus longtemps qu'attendu dans le scope global, ce qui aide aussi à éviter les collisions de - variables. + *Pourquoi ?* : Une IIFE supprime les variables du scope global. Cela aide à éviter que les déclarations de variables et de fonctions ne vivent plus longtemps qu'attendu dans le scope global, ce qui aide aussi à éviter les collisions de variables. - *Pourquoi ?* : Lorsque votre code est minifié et embarqué dans un unique fichier pour le déploiement dans un serveur - de production, vous pouvez avoir des collisions de variables et de nombreuses variables globales. Une IIFE protège - contre ces derniers en fournissant un scope de variable pour chaque fichier. + *Pourquoi ?* : Lorsque votre code est minifié et embarqué dans un unique fichier pour le déploiement dans un serveur de production, vous pouvez avoir des collisions de variables et de nombreuses variables globales. Une IIFE protège contre ces derniers en fournissant un scope de variable pour chaque fichier. ```javascript - /* éviter */ + /* à éviter */ // logger.js angular .module('app') @@ -179,34 +164,30 @@ sont maintenues par la communauté et peuvent être trouvées ici. })(); ``` - - Note : Pour des raisons de concision seulement, le reste des examples de ce guide peuvent avoir omis la syntaxe - IIFE. + - Note : Pour des raisons de concision seulement, le reste des examples de ce guide peuvent avoir omis la syntaxe IIFE. - - Note : Les IIFE empêchent le code code de test d'atteindre des membres privés comme des expressions régulières ou - des fonctions helper ce qui est bon pour tester unitairement directement indépendamment. Cependant, vous pouvez les - tester à travers des membres accessibles ou en les exposant à travers leur propre composant. Par exemple en plaçant - des fonctions helper, des expressions régulières ou des constantes dans leur propre factory ou contante. + - Note : Les IIFE empêchent le code code de test d'atteindre des membres privés comme des expressions régulières ou des fonctions helper ce qui est bon pour tester unitairement directement indépendamment. Cependant, vous pouvez les tester à travers des membres accessibles ou en les exposant à travers leur propre composant. Par exemple en plaçant des fonctions helper, des expressions régulières ou des constantes dans leur propre factory ou contante. **[Retour en haut de page](#table-des-matières)** ## Modules -### Avoid Naming Collisions +### Éviter les Collisions de Nommage ###### [Style [Y020](#style-y020)] - - Use unique naming conventions with separators for sub-modules. + - Utilisez des conventions de nommages uniques avec des séparations pour les sous-modules. - *Why?*: Unique names help avoid module name collisions. Separators help define modules and their submodule hierarchy. For example `app` may be your root module while `app.dashboard` and `app.users` may be modules that are used as dependencies of `app`. + *Pourquoi ?* : Les noms uniques aident à éviter les collisions de nom de module. Les séparateurs aident à définir les modules et leur hiérarchie de sous-modules. Par exemple, `app` pourrait être le module racine tandis que `app.dashboard` et `app.users` serait les modules qui sont utilisés en tant que dépendances de `app`. -### Definitions (aka Setters) +### Définitions (i.e. Setters) ###### [Style [Y021](#style-y021)] - - Declare modules without a variable using the setter syntax. + - Déclarer des modules sans variable en utilisant la syntaxe setter. - *Why?*: With 1 component per file, there is rarely a need to introduce a variable for the module. + *Pourquoi ?* : Avec 1 composant par fichier, on ne devrait pas avoir besoin d'introduire une variable pour le module. ```javascript - /* avoid */ + /* à éviter */ var app = angular.module('app', [ 'ngAnimate', 'ngRoute', @@ -215,10 +196,10 @@ sont maintenues par la communauté et peuvent être trouvées ici. ]); ``` - Instead use the simple setter syntax. + Utiliser à la place la syntaxe setter simple. ```javascript - /* recommended */ + /* recommandé */ angular .module('app', [ 'ngAnimate', @@ -231,12 +212,12 @@ sont maintenues par la communauté et peuvent être trouvées ici. ### Getters ###### [Style [Y022](#style-y022)] - - When using a module, avoid using a variable and instead use chaining with the getter syntax. + - Lorsque vous utilisez un module, évitez d'utiliser une variable en utilisant plutôt le chaînage avec la syntaxe du getter. - *Why?* : This produces more readable code and avoids variable collisions or leaks. + *Pourquoi ?* : Cela produit du code plus lisible et évite les collisions de variable ou les fuites. ```javascript - /* avoid */ + /* à éviter */ var app = angular.module('app'); app.controller('SomeController', SomeController); @@ -244,7 +225,7 @@ sont maintenues par la communauté et peuvent être trouvées ici. ``` ```javascript - /* recommended */ + /* recommandé */ angular .module('app') .controller('SomeController', SomeController); @@ -252,25 +233,25 @@ sont maintenues par la communauté et peuvent être trouvées ici. function SomeController() { } ``` -### Setting vs Getting +### Setting contre Getting ###### [Style [Y023](#style-y023)] - - Only set once and get for all other instances. + - Ne `settez` qu'une fois et `gettez` pour toutes les autres instances. - *Why?*: A module should only be created once, then retrieved from that point and after. + *Pourquoi ?* : Un module ne devrait être créé qu'une seule fois, et ensuite récupéré à partir de ce point et après. - - Use `angular.module('app', []);` to set a module. - - Use `angular.module('app');` to get a module. + - Utilisez `angular.module('app', []);` pour setter un module. + - Utilisez `angular.module('app');` pour getter un module. -### Named vs Anonymous Functions +### Fonctions Nommées contre Anonymes ###### [Style [Y024](#style-y024)] - - Use named functions instead of passing an anonymous function in as a callback. + - Utilisez des fonctions nommées au lieu de passer une fonction anonyme comme callback. - *Why?*: This produces more readable code, is much easier to debug, and reduces the amount of nested callback code. + *Pourquoi ?* : Celà produit du code plus lisible, est plus facile à débugguer, et réduit la quantité de code callback imbriqué. ```javascript - /* avoid */ + /* éviter */ angular .module('app') .controller('Dashboard', function() { }) @@ -278,7 +259,7 @@ sont maintenues par la communauté et peuvent être trouvées ici. ``` ```javascript - /* recommended */ + /* recommendé */ // dashboard.js angular @@ -297,7 +278,7 @@ sont maintenues par la communauté et peuvent être trouvées ici. function logger() { } ``` -**[Back to top](#table-of-contents)** +**[Retour en haut de page](#table-des-matières)** ## Controllers From 3053aac93acc28e25e03d1ce4cc4019349846d6a Mon Sep 17 00:00:00 2001 From: Eric Date: Sat, 20 Dec 2014 17:51:18 +0100 Subject: [PATCH 149/567] [FR] Controller --- i18n/fr-FR.md | 161 +++++++++++++++++++++++++------------------------- 1 file changed, 81 insertions(+), 80 deletions(-) diff --git a/i18n/fr-FR.md b/i18n/fr-FR.md index beddefcc..1644595e 100644 --- a/i18n/fr-FR.md +++ b/i18n/fr-FR.md @@ -24,7 +24,7 @@ Alors que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'a ét 1. [Responsabilité Unique](#responsabilité-unique) 1. [IIFE](#iife) 1. [Modules](#modules) - 1. [Controllers](#controllers) + 1. [Controlleurs](#controlleurs) 1. [Services](#services) 1. [Factories](#factories) 1. [Data Services](#data-services) @@ -133,7 +133,6 @@ Alors que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'a ét function storage() { } ``` - ```javascript /** * recommandé @@ -196,7 +195,7 @@ Alors que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'a ét ]); ``` - Utiliser à la place la syntaxe setter simple. + Utilisez à la place la syntaxe setter simple. ```javascript /* recommandé */ @@ -233,17 +232,17 @@ Alors que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'a ét function SomeController() { } ``` -### Setting contre Getting +### Setting ou Getting ###### [Style [Y023](#style-y023)] - - Ne `settez` qu'une fois et `gettez` pour toutes les autres instances. + - Ne settez qu'une fois et gettez pour toutes les autres instances. *Pourquoi ?* : Un module ne devrait être créé qu'une seule fois, et ensuite récupéré à partir de ce point et après. - Utilisez `angular.module('app', []);` pour setter un module. - Utilisez `angular.module('app');` pour getter un module. -### Fonctions Nommées contre Anonymes +### Fonctions Nommées ou Anonymes ###### [Style [Y024](#style-y024)] - Utilisez des fonctions nommées au lieu de passer une fonction anonyme comme callback. @@ -251,7 +250,7 @@ Alors que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'a ét *Pourquoi ?* : Celà produit du code plus lisible, est plus facile à débugguer, et réduit la quantité de code callback imbriqué. ```javascript - /* éviter */ + /* à éviter */ angular .module('app') .controller('Dashboard', function() { }) @@ -280,46 +279,46 @@ Alors que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'a ét **[Retour en haut de page](#table-des-matières)** -## Controllers +## Controlleurs -### controllerAs View Syntax +### La Syntaxe Vue controllerAs ###### [Style [Y030](#style-y030)] - - Use the [`controllerAs`](http://www.johnpapa.net/do-you-like-your-angular-controllers-with-or-without-sugar/) syntax over the `classic controller with $scope` syntax. + - Utilisez la syntaxe [`controllerAs`](http://www.johnpapa.net/do-you-like-your-angular-controllers-with-or-without-sugar/) au lieu de la syntaxe de `controlleur classique avec $scope`. - *Why?*: Controllers are constructed, "newed" up, and provide a single new instance, and the `controllerAs` syntax is closer to that of a JavaScript constructor than the `classic $scope syntax`. + *Pourquoi ?* : Les controlleurs sont constuits, "new-és", and fournissent une unique nouvelle instance, et la syntaxe `controllerAs` est plus proche de celle d'un contructeur Javascript que la `syntaxe $scope classique`. - *Why?*: It promotes the use of binding to a "dotted" object in the View (e.g. `customer.name` instead of `name`), which is more contextual, easier to read, and avoids any reference issues that may occur without "dotting". + *Pourquoi ?* : Il promeut l'usage du binding entre un objet avec "point" et la Vue (ex. `customer.name` au lieu de `name`), ce qui est plus contextuel, plus facile à lire, et évite tout problème de référence qui peut arriver sans "point". - *Why?*: Helps avoid using `$parent` calls in Views with nested controllers. + *Pourquoi ?* : Permet d'éviter l'usage des appels à `$parent` dans les Vues avec des controlleurs imbriqués. ```html - +
{{ name }}
``` ```html - +
{{ customer.name }}
``` -### controllerAs Controller Syntax +### La Syntaxe de Controlleur controllerAs ###### [Style [Y031](#style-y031)] - - Use the `controllerAs` syntax over the `classic controller with $scope` syntax. + - Utilisez la syntaxe `controllerAs` au lieu de la syntaxe de `controlleur classique avec $scope`. - - The `controllerAs` syntax uses `this` inside controllers which gets bound to `$scope` + - La syntaxe `controllerAs` utilise `this` à l'intérieur des controlleurs qui se font relier au `$scope`. - *Why?*: `controllerAs` is syntactic sugar over `$scope`. You can still bind to the View and still access `$scope` methods. + *Pourquoi ?* : `controllerAs` est un sucre syntaxique sur le `$scope`. Vous pouvez toujours vous relier à la Vue et toujours accéder aux métodes du `$scope`. - *Why?*: Helps avoid the temptation of using `$scope` methods inside a controller when it may otherwise be better to avoid them or move them to a factory. Consider using `$scope` in a factory, or if in a controller just when needed. For example when publishing and subscribing events using [`$emit`](https://docs.angularjs.org/api/ng/type/$rootScope.Scope#$emit), [`$broadcast`](https://docs.angularjs.org/api/ng/type/$rootScope.Scope#$broadcast), or [`$on`](https://docs.angularjs.org/api/ng/type/$rootScope.Scope#$on) consider moving these uses to a factory and invoke from the controller. + *Pourquoi ?* : Permet d'éviter la tentation d'utiliser les méthodes du `$scope` à l'intérieur d'un controlleur alors qu'il serait par ailleurs meilleur de les éviter ou de les déplacer dans une factory. Considérez utiliser le `$scope` dans une factory, ou seulement si nécessaire dans un controlleur. Par exemple lorsqu'il faut publier ou souscrire des événements en utilisant [`$emit`](https://docs.angularjs.org/api/ng/type/$rootScope.Scope#$emit), [`$broadcast`](https://docs.angularjs.org/api/ng/type/$rootScope.Scope#$broadcast), ou [`$on`](https://docs.angularjs.org/api/ng/type/$rootScope.Scope#$on) considérez déplacer ces usages dans une factory et les invoquer depuis le controlleur. ```javascript - /* avoid */ + /* à éviter */ function Customer($scope) { $scope.name = {}; $scope.sendMessage = function() { }; @@ -327,22 +326,22 @@ Alors que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'a ét ``` ```javascript - /* recommended - but see next section */ + /* recommandé - mais voir la section suivante */ function Customer() { this.name = {}; this.sendMessage = function() { }; } ``` -### controllerAs with vm +### controllerAs avec vm ###### [Style [Y032](#style-y032)] - - Use a capture variable for `this` when using the `controllerAs` syntax. Choose a consistent variable name such as `vm`, which stands for ViewModel. + - Utilisez une variable de capture pour `this` quand vous utilisez la syntaxe `controllerAs`. Choisissez un nom de variable consistant tel que `vm`, qui signifie ViewModel. - *Why?*: The `this` keyword is contextual and when used within a function inside a controller may change its context. Capturing the context of `this` avoids encountering this problem. + *Pourquoi ?* : Le mot clé `this` est contextuel et son utilisation au sein d'une fonction à l'intérieur d'un controlleur pourrait changer son contexte. Capturer le contexte de `this` évite de rencontrer ce problème. ```javascript - /* avoid */ + /* à éviter */ function Customer() { this.name = {}; this.sendMessage = function() { }; @@ -350,7 +349,7 @@ Alors que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'a ét ``` ```javascript - /* recommended */ + /* recommandé */ function Customer() { var vm = this; vm.name = {}; @@ -358,14 +357,14 @@ Alors que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'a ét } ``` - Note: You can avoid any [jshint](http://www.jshint.com/) warnings by placing the comment below above the line of code. However it is not needed when the function is named using UpperCasing, as this convention means it is a constructor function, which is what a controller is in Angular. + Note : Vous pouvez évitez n'importe quel avertissement [jshint](http://www.jshint.com/) en plaçant le commentaire ci-dessous au dessus de la ligne de code. Cependant, ce n'est pas nécesaire lorsque la fonction est nommée en utilisant la CasseEnMajuscule, puisque cette convention signifie que c'est une fonction constructeur, ce qu'est un controlleur en Angular. ```javascript /* jshint validthis: true */ var vm = this; ``` - Note: When creating watches in a controller using `controller as`, you can watch the `vm.*` member using the following syntax. (Create watches with caution as they add more load to the digest cycle.) + Note : Lors de la création de watchs dans un controlleur en utilisant `controller as`, vous pouvez watcher les membres `vm.*` en utilisant la syntaxe suivante. (Créez des watchs avec prudence puisqu'ils ajoutent plus de charge au cycle de digest.) ```html @@ -383,14 +382,15 @@ Alors que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'a ét } ``` -### Bindable Members Up Top +### Les Membres Bindable au Début ###### [Style [Y033](#style-y033)] - - Place bindable members at the top of the controller, alphabetized, and not spread through the controller code. + - Placez les membres bindables au début du controlleur, par ordre alphabétique, et non pas dispersés à travers le code du controlleur. - *Why?*: Placing bindable members at the top makes it easy to read and helps you instantly identify which members of the controller can be bound and used in the View. + *Pourquoi ?* : Placer les membres bindables au début permet de faciliter la lecture et vous aide à identifier instantanément quels membres du controlleur peut être bindé et utilisés dans la Vue. - *Why?*: Setting anonymous functions in-line can be easy, but when those functions are more than 1 line of code they can reduce the readability. Defining the functions below the bindable members (the functions will be hoisted) moves the implementation details down, keeps the bindable members up top, and makes it easier to read. + *Pourquoi ?* : Placer les fonction anonymes sur la même ligne peut être facile, mais lorsque ces fonctions ont plus d'une ligne de code elles peuvent réduire la lisibilité. Définir les fonctions sous les membres bindables (les fonctions seront hissées) déplace les détails d'implémentation en bas, guardant les membres bindables en haut, + Setting anonymous functions in-line can be easy, but when those functions are more than 1 line of code they can reduce the readability. Defining the functions below the bindable members (the functions will be hoisted) moves the implementation details down, keeps the bindable members up top, and makes it easier to read. ```javascript /* avoid */ @@ -436,12 +436,12 @@ Alors que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'a ét } ``` - ![Controller Using "Above the Fold"](https://raw.githubusercontent.com/johnpapa/angularjs-styleguide/master/assets/above-the-fold-1.png) + ![Les Controlleur Utilisant "Au dessus de la Réduction"](https://raw.githubusercontent.com/johnpapa/angularjs-styleguide/master/assets/above-the-fold-1.png) - Note: If the function is a 1 liner consider keeping it right up top, as long as readability is not affected. + Note : Si la fonction est un one-liner, considérez de la garder bien en haut, tant que la lisibilité n'est pas affectée. ```javascript - /* avoid */ + /* à éviter */ function Sessions(data) { var vm = this; @@ -461,36 +461,36 @@ Alors que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'a ét ``` ```javascript - /* recommended */ + /* recommandé */ function Sessions(dataservice) { var vm = this; vm.gotoSession = gotoSession; - vm.refresh = dataservice.refresh; // 1 liner is OK + vm.refresh = dataservice.refresh; // Le one-liner est acceptable vm.search = search; vm.sessions = []; vm.title = 'Sessions'; ``` -### Function Declarations to Hide Implementation Details +### Déclaration de Fonctions pour Cacher les Détails d'Implémentation ###### [Style [Y034](#style-y034)] - - Use function declarations to hide implementation details. Keep your bindable members up top. When you need to bind a function in a controller, point it to a function declaration that appears later in the file. This is tied directly to the section Bindable Members Up Top. For more details see [this post](http://www.johnpapa.net/angular-function-declarations-function-expressions-and-readable-code). + - Utilisez les déclarations de fonctions pour cacher les détails d'implémentation. Gardez vos membres bindables tout en haut. Quand vous avez besoin de binder une fonction dans un controlleur, faites-la pointer vers la déclaration de la fonction plus bas dans le fichier. Ceci est directement lié à la section des Membres Bindable au Début. Pour plus de détails, vous pouvez lire [cet article](http://www.johnpapa.net/angular-function-declarations-function-expressions-and-readable-code). - *Why?*: Placing bindable members at the top makes it easy to read and helps you instantly identify which members of the controller can be bound and used in the View. (Same as above.) + *Pourquoi ?* : Placer les membres bindables en haut rend plus facile la lecture et vous aide instantanément à identifier quels membres du controlleur peuvent être bindés et utilisés dans la Vue. (Même chose que plus haut.) - *Why?*: Placing the implementation details of a function later in the file moves that complexity out of view so you can see the important stuff up top. + *Pourquoi ?* : Placer les détails d'implémentation d'une fonction plus bas dans le fichier déplace cette complexité en dehors du regard ainsi vous pouvez ne voir que les choses importantes en haut. - *Why?*: Function declaration are hoisted so there are no concerns over using a function before it is defined (as there would be with function expressions). + *Pourquoi ?* : Les déclarations de fichiers sont remontées donc il n'y a aucun problème à utiliser une fonction avant qu'elle ne soit définie (alors que ça le serait avec les expressions de fonction). - *Why?*: You never have to worry with function declarations that moving `var a` before `var b` will break your code because `a` depends on `b`. + *Pourquoi ?* : Vous ne vous préocuperez plus des déclarations de fonctions déplaçant `var a` avant `var b` cassant ainsi votre code car `a` dépend de `b`. - *Why?*: Order is critical with function expressions + *Pourquoi ?* : L'ordre est critique avec les expressions de fonction ```javascript /** - * avoid - * Using function expressions. + * à éviter + * L'utilisation des expressions de fonction. */ function Avengers(dataservice, logger) { var vm = this; @@ -516,13 +516,13 @@ Alors que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'a ét } ``` - Notice that the important stuff is scattered in the preceding example. In the example below, notice that the important stuff is up top. For example, the members bound to the controller such as `vm.avengers` and `vm.title`. The implementation details are down below. This is just easier to read. + Remarquez que les choses importantes sont dispersées dans l'exemple précédent. Dans l'exemple ci-dessous, remarquez que les choses importantes sont tout en haut. Par exemple, les membres bindés au controlleur tels que `vm.avengers` et `vm.title`. Les détails d'implémentation sont plus bas dessous. C'est simplement plus facile à lire. ```javascript /* - * recommend - * Using function declarations - * and bindable members up top. + * recommandé + * L'utilisation des déclarations de fonction + * et les membres bindables tout en haut. */ function Avengers(dataservice, logger) { var vm = this; @@ -547,20 +547,20 @@ Alors que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'a ét } ``` -### Defer Controller Logic +### Déplacer la Logique des Controlleurs ###### [Style [Y035](#style-y035)] - - Defer logic in a controller by delegating to services and factories. - - *Why?*: Logic may be reused by multiple controllers when placed within a service and exposed via a function. + - Déplacer la logique d'un controlleur en la déléguant à des services et des factories. + + *Pourquoi ?* : La logique peut être ré-utilisée par plusieurs controlleurs lorsqu'elle est placée au sein d'un service et exposée via une fonction. - *Why?*: Logic in a service can more easily be isolated in a unit test, while the calling logic in the controller can be easily mocked. + *Pourquoi ?* : La logique d'un service peut plus facilement être isolée dans un test unitaire, tandis que la logique d'appel dans le controlleur peut facilement être mockée. - *Why?*: Removes dependencies and hides implementation details from the controller. + *Pourquoi ?* : Cela supprime des dépendances et cache les détails d'implémentation au controlleur. ```javascript - /* avoid */ + /* à éviter */ function Order($http, $q, config, userInfo) { var vm = this; vm.checkCredit = checkCredit; @@ -568,22 +568,23 @@ Alors que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'a ét vm.total = 0; function checkCredit() { - var settings = {}; - // Get the credit service base URL from config - // Set credit service required headers - // Prepare URL query string or data object with request data - // Add user-identifying info so service gets the right credit limit for this user. - // Use JSONP for this browser if it doesn't support CORS + var settings = {}; + // Obtenir l'URL de base du service credit à partir de la config + // Positionne les headers requis pour le service credit + // Prépare l'URL query string ou l'objet de données avec les données de requête. + // Ajoute les infos d'identification de l'utilsiateur afin que le service obtienne + // les bons droits de limite credit pour cet utilisateur. + // Utilise JSONP pour ce navigateur s'il ne supporte pas CORS return $http.get(settings) .then(function(data) { - // Unpack JSON data in the response object - // to find maxRemainingAmount + // Décompresse les données JSON dans l'objet réponse + // afin de rechercher maxRemainingAmount vm.isCreditOk = vm.total <= maxRemainingAmount }) .catch(function(error) { - // Interpret error - // Cope w/ timeout? retry? try alternate service? - // Re-reject with appropriate error for a user to see + // Interpréter l'erreur + // Gérer le timeout ? Réessayer ? Essayer un service alternatif ? + // Re-rejetter avec une erreur appropriée à la vue de l'utilisateur }); }; } @@ -591,7 +592,7 @@ Alors que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'a ét ```javascript - /* recommended */ + /* recommandé */ function Order(creditService) { var vm = this; vm.checkCredit = checkCredit; @@ -606,24 +607,24 @@ Alors que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'a ét } ``` -### Keep Controllers Focused +### Gardez des Controlleurs Focalisés ###### [Style [Y037](#style-y037)] - - Define a controller for a view, and try not to reuse the controller for other views. Instead, move reusable logic to factories and keep the controller simple and focused on its view. + - Définir un controlleur pour une vue, et n'essayez pas de ré-utiliser le controlleur pour d'autres vues. Au lieu de cela, déplacez la logique réutilisable vers des factories et gardez le controlleur simple et focalisé sur sa vue. - *Why?*: Reusing controllers with several views is brittle and good end to end (e2e) test coverage is required to ensure stability across large applications. + *Pourquoi ?*: La réutilisation de controlleurs sur plusieurs vues est fragile et une bonne couverture de tests de bout en bout ("end to end" ou "e2e") est requise afin d'assurer la stabilité dans les grosses applications. -### Assigning Controllers +### Assigner les Controlleurs ###### [Style [Y038](#style-y038)] - - When a controller must be paired with a view and either component may be re-used by other controllers or views, define controllers along with their routes. + - Lorsqu'un controlleur doit être associé à une vue et qu'un composant pourrait être ré-utilisé par d'autres controlleurs ou vues, définissez les controlleurs avec leurs routes. - Note: If a View is loaded via another means besides a route, then use the `ng-controller="Avengers as vm"` syntax. + Note : Si une Vue est chargée via d'autres moyens que la route, alors utilisez la syntaxe `ng-controller="Avengers as vm"`. - *Why?*: Pairing the controller in the route allows different routes to invoke different pairs of controllers and views. When controllers are assigned in the view using [`ng-controller`](https://docs.angularjs.org/api/ng/directive/ngController), that view is always associated with the same controller. + *Pourquoi ?* : Associer le controlleur dans la route permet que différentes routes invoquent d'autres paires de controlleurs et vues. Lorsque les controlleurs sont assignés dans la vue avec [`ng-controller`](https://docs.angularjs.org/api/ng/directive/ngController), cette vue est toujours associée avec le même controlleur. ```javascript - /* avoid - when using with a route and dynamic pairing is desired */ + /* à éviter - lorsque l'utilisation avec une route et une association dynamique est voulue */ // route-config.js angular @@ -645,7 +646,7 @@ Alors que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'a ét ``` ```javascript - /* recommended */ + /* recommandé */ // route-config.js angular @@ -668,7 +669,7 @@ Alors que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'a ét ``` -**[Back to top](#table-of-contents)** +**[Retour en haut de page](#table-of-contents)** ## Services From 0bf1e5168dd1a0e79f11643a81a178367f6104e6 Mon Sep 17 00:00:00 2001 From: Eric Date: Sun, 28 Dec 2014 17:42:24 +0100 Subject: [PATCH 150/567] [FR] Services --- i18n/fr-FR.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/i18n/fr-FR.md b/i18n/fr-FR.md index 1644595e..bf56c394 100644 --- a/i18n/fr-FR.md +++ b/i18n/fr-FR.md @@ -676,9 +676,9 @@ Alors que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'a ét ### Singletons ###### [Style [Y040](#style-y040)] - - Services are instantiated with the `new` keyword, use `this` for public methods and variables. Since these are so similar to factories, use a factory instead for consistency. + - Les Services sont instanciés avec le mot clé `new`, utilisez `this` pour les méthodes publiques et les variables. Puisque ces derniers sont tellement similaires aux factories, utilisez à la place une factory pour la cohérence. - Note: [All AngularJS services are singletons](https://docs.angularjs.org/guide/services). This means that there is only one instance of a given service per injector. + Note : [Tous les serices AngularJS services sont des singletons](https://docs.angularjs.org/guide/services). Celà signifie qu'il n'y a qu'une seule instance d'un service donné par injecteur. ```javascript // service @@ -708,7 +708,7 @@ Alors que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'a ét } ``` -**[Back to top](#table-of-contents)** +**[Retour en faut de page](#table-of-contents)** ## Factories From c6d5590966b2f8a97c94fd8ad67a9a28b4f0cf24 Mon Sep 17 00:00:00 2001 From: Eric Date: Tue, 30 Dec 2014 11:08:10 +0100 Subject: [PATCH 151/567] [FR] Factories --- i18n/fr-FR.md | 72 +++++++++++++++++++++++++-------------------------- 1 file changed, 36 insertions(+), 36 deletions(-) diff --git a/i18n/fr-FR.md b/i18n/fr-FR.md index bf56c394..da11ee09 100644 --- a/i18n/fr-FR.md +++ b/i18n/fr-FR.md @@ -712,31 +712,31 @@ Alors que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'a ét ## Factories -### Single Responsibility +### Responsabilité Unique ###### [Style [Y050](#style-y050)] - - Factories should have a [single responsibility](http://en.wikipedia.org/wiki/Single_responsibility_principle), that is encapsulated by its context. Once a factory begins to exceed that singular purpose, a new factory should be created. + - Les factories ne devraient avoir qu'une [unique responsabilité](http://en.wikipedia.org/wiki/Single_responsibility_principle), c'est-à-dire encapsulé par son contexte. Une fois qu'une factory commence à dépasser ce but unique, une nouvelle factory devrait être créée. ### Singletons ###### [Style [Y051](#style-y051)] - - Factories are singletons and return an object that contains the members of the service. + - Les factories sont des singletons et renvoient un objet qui contient les membres du service. - Note: [All AngularJS services are singletons](https://docs.angularjs.org/guide/services). + Note : [Tous les services AngularJS sont des singletons](https://docs.angularjs.org/guide/services). -### Accessible Members Up Top +### Membres Accessibles Tout en Haut ###### [Style [Y052](#style-y052)] - - Expose the callable members of the service (it's interface) at the top, using a technique derived from the [Revealing Module Pattern](http://addyosmani.com/resources/essentialjsdesignpatterns/book/#revealingmodulepatternjavascript). + - Exposer les membres appellables du services (son interface) en haut, utilisant une technique dérivée du Principe du Module Révélateur ou [Revealing Module Pattern](http://addyosmani.com/resources/essentialjsdesignpatterns/book/#revealingmodulepatternjavascript). - *Why?*: Placing the callable members at the top makes it easy to read and helps you instantly identify which members of the service can be called and must be unit tested (and/or mocked). + *Pourquoi ?* : Placer les membres appellables tout en haut le rend facile à lire et vous aide à identifier instantanément quels membres du service peut être appellé et doit être testé unitairement (et/ou mocké). - *Why?*: This is especially helpful when the file gets longer as it helps avoid the need to scroll to see what is exposed. + *Pourquoi ?* : Ceci est spécialement conseillé lorsque le fichier devient un peu long et celà aide à éviter le besoin de faire défiler pour voir ce qui est exposé. - *Why?*: Setting functions as you go can be easy, but when those functions are more than 1 line of code they can reduce the readability and cause more scrolling. Defining the callable interface via the returned service moves the implementation details down, keeps the callable interface up top, and makes it easier to read. + *Pourquoi ?* : Placer les fonctions au fil de l'écriture semble être facile, mais quand ces fonctions ont plus d'une ligne de code, elles peuvent réduire la lisibilité et causer plus de défilement. Définir l'interface à appeller via le service renvoyé déplace les détails d'implémentation plus bas, garde l'interface appellante tout en haut, et rend le tout plus facile à lire. ```javascript - /* avoid */ + /* à éviter */ function dataService() { var someValue = ''; function save() { @@ -755,7 +755,7 @@ Alors que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'a ét ``` ```javascript - /* recommended */ + /* recommandé */ function dataService() { var someValue = ''; var service = { @@ -777,52 +777,52 @@ Alors que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'a ét } ``` - This way bindings are mirrored across the host object, primitive values cannot update alone using the revealing module pattern + De cette façon, les bindings sont dupliqués à travers l'objet hôte, les valeurs primitives ne peuvant se mettre à jour toutes seules grâce au principe du module révélateur. - ![Factories Using "Above the Fold"](https://raw.githubusercontent.com/johnpapa/angularjs-styleguide/master/assets/above-the-fold-2.png) + ![Factories Utilisants "Au dessus du Pliage"](https://raw.githubusercontent.com/johnpapa/angularjs-styleguide/master/assets/above-the-fold-2.png) -### Function Declarations to Hide Implementation Details +### Déclaration de Fonctions pour Cacher les Détails d'Implémentation ###### [Style [Y053](#style-y053)] - - Use function declarations to hide implementation details. Keep your accessible members of the factory up top. Point those to function declarations that appears later in the file. For more details see [this post](http://www.johnpapa.net/angular-function-declarations-function-expressions-and-readable-code). + - Utilisez les déclarations de fonction pour cacher les détails d'implémentation. Gardez les membres accessibles de la factory tout en haut. Faites-les pointer vers les déclarations de fonction qui apparaissent plus loin dans le fichier. Pour plus de détails, voir [ce post](http://www.johnpapa.net/angular-function-declarations-function-expressions-and-readable-code). - *Why?*: Placing accessible members at the top makes it easy to read and helps you instantly identify which functions of the factory you can access externally. + *Pourquoi ?* : Placer les membres accessibles tout en haut permet de le rendre facile à lire et vous aide à identifier instantanément quelles fonctions de la factory vous pouvez accéder de l'extérieur. - *Why?*: Placing the implementation details of a function later in the file moves that complexity out of view so you can see the important stuff up top. + *Pourquoi ?* : Placer les détails d'implémentation d'une fonction plus loin dans le fichier déplace cette complexité en dehors de la vue afin de voir les choses importantes tout en haut. - *Why?*: Function declaration are hoisted so there are no concerns over using a function before it is defined (as there would be with function expressions). + *Pourquoi ?* : Les déclarations de fonctions sont hissées de telle sorte qu'il n'y ait aucun soucis à utiliser une fonction avant qu'elle ne soit définie (comme il serait de mise avec les expressions fonctionnelles). - *Why?*: You never have to worry with function declarations that moving `var a` before `var b` will break your code because `a` depends on `b`. + *Pourquoi ?* : Vous n'aurez plus jamais à vous en faire avec les déclarations de fonction dont le déplacement de `var a` avant `var b` pourrait casser votre code à cause d'une dépendance de `a` vers `b`. - *Why?*: Order is critical with function expressions + *Pourquoi ?* : L'ordre est critique avec les expressions fonctionnelles. ```javascript /** - * avoid - * Using function expressions + * À éviter + * L'utilisation des expressions fonctionnelles */ function dataservice($http, $location, $q, exception, logger) { var isPrimed = false; var primePromise; var getAvengers = function() { - // implementation details go here + // avec les détails d'implémentation ici }; var getAvengerCount = function() { - // implementation details go here + // avec les détails d'implémentation ici }; var getAvengersCast = function() { - // implementation details go here + // avec les détails d'implémentation ici }; var prime = function() { - // implementation details go here + // avec les détails d'implémentation ici }; var ready = function(nextPromises) { - // implementation details go here + // avec les détails d'implémentation ici }; var service = { @@ -838,9 +838,9 @@ Alors que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'a ét ```javascript /** - * recommended - * Using function declarations - * and accessible members up top. + * recommandé + * L'utilisation des déclararions de fonction + * et des membres accessibles tout en haut. */ function dataservice($http, $location, $q, exception, logger) { var isPrimed = false; @@ -858,28 +858,28 @@ Alors que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'a ét //////////// function getAvengers() { - // implementation details go here + // avec les détails d'implémentation ici } function getAvengerCount() { - // implementation details go here + // avec les détails d'implémentation ici } function getAvengersCast() { - // implementation details go here + // avec les détails d'implémentation ici } function prime() { - // implementation details go here + // avec les détails d'implémentation ici } function ready(nextPromises) { - // implementation details go here + // avec les détails d'implémentation ici } } ``` -**[Back to top](#table-of-contents)** +**[Retour en haut de page](#table-des-matières)** ## Data Services From 97371a6c09ad66a8df0f42ccb32d360bd1a88f56 Mon Sep 17 00:00:00 2001 From: Eric Date: Fri, 2 Jan 2015 00:33:51 +0100 Subject: [PATCH 152/567] [FR] Data services --- i18n/fr-FR.md | 50 +++++++++++++++++++++++++------------------------- 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/i18n/fr-FR.md b/i18n/fr-FR.md index da11ee09..628e24fc 100644 --- a/i18n/fr-FR.md +++ b/i18n/fr-FR.md @@ -881,23 +881,23 @@ Alors que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'a ét **[Retour en haut de page](#table-des-matières)** -## Data Services +## Services de Données -### Separate Data Calls +### Séparer les Appels de Données ###### [Style [Y060](#style-y060)] - - Refactor logic for making data operations and interacting with data to a factory. Make data services responsible for XHR calls, local storage, stashing in memory, or any other data operations. + - Refactorer la logique pour faire les opérations sur les données et les interactions avec la donnée dans une factory. Rendez les services de données responsables des appels ajax, du local storage, du stockage en mémoire, ou toute autre opérations sur les données. - *Why?*: The controller's responsibility is for the presentation and gathering of information for the view. It should not care how it gets the data, just that it knows who to ask for it. Separating the data services moves the logic on how to get it to the data service, and lets the controller be simpler and more focused on the view. + *Pourquoi ?* : La responsabilité du controlleur est la présentation et l'assemblage des informations pour la vue. Il ne devrait pas se soucier de la façon dont la donnée est récupérée, mais seulement de la façon de la demander. Séparer des services de données déplace la logique du 'comment récupérer une donnée' dans ce service de donnée, et laisse le controlleur plus simple et plus focalisé sur la vue. - *Why?*: This makes it easier to test (mock or real) the data calls when testing a controller that uses a data service. + *Pourquoi ?* : Cela le rend plus facile à tester (en mockant ou avec le vrai) les appels aux données lorsque l'on teste un controlleur qui utilise un service de données. - *Why?*: Data service implementation may have very specific code to handle the data repository. This may include headers, how to talk to the data, or other services such as $http. Separating the logic into a data service encapsulates this logic in a single place hiding the implementation from the outside consumers (perhaps a controller), also making it easier to change the implementation. + *Pourquoi ?* : L'implémentation d'un service de données peut avoir du code très spécifique pour gérer le référentiel des données. Celà peut inclure des entêtes, la façon de dialoguer avec la donnée, ou des dépendances vers d'autres services tels que $http. La séparation de la logique vers un service de données encapsule cette logique dans un unique endroit en cachant les détails d'implémentation du consommateur externe (peut-être un controlleur), en rendant également plus simple les changements d'implémentation. ```javascript - /* recommended */ + /* Recommandé */ - // dataservice factory + // une factory service de données angular .module('app.core') .factory('dataservice', dataservice); @@ -925,12 +925,12 @@ Alors que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'a ét } ``` - Note: The data service is called from consumers, such as a controller, hiding the implementation from the consumers, as shown below. + Note : Le service de données est appellé depuis des consommateurs, tels que des controlleurs, en leur cachant l'implémentation, comme le montre l'éxemple ci-dessous. ```javascript - /* recommended */ + /* Recommandé */ - // controller calling the dataservice factory + // un controller qui appelle la factory du service de données angular .module('app.avengers') .controller('Avengers', Avengers); @@ -959,28 +959,28 @@ Alors que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'a ét } ``` -### Return a Promise from Data Calls +### Retourner une promesse depuis un appel de donnée ###### [Style [Y061](#style-y061)] - - When calling a data service that returns a promise such as $http, return a promise in your calling function too. + - Lorsqu'un service de données retourne une promesse telle que $http, retournez une promesse dans votre fonction appelée. - *Why?*: You can chain the promises together and take further action after the data call completes and resolves or rejects the promise. + *Pourquoi ?* : Vous pouvez chainez les promesses entre elles et ajouter des actions après que l'appel des données soit terminé puis résoudre ou rejeter la promesse. ```javascript - /* recommended */ + /* Recommandé */ activate(); function activate() { /** - * Step 1 - * Ask the getAvengers function for the - * avenger data and wait for the promise + * Etape 1 + * Appel la fonction getAvengers pour récupérer + * les données avenger et attend la promesse */ return getAvengers().then(function() { /** - * Step 4 - * Perform an action on resolve of final promise + * Etape 4 + * Exécute une action à la résolution de la promesse finale */ logger.info('Activated Avengers View'); }); @@ -988,15 +988,15 @@ Alors que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'a ét function getAvengers() { /** - * Step 2 - * Ask the data service for the data and wait - * for the promise + * Etape 2 + * Appel du service de données pour récupérer les données + * et attend la promesse */ return dataservice.getAvengers() .then(function(data) { /** - * Step 3 - * set the data and resolve the promise + * Etape 3 + * Défini les donnée et résoue la promesse */ vm.avengers = data; return vm.avengers; From e1c391ce731eb117462fd4d76f4bf7e23a514976 Mon Sep 17 00:00:00 2001 From: Audrien Fontaine Date: Sat, 3 Jan 2015 19:32:58 +0100 Subject: [PATCH 153/567] [FR] Directives --- i18n/fr-FR.md | 98 +++++++++++++++++++++++++-------------------------- 1 file changed, 49 insertions(+), 49 deletions(-) diff --git a/i18n/fr-FR.md b/i18n/fr-FR.md index 628e24fc..5f74f303 100644 --- a/i18n/fr-FR.md +++ b/i18n/fr-FR.md @@ -930,7 +930,7 @@ Alors que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'a ét ```javascript /* Recommandé */ - // un controller qui appelle la factory du service de données + // un controlleur qui appelle la factory du service de données angular .module('app.avengers') .controller('Avengers', Avengers); @@ -964,10 +964,10 @@ Alors que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'a ét - Lorsqu'un service de données retourne une promesse telle que $http, retournez une promesse dans votre fonction appelée. - *Pourquoi ?* : Vous pouvez chainez les promesses entre elles et ajouter des actions après que l'appel des données soit terminé puis résoudre ou rejeter la promesse. + *Pourquoi ?* : Vous pouvez chainer les promesses entre elles et ajouter des actions après que l'appel des données soit terminé puis résoudre ou rejeter la promesse. ```javascript - /* Recommandé */ + /* recommandé */ activate(); @@ -1004,54 +1004,54 @@ Alors que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'a ét } ``` - **[Back to top](#table-of-contents)** + **[Retour en haut de page](#table-des-matières)** ## Directives -### Limit 1 Per File +### Limite de 1 Par Fichier ###### [Style [Y070](#style-y070)] - - Create one directive per file. Name the file for the directive. + - Créer une directive par fichier. Nommer le fichier en fonction de la directive. - *Why?*: It is easy to mash all the directives in one file, but difficult to then break those out so some are shared across apps, some across modules, some just for one module. + *Pourquoi ?* : C'est facile de placer toutes les directives dans un fichier, mais difficile de les séparer, certains sont partagés par toute l'application, certain par modules, et certain juste par un module. - *Why?*: One directive per file is easy to maintain. + *Pourquoi ?* : Une directive par fichier est plus facilement maintenable. ```javascript - /* avoid */ + /* à éviter */ /* directives.js */ angular .module('app.widgets') - /* order directive that is specific to the order module */ + /* directive order spécifique pour le module order */ .directive('orderCalendarRange', orderCalendarRange) - /* sales directive that can be used anywhere across the sales app */ + /* directive sales pouvant être utilisée n'importe où dans l'application sales */ .directive('salesCustomerInfo', salesCustomerInfo) - /* spinner directive that can be used anywhere across apps */ + /* directive spinner pouvant être utilisée n'importe où dans l'application */ .directive('sharedSpinner', sharedSpinner); function orderCalendarRange() { - /* implementation details */ + /* détails de l'implémentation */ } function salesCustomerInfo() { - /* implementation details */ + /* détails de l'implémentation */ } function sharedSpinner() { - /* implementation details */ + /* détails de l'implémentation */ } ``` ```javascript - /* recommended */ + /* recommandé */ /* calendarRange.directive.js */ /** - * @desc order directive that is specific to the order module at a company named Acme + * @desc directive order spécifique pour le module order pour la compagnie Acme * @example
*/ angular @@ -1059,16 +1059,16 @@ Alors que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'a ét .directive('acmeOrderCalendarRange', orderCalendarRange); function orderCalendarRange() { - /* implementation details */ + /* détails de l'implémentation */ } ``` ```javascript - /* recommended */ + /* recommandé */ /* customerInfo.directive.js */ /** - * @desc spinner directive that can be used anywhere across the sales app at a company named Acme + * @desc directive sales pouvant être utilisée n'importe où dans l'application sales pour la compagnie Acme * @example
*/ angular @@ -1076,16 +1076,16 @@ Alors que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'a ét .directive('acmeSalesCustomerInfo', salesCustomerInfo); function salesCustomerInfo() { - /* implementation details */ + /* détails de l'implémentation */ } ``` ```javascript - /* recommended */ + /* recommandé */ /* spinner.directive.js */ /** - * @desc spinner directive that can be used anywhere across apps at a company named Acme + * @desc directive spinner pouvant être utilisée n'importe où dans l'application pour la compagnie Acme * @example
*/ angular @@ -1093,46 +1093,46 @@ Alors que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'a ét .directive('acmeSharedSpinner', sharedSpinner); function sharedSpinner() { - /* implementation details */ + /* détails de l'implémentation */ } ``` - Note: There are many naming options for directives, especially since they can be used in narrow or wide scopes. Choose one that makes the directive and it's file name distinct and clear. Some examples are below, but see the naming section for more recommendations. + Note : Il y a plusieurs options de nommage pour les directives, puisqu'elles peuvent être utilisé par des scopes plus ou moins larges. Choisissez un nom qui rend la directive et son fichier clair et distinct. Des exemples sont définis plus bas, mais regarder la section des noms pour plus de recommandations. -### Manipulate DOM in a Directive +### Manipuler le DOM dans une Directive ###### [Style [Y072](#style-y072)] - - When manipulating the DOM directly, use a directive. If alternative ways can be used such as using CSS to set styles or the [animation services](https://docs.angularjs.org/api/ngAnimate), Angular templating, [`ngShow`](https://docs.angularjs.org/api/ng/directive/ngShow) or [`ngHide`](https://docs.angularjs.org/api/ng/directive/ngHide), then use those instead. For example, if the directive simply hides and shows, use ngHide/ngShow. + - Quand le DOM est directement manipulé, utilisez une directive. Si une alternative peut être utilisé avec le CSS pour définir le style ou les [services d'animation](https://docs.angularjs.org/api/ngAnimate), les templates Angular , [`ngShow`](https://docs.angularjs.org/api/ng/directive/ngShow) ou [`ngHide`](https://docs.angularjs.org/api/ng/directive/ngHide), mieux vaut les utiliser à la place. Par exemple, si la directive affiche ou cache un élément, utilisez ngHide/ngShow. - *Why?*: DOM manipulation can be difficult to test, debug, and there are often better ways (e.g. CSS, animations, templates) + *Pourquoi ?* : La manipulation du DOM peut être difficile à tester, debugger, et il y a souvent une meilleure façon de faire (e.g. CSS, animations, templates) -### Provide a Unique Directive Prefix +### Fournir un Unique Préfixe de Directive ###### [Style [Y073](#style-y073)] - - Provide a short, unique and descriptive directive prefix such as `acmeSalesCustomerInfo` which is declared in HTML as `acme-sales-customer-info`. + - Definissez un préfixe de directive court, unique et descriptif tel que `acmeSalesCustomerInfo` et déclaré en HTML comme `acme-sales-customer-info`. - *Why?*: The unique short prefix identifies the directive's context and origin. For example a prefix of `cc-` may indicate that the directive is part of a CodeCamper app while `acme-` may indicate a directive for the Acme company. + *Pourquoi ?* : Le préfixe court et unique identifie le contexte et l'origine de la directive. Par exemple, un préfixe `cc-` peut indiquer que la directive fait partie de l'application CodeCamper alors que `acme-` peut indiquer une directive de la companie Acme. - Note: Avoid `ng-` as these are reserved for AngularJS directives.Research widely used directives to avoid naming conflicts, such as `ion-` for the [Ionic Framework](http://ionicframework.com/). + Note : Evitez `ng-` car il est réservé pour les directives AngularJS. Cherchez les directives largement utilisées pour éviter les conflits de nom, tel que `ion-` pour le [Framework Ionic](http://ionicframework.com/). -### Restrict to Elements and Attributes +### Restreindre aux Éléments et aux Attributs ###### [Style [Y074](#style-y074)] - - When creating a directive that makes sense as a standalone element, allow restrict `E` (custom element) and optionally restrict `A` (custom attribute). Generally, if it could be its own control, `E` is appropriate. General guideline is allow `EA` but lean towards implementing as an element when its standalone and as an attribute when it enhances its existing DOM element. + - Lors de la création d'une directive qui fait du sens comme élément indépendant, permettez la restriction `E` (élément personnalisé) et éventuellement la restriction `A` (attribut personnalisé). En général, s'il devrait avoir son propre contrôle, `E` est le plus indiqué. Le conseil le plus général est de permettre `EA` mais se dirige vers une implémentation en tant qu'élément lorsqu'il est indépendant et en tant qu'attribut lorsqu'il améliore un élément DOM existant. - *Why?*: It makes sense. + *Why?* : Ça fait sens. - *Why?*: While we can allow the directive to be used as a class, if the directive is truly acting as an element it makes more sense as an element or at least as an attribute. + *Why?* : Même s'il est autorisé d'utiliser une directive en tant que classe, si la directive agit vraiement comme un élément, elle fait plus de sens en tant qu'élément ou au moins en tant qu'attribut. - Note: EA is the default for AngularJS 1.3 + + Note : EA est la valeur par défaut avec AngularJS 1.3 + ```html - +
``` ```javascript - /* avoid */ + /* à éviter */ angular .module('app.widgets') .directive('myCalendarRange', myCalendarRange); @@ -1152,13 +1152,13 @@ Alors que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'a ét ``` ```html - +
``` ```javascript - /* recommended */ + /* recommandé */ angular .module('app.widgets') .directive('myCalendarRange', myCalendarRange); @@ -1177,18 +1177,18 @@ Alors que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'a ét } ``` -### Directives and ControllerAs +### Directives et ControllerAs ###### [Style [Y075](#style-y075)] - - Use `controller as` syntax with a directive to be consistent with using `controller as` with view and controller pairings. + - Utilisez la syntaxe `controller as` avec une directive pour être cohérent avec l'utilisation de `controller as` pour l'association de la vue et du controlleur. - *Why?*: It makes sense and it's not difficult. + *Pourquoi ?* : Ça fait sens et ce n'est pas difficile. - Note: The directive below demonstrates some of the ways you can use scope inside of link and directive controllers, using controllerAs. I in-lined the template just to keep it all in one place. + Note : La directive ci-dessous démontre une façon parmis d'autres d'utiliser le scope à l'intérieur de la fonction link et dans un controlleur de directive, par l'utilisation de controllerAs. J'ai in-liné le template que pour le mettre au même endroit. - Note: Regarding dependency injection, see [Manually Identify Dependencies](#manual-annotating-for-dependency-injection). + Note : Concernant l'injection de dépendance, voir [Identifier Manuellement les Dépendances](#manual-annotating-for-dependency-injection). - Note: Note that the directive's controller is outside the directive's closure. This style eliminates issues where the injection gets created as unreachable code after a `return`. + Note : Remarquez que le controlleur de la directive est à l'extérieur de la closure de la directive. Cette façon de faire évite le problème des injections plus disponibles après le `return`. ```html
@@ -1223,7 +1223,7 @@ Alors que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'a ét ExampleController.$inject = ['$scope']; function ExampleController($scope) { - // Injecting $scope just for comparison + // Injection du $scope seuelement pour la comparaison var vm = this; vm.min = 3; @@ -1241,7 +1241,7 @@ Alors que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'a ét
min={{vm.min}}
``` -**[Back to top](#table-of-contents)** +**[Retour en haut de la page](#table-des-matieres)** ## Resolving Promises for a Controller From e1c14fd485c0c7c5496807f912d5606648577d46 Mon Sep 17 00:00:00 2001 From: Eric Date: Thu, 8 Jan 2015 08:32:18 +0100 Subject: [PATCH 154/567] [FR] Resolving Promises for a Controller --- i18n/fr-FR.md | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/i18n/fr-FR.md b/i18n/fr-FR.md index 5f74f303..5b0945a7 100644 --- a/i18n/fr-FR.md +++ b/i18n/fr-FR.md @@ -1245,17 +1245,17 @@ Alors que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'a ét ## Resolving Promises for a Controller -### Controller Activation Promises +### Promesses d'Activation du Controller ###### [Style [Y080](#style-y080)] - - Resolve start-up logic for a controller in an `activate` function. + - Résolvez la logique de démarrage d'un controlleur dans une fonction `activate`. - *Why?*: Placing start-up logic in a consistent place in the controller makes it easier to locate, more consistent to test, and helps avoid spreading out the activation logic across the controller. + *Pourquoi ?* : Placer la logique de démarrage toujours au même endroit permet de le rendre plus facile à localiser, plus cohérent à tester, et permet d'éviter la dispersion de la logique d'activation à travers le controlleur. - Note: If you need to conditionally cancel the route before you start use the controller, use a route resolve instead. + Note : Si vous avez besoin d'annuler sous conditions la route avant de vous mettre à utiliser le controlleur, utilisez une résolution de route à la place. ```javascript - /* avoid */ + /* à éviter */ function Avengers(dataservice) { var vm = this; vm.avengers = []; @@ -1269,7 +1269,7 @@ Alors que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'a ét ``` ```javascript - /* recommended */ + /* recommandé */ function Avengers(dataservice) { var vm = this; vm.avengers = []; @@ -1288,24 +1288,24 @@ Alors que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'a ét } ``` -### Route Resolve Promises +### Promesses de Résolution de Route ###### [Style [Y081](#style-y081)] - - When a controller depends on a promise to be resolved, resolve those dependencies in the `$routeProvider` before the controller logic is executed. If you need to conditionally cancel a route before the controller is activated, use a route resolver. + - Lorsqu'un controlleur dépend d'une promesse qui doit être résolue, résolvez ces dépendances dans le `$routeProvider` avant que la logique du controlleur soit éxécutée. Si vous avez besoin d'annuler une route sous certaines conditions avant que le controlleur soit activé, utilisez un resolver de route. - *Why?*: A controller may require data before it loads. That data may come from a promise via a custom factory or [$http](https://docs.angularjs.org/api/ng/service/$http). Using a [route resolve](https://docs.angularjs.org/api/ngRoute/provider/$routeProvider) allows the promise to resolve before the controller logic executes, so it might take action based on that data from the promise. + *Pourquoi ?* : Un controlleur pourrait avoir besoin de données avant qu'il se charge. Cette donnée pourrait venir d'une promesse via une factory personnalisée ou de [$http](https://docs.angularjs.org/api/ng/service/$http). Utiliser une [resolution de route](https://docs.angularjs.org/api/ngRoute/provider/$routeProvider) permet à la promesse de se résoudre avant que la logique du controlleur s'éxécute, ainsi on peut prendre des actions basées sur cette donnée à partir de la promesse. ```javascript - /* avoid */ + /* à éviter */ angular .module('app') .controller('Avengers', Avengers); function Avengers(movieService) { var vm = this; - // unresolved + // non-résolue vm.movies; - // resolved asynchronously + // résolue de façon asynchrone movieService.getMovies().then(function(response) { vm.movies = response.movies; }); @@ -1313,7 +1313,7 @@ Alors que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'a ét ``` ```javascript - /* better */ + /* mieux */ // route-config.js angular @@ -1346,9 +1346,9 @@ Alors que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'a ét } ``` - Note: The code example's dependency on `movieService` is not minification safe on its own. For details on how to make this code minification safe, see the sections on [dependency injection](#manual-annotating-for-dependency-injection) and on [minification and annotation](#minification-and-annotation). + Note : Les dépendances dans l'exemple de code sur `movieService` n'est pas directement compatible avec la minification. Pour les détails sur la façon de rendre ce code compatible avec la minification, voir la section sur l'[injection de dépendance](#manual-annotating-for-dependency-injection) et sur [la minification et les annotations](#minification-and-annotation). -**[Back to top](#table-of-contents)** +**[Retour en haut de page](#table-of-contents)** ## Manual Annotating for Dependency Injection From 8e408d3615d1101144cb4c8a509058e44cb447b3 Mon Sep 17 00:00:00 2001 From: Eric Date: Sun, 11 Jan 2015 10:25:22 +0100 Subject: [PATCH 155/567] [FR] Manual Annotation for Dependency Injection --- i18n/fr-FR.md | 52 +++++++++++++++++++++++++-------------------------- 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/i18n/fr-FR.md b/i18n/fr-FR.md index 5b0945a7..e7f15933 100644 --- a/i18n/fr-FR.md +++ b/i18n/fr-FR.md @@ -1346,21 +1346,21 @@ Alors que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'a ét } ``` - Note : Les dépendances dans l'exemple de code sur `movieService` n'est pas directement compatible avec la minification. Pour les détails sur la façon de rendre ce code compatible avec la minification, voir la section sur l'[injection de dépendance](#manual-annotating-for-dependency-injection) et sur [la minification et les annotations](#minification-and-annotation). + Note : Les dépendances dans l'exemple de code sur `movieService` ne sont pas directement compatibles avec la minification. Pour les détails sur la façon de rendre ce code compatible avec la minification, voir la section sur l'[injection de dépendance](#manual-annotating-for-dependency-injection) et sur [la minification et les annotations](#minification-and-annotation). **[Retour en haut de page](#table-of-contents)** -## Manual Annotating for Dependency Injection +## Annoter Manuellement pour l'Injection de Dépendances -### UnSafe from Minification +### Non Sur pour la Minification ###### [Style [Y090](#style-y090)] - - Avoid using the shortcut syntax of declaring dependencies without using a minification-safe approach. + - Eviter l'utilisation de la syntaxe raccourcie de déclaration des dépendances sans utiliser une approche sûre pour la minification. - *Why?*: The parameters to the component (e.g. controller, factory, etc) will be converted to mangled variables. For example, `common` and `dataservice` may become `a` or `b` and not be found by AngularJS. + *Pourquoi ?* : Les paramètres du composant (ex: controlleur, factory, etc.) seront converties en variables mutilées. Par exemple, ˋcommonˋet ˋdataserviceˋ deviendraient ˋaˋet ˋbˋ et ne seraient pas trouvées par AngularJS. ```javascript - /* avoid - not minification-safe*/ + /* à éviter - non sûr pour la minification */ angular .module('app') .controller('Dashboard', Dashboard); @@ -1369,26 +1369,26 @@ Alors que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'a ét } ``` - This code may produce mangled variables when minified and thus cause runtime errors. + Ce code pourrait produire des variables mutilées après minification et en cela provoquer des erreurs à l'éxécution. ```javascript - /* avoid - not minification-safe*/ + /* à éviter - non sûr pour la minification */ angular.module('app').controller('Dashboard', d);function d(a, b) { } ``` -### Manually Identify Dependencies +### Identifier Manuellement les Dépendances ###### [Style [Y091](#style-y091)] - - Use `$inject` to manually identify your dependencies for AngularJS components. + - Utilisez ˋ$injectˋpour identifier manuellement vos dépendances de composants AngularJS. - *Why?*: This technique mirrors the technique used by [`ng-annotate`](https://github.com/olov/ng-annotate), which I recommend for automating the creation of minification safe dependencies. If `ng-annotate` detects injection has already been made, it will not duplicate it. + *Pourquoi ? * : Cette technique est la même que celle utilisée par [`ng-annotate`](https://github.com/olov/ng-annotate), que je recommande pour automatiser la création de dépendances sûres pour la minification. Si ˋng-annotateˋ détecte que l'injection a déjà été faite, celà ne la dupliquera pas. - *Why?*: This safeguards your dependencies from being vulnerable to minification issues when parameters may be mangled. For example, `common` and `dataservice` may become `a` or `b` and not be found by AngularJS. + *Pourquoi ?* : Ca préserve vos dépendances d'être vulnérable aux problèmes de minification lorsque les paramètres sont mutilés. Par exemple, ˋcommonˋet ˋdataserviceˋpourraient devenir ˋaˋ et ˋbˋ et ne pas être trouvés par AngularJS. - *Why?*: Avoid creating in-line dependencies as long lists can be difficult to read in the array. Also it can be confusing that the array is a series of strings while the last item is the component's function. + *Pourquoi ?* : Eviter de créer en ligne une longue liste de dépendances peut rendre le tableau difficile à lire. De même, il peut entraîner une confusion dans la mesure où le tableau est une série de chaînes de caratères alors que le dernier élément est le nom de la fonction du composant. ```javascript - /* avoid */ + /* à éviter */ angular .module('app') .controller('Dashboard', @@ -1398,7 +1398,7 @@ Alors que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'a ét ``` ```javascript - /* avoid */ + /* à éviter */ angular .module('app') .controller('Dashboard', @@ -1409,7 +1409,7 @@ Alors que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'a ét ``` ```javascript - /* recommended */ + /* recommandé */ angular .module('app') .controller('Dashboard', Dashboard); @@ -1420,12 +1420,12 @@ Alors que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'a ét } ``` - Note: When your function is below a return statement the $inject may be unreachable (this may happen in a directive). You can solve this by either moving the $inject above the return statement or by using the alternate array injection syntax. + Note : Lorsque votre fonction est sous une instruction de return, le $inject peut ne pas être accessible (cela pourrait arriver dans une directive). Vous pouvez résoudre ça soit en déplaçant le $inject au dessus de l'instruction de return soit en utilisant la syntaxe d'injection avec le tableau. - Note: [`ng-annotate 0.10.0`](https://github.com/olov/ng-annotate) introduced a feature where it moves the `$inject` to where it is reachable. + Note : [`ng-annotate 0.10.0`](https://github.com/olov/ng-annotate) a introduit une fonctionnalité où il déplace le ˋ$injectˋ là où il devient accessible. ```javascript - // inside a directive definition + // à l'intérieur d'une définition de directive function outer() { return { controller: DashboardPanel, @@ -1438,7 +1438,7 @@ Alors que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'a ét ``` ```javascript - // inside a directive definition + // à l'intérieur d'une définition de directive. function outer() { DashboardPanel.$inject = ['logger']; // reachable return { @@ -1450,17 +1450,17 @@ Alors que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'a ét } ``` -### Manually Identify Route Resolver Dependencies +### Identifier Manuellement les Dépendances du Route Resolver ###### [Style [Y092](#style-y092)] - - Use $inject to manually identify your route resolver dependencies for AngularJS components. + - Utilisez $inject pour identifier manuellement vos dépendances du route resolver pour les composants AngularJS. - *Why?*: This technique breaks out the anonymous function for the route resolver, making it easier to read. + *Pourquoi ?* : Cette technique divise la fonction anonyme pour le route resolver, la rendant plsu facile à lire. - *Why?*: An `$inject` statement can easily precede the resolver to handle making any dependencies minification safe. + *Pourquoi ?* : Une instruction `$inject` peut facilement précéder le resolver à manipuler rendant n'importe quelle dépendance sûre à la minification. ```javascript - /* recommended */ + /* recommandé */ function config($routeProvider) { $routeProvider .when('/avengers', { @@ -1479,7 +1479,7 @@ Alors que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'a ét } ``` -**[Back to top](#table-of-contents)** +**[Retour en haut de page](#table-des-matieres)** ## Minification and Annotation From 7d0d56941970128884b147de76002bbca2a7ca53 Mon Sep 17 00:00:00 2001 From: Eric Date: Tue, 13 Jan 2015 06:48:52 +0100 Subject: [PATCH 156/567] [FR] Minification et Annotation --- i18n/fr-FR.md | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/i18n/fr-FR.md b/i18n/fr-FR.md index e7f15933..db828eae 100644 --- a/i18n/fr-FR.md +++ b/i18n/fr-FR.md @@ -1481,20 +1481,20 @@ Alors que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'a ét **[Retour en haut de page](#table-des-matieres)** -## Minification and Annotation +## Minification et Annotation ### ng-annotate ###### [Style [Y100](#style-y100)] - - Use [ng-annotate](//github.com/olov/ng-annotate) for [Gulp](http://gulpjs.com) or [Grunt](http://gruntjs.com) and comment functions that need automated dependency injection using `/** @ngInject */` + - Utilisez [ng-annotate](//github.com/olov/ng-annotate) pour [Gulp](http://gulpjs.com) ou [Grunt](http://gruntjs.com) et commentez les fonctions qui nécessitent l'injection de dépendances automatique en utilisant `/** @ngInject */`. - *Why?*: This safeguards your code from any dependencies that may not be using minification-safe practices. + *Pourquoi ?* : Ca préserve votre code de n'importe quelle dépendance qui pourrait ne pas utiliser les pratiques sûres à la minification. - *Why?*: [`ng-min`](https://github.com/btford/ngmin) is deprecated + *Pourquoi ?*: [`ng-min`](https://github.com/btford/ngmin) est déprécié. - >I prefer Gulp as I feel it is easier to write, to read, and to debug. + >Je préfère Gulp car ça me paraît plus facile à écrire, lire et débugger. - The following code is not using minification safe dependencies. + Le code suivant n'utilise pas de dépendances sûres à la minification. ```javascript angular @@ -1514,7 +1514,7 @@ Alors que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'a ét } ``` - When the above code is run through ng-annotate it will produce the following output with the `$inject` annotation and become minification-safe. + Lorsque le code ci-dessus est éxécuté par ng-annotate il produira le résultat suivant avec l'annotation ˋ$injectˋ et deviendra sûr à la minification. ```javascript angular @@ -1536,12 +1536,12 @@ Alors que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'a ét Avengers.$inject = ['storageService', 'avengerService']; ``` - Note: If `ng-annotate` detects injection has already been made (e.g. `@ngInject` was detected), it will not duplicate the `$inject` code. + Note : Si ˋng-annotateˋ détecte que l'injection a déjà été faite (ex : ˋ@ngInjectˋ a été détécté), il ne dupliquera pas le code ˋ$injectˋ. - Note: When using a route resolver you can prefix the resolver's function with `/* @ngInject */` and it will produce properly annotated code, keeping any injected dependencies minification safe. + Note : Lors de l'utilisation d'un route resolver, vous pouvez préfixer la fonction de résolution avec `/* @ngInject */` et cela produira le code proprepement annoté, en gardant toute dépendance injectée sûre à la minification. ```javascript - // Using @ngInject annotations + // En utilisant les annotations @ngInject function config($routeProvider) { $routeProvider .when('/avengers', { @@ -1557,17 +1557,17 @@ Alors que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'a ét } ``` - > Note: Starting from AngularJS 1.3 use the [`ngApp`](https://docs.angularjs.org/api/ng/directive/ngApp) directive's `ngStrictDi` parameter. When present the injector will be created in "strict-di" mode causing the application to fail to invoke functions which do not use explicit function annotation (these may not be minification safe). Debugging info will be logged to the console to help track down the offending code. + > Note : A partir d'AngularJS 1.3, utilisez le paramètre ˋngStrictDiˋ de la directive [`ngApp`](https://docs.angularjs.org/api/ng/directive/ngApp). Avec ce paramètre, l'injecteur sera créé en mode "strict-di" qui rendra fera échouer les invocations de fonctions de l'application qui n'utilisent pas explicitement les annotation de fonction (ceci peut ne pas être sûr à la minification). Débugger les informations qui seront logguées dans la console peut aider à débusquer le code à l'origine. `` -### Use Gulp or Grunt for ng-annotate +### Utilisation de Gulp ou Grunt pour ng-annotate ###### [Style [Y101](#style-y101)] - - Use [gulp-ng-annotate](https://www.npmjs.org/package/gulp-ng-annotate) or [grunt-ng-annotate](https://www.npmjs.org/package/grunt-ng-annotate) in an automated build task. Inject `/* @ngInject */` prior to any function that has dependencies. + - Utilisez [gulp-ng-annotate](https://www.npmjs.org/package/gulp-ng-annotate) ou [grunt-ng-annotate](https://www.npmjs.org/package/grunt-ng-annotate) dans une tâche de build automatisée. Injectez `/* @ngInject */` avant toute fonction qui possède des dépendances. - *Why?*: ng-annotate will catch most dependencies, but it sometimes requires hints using the `/* @ngInject */` syntax. + *Pourquoi ?* : ng-annotate va intercepter la plupart des dépendances, mais parfois va nécessiter des indices grâce à l'utilisation de la syntaxe `/* @ngInject */ˋ. - The following code is an example of a gulp task using ngAnnotate + Le code ci-dessous est un exemple d'une tâche gulp qui utilise ngAnnotate ```javascript gulp.task('js', ['jshint'], function() { @@ -1575,10 +1575,10 @@ Alors que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'a ét return gulp.src(source) .pipe(sourcemaps.init()) .pipe(concat('all.min.js', {newLine: ';'})) - // Annotate before uglify so the code get's min'd properly. + // Annotate est avant uglify pour que le code soit minifié correctement. .pipe(ngAnnotate({ - // true helps add where @ngInject is not used. It infers. - // Doesn't work with resolve, so we must be explicit there + // true permet de l'ajouter là où @ngInject n'est pas utilisé. C'est inféré. + // Ne fonctionne pas avec resolve, donc nous devons être explicite ici. add: true })) .pipe(bytediff.start()) @@ -1590,7 +1590,7 @@ Alors que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'a ét ``` -**[Back to top](#table-of-contents)** +**[Retour en haut de page](#table-des-matières)** ## Exception Handling From 75666fca33212bde053ed9ac04fdbdcf575a5f6f Mon Sep 17 00:00:00 2001 From: Eric Date: Wed, 14 Jan 2015 09:34:58 +0100 Subject: [PATCH 157/567] [FR] Exceptions Handling --- i18n/fr-FR.md | 52 +++++++++++++++++++++++++-------------------------- 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/i18n/fr-FR.md b/i18n/fr-FR.md index db828eae..8b5e9d3e 100644 --- a/i18n/fr-FR.md +++ b/i18n/fr-FR.md @@ -32,7 +32,7 @@ Alors que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'a ét 1. [Resolving Promises for a Controller](#resolving-promises-for-a-controller) 1. [Manual Annotating for Dependency Injection](#manual-annotating-for-dependency-injection) 1. [Minification and Annotation](#minification-and-annotation) - 1. [Exception Handling](#exception-handling) + 1. [Gestion des Exceptions](#gestion-des-exceptions) 1. [Naming](#naming) 1. [Application Structure LIFT Principle](#application-structure-lift-principle) 1. [Application Structure](#application-structure) @@ -1592,19 +1592,19 @@ Alors que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'a ét **[Retour en haut de page](#table-des-matières)** -## Exception Handling +## Gestion des Exceptions -### decorators +### decorateurs ###### [Style [Y110](#style-y110)] - - Use a [decorator](https://docs.angularjs.org/api/auto/service/$provide#decorator), at config time using the [`$provide`](https://docs.angularjs.org/api/auto/service/$provide) service, on the [`$exceptionHandler`](https://docs.angularjs.org/api/ng/service/$exceptionHandler) service to perform custom actions when exceptions occur. + - Utilisez un [decorateur](https://docs.angularjs.org/api/auto/service/$provide#decorator), au moment de la configuration en utilisant le service [`$provide`](https://docs.angularjs.org/api/auto/service/$provide), sur le service [`$exceptionHandler`](https://docs.angularjs.org/api/ng/service/$exceptionHandler) pour effecture des actions personnalisées lorsque des exceptions se produisent. - *Why?*: Provides a consistent way to handle uncaught AngularJS exceptions for development-time or run-time. + *Pourquoi ?* : Fournir un moyen cohérent pour gérer les exceptions non interceptées d'AngularJS pendant le développement ou à l'éxécution. - Note: Another option is to override the service instead of using a decorator. This is a fine option, but if you want to keep the default behavior and extend it a decorator is recommended. + Note : Une autre possibilité serait de surcharger le service au lieu d'utiliser un décorateur. C'est une bonne possibilité, mais si vou voulez garder le comportement par défaut et l'étendre, un décorateur est plus approprié. ```javascript - /* recommended */ + /* recommandé */ angular .module('blocks.exception') .config(exceptionConfig); @@ -1625,9 +1625,9 @@ Alors que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'a ét cause: cause }; /** - * Could add the error to a service's collection, - * add errors to $rootScope, log errors to remote web server, - * or log locally. Or throw hard. It is entirely up to you. + * On pourrait ajouter l'erreur à une collection d'un service, + * ajouter les erreurs au $rootScope, loguer les erreurs vers un serveur distant, + * ou loguer locallement. Ou rejetter directement. C'est entièrement votre choix. * throw exception; */ toastr.error(exception.msg, errorData); @@ -1635,17 +1635,17 @@ Alors que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'a ét } ``` -### Exception Catchers +### Catcher d'Exceptions ###### [Style [Y111](#style-y111)] - - Create a factory that exposes an interface to catch and gracefully handle exceptions. + - Créer une factory qui expose une interface pour attraper et gérer correctement les exceptions. - *Why?*: Provides a consistent way to catch exceptions that may be thrown in your code (e.g. during XHR calls or promise failures). + *Pourquoi ?* : Fournir un moyen cohérent pour gérer les exception qui peuvent être déclenchées dans votre code (par example, pendant un appel Ajax ou lors d'un échec d'une promesse). - Note: The exception catcher is good for catching and reacting to specific exceptions from calls that you know may throw one. For example, when making an XHR call to retrieve data from a remote web service and you want to catch any exceptions from that service and react uniquely. + Note : Le catcher d'axception est bon pour attraper et réagir à des exceptions spécifiques provenant d'appels dont vous savez qu'elles sont déclenchées. Par exemple, lorsque on fait un appel Ajax pour récuppérer des données d'un serveur distant et que vous voulez attraper n'importe quelles exceptions provenant de ce service uniquement et réagir seulement à celui-ci. ```javascript - /* recommended */ + /* recommandé */ angular .module('blocks.exception') .factory('exception', exception); @@ -1666,22 +1666,22 @@ Alors que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'a ét } ``` -### Route Errors +### Erreurs de Routage ###### [Style [Y112](#style-y112)] - - Handle and log all routing errors using [`$routeChangeError`](https://docs.angularjs.org/api/ngRoute/service/$route#$routeChangeError). + - Gérez et loguez toute erreur de routage en utilisant [`$routeChangeError`](https://docs.angularjs.org/api/ngRoute/service/$route#$routeChangeError). - *Why?*: Provides a consistent way handle all routing errors. + *Pourquoi ?* : Fournir un moyen cohérent de gérer les erreurs de routage. - *Why?*: Potentially provides a better user experience if a routing error occurs and you route them to a friendly screen with more details or recovery options. + *Pourquoi ?* : Fournir potentiellement une meilleure expérience utilisateur si une erreur de routage se produit et les rediriger vers un écran convivial avec plus de détails ou les possibilités de s'en sortir. ```javascript - /* recommended */ + /* recommandé */ function handleRoutingErrors() { /** - * Route cancellation: - * On routing error, go to the dashboard. - * Provide an exit clause if it tries to do it twice. + * Annulation du routage: + * Sur une erreur de routage, aller au dashboard. + * Fournir une clause de sortie s'il essaye de le faire deux fois. */ $rootScope.$on('$routeChangeError', function(event, current, previous, rejection) { @@ -1689,8 +1689,8 @@ Alors que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'a ét 'unknown target'; var msg = 'Error routing to ' + destination + '. ' + (rejection.msg || ''); /** - * Optionally log using a custom service or $log. - * (Don't forget to inject custom service) + * Loguer éventuellement en utilisant un service personnalisé ou $log. + * (N'oubliez pas d'injecter votre service personnalisé) */ logger.warning(msg, [current]); } @@ -1698,7 +1698,7 @@ Alors que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'a ét } ``` -**[Back to top](#table-of-contents)** +**[Retour en haut de page](#table-des-matieres)** ## Naming From b8c8246e3da7a281489ee7a90dd3097b0417affb Mon Sep 17 00:00:00 2001 From: Eric Date: Thu, 15 Jan 2015 08:25:46 +0100 Subject: [PATCH 158/567] [FR] Naming --- i18n/fr-FR.md | 106 +++++++++++++++++++++++++------------------------- 1 file changed, 53 insertions(+), 53 deletions(-) diff --git a/i18n/fr-FR.md b/i18n/fr-FR.md index 8b5e9d3e..9b8612aa 100644 --- a/i18n/fr-FR.md +++ b/i18n/fr-FR.md @@ -1700,34 +1700,34 @@ Alors que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'a ét **[Retour en haut de page](#table-des-matieres)** -## Naming +## Nommage -### Naming Guidelines +### Règles de Nommage ###### [Style [Y120](#style-y120)] - - Use consistent names for all components following a pattern that describes the component's feature then (optionally) its type. My recommended pattern is `feature.type.js`. There are 2 names for most assets: - * the file name (`avengers.controller.js`) - * the registered component name with Angular (`AvengersController`) + - Utilisez des noms cohérents pour tous les composants en utilisant un pattern qui décrit la fonctionnalité de ce composant puis (éventuellement) son type. Le pattern que je recommande est `fonctionnalité.type.js`. Il y a 2 noms pour la plupart des resources: + * le nom du fichier (`avengers.controller.js`) + * le nom du composant déclaré à Angular (`AvengersController`) - *Why?*: Naming conventions help provide a consistent way to find content at a glance. Consistency within the project is vital. Consistency with a team is important. Consistency across a company provides tremendous efficiency. + *Pourquoi ?* : Les conventions de nommage donnent une façon cohérente de s'y retrouver en un clin d'oeil. La cohérence dans tout le projet est vitale. La cohérence au sein de l'équipe est importante. La cohérence dans l'entreprise apporte une efficacité redoutable. - *Why?*: The naming conventions should simply help you find your code faster and make it easier to understand. + *Pourquoi ?* : Les conventions de nommage doivent simplement vous aider à naviguer dans le code plus vite et le rendre plus facile à comprendre. -### Feature File Names +### Nom des Fichiers de Fonctionnalités ###### [Style [Y121](#style-y121)] - - Use consistent names for all components following a pattern that describes the component's feature then (optionally) its type. My recommended pattern is `feature.type.js`. + - Utilisez des noms cohérents pour tous les composants qui suivent un pattern qui décrit la fonctionnalité d'un composant et (éventuellent) son type. Le pattern que je recommande est `fonctionnalité.type.js`. - *Why?*: Provides a consistent way to quickly identify components. + *Pourquoi ?* : Offre une façon cohérente d'identifier rapidement les composants. - *Why?*: Provides pattern matching for any automated tasks. + *Pourquoi ?* : Fournit un pattern matching pour automatiser des tâches. ```javascript /** - * common options + * possibilités couramment rencontrées. */ - // Controllers + // Controlleurs avengers.js avengers.controller.js avengersController.js @@ -1740,10 +1740,10 @@ Alors que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'a ét ```javascript /** - * recommended + * recommandé */ - // controllers + // controlleurs avengers.controller.js avengers.controller.spec.js @@ -1751,10 +1751,10 @@ Alors que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'a ét logger.service.js logger.service.spec.js - // constants + // constantes constants.js - // module definition + // definition de module avengers.module.js // routes @@ -1769,29 +1769,29 @@ Alors que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'a ét avenger-profile.directive.spec.js ``` - Note: Another common convention is naming controller files without the word `controller` in the file name such as `avengers.js` instead of `avengers.controller.js`. All other conventions still hold using a suffix of the type. Controllers are the most common type of component so this just saves typing and is still easily identifiable. I recommend you choose 1 convention and be consistent for your team. + Note : Une autre convention courante consiste à nommer les fichiers de controlleurs sans le mot `controller` dans le nom de fichier comme `avengers.js`au lieu de `avengers.controller.js`. Toutes les autres conventions étant maintenues avec un suffixe par type. Les controlleurs étant les les types de composant les plus courants, ça permet d'économiser la frappe au clavier tout en étant facilement identifiable. Je vous conseille de choisir une convention et de vous y tenir dans toute l'équipe. ```javascript /** - * recommended + * recommandé */ - // Controllers + // Controlleurs avengers.js avengers.spec.js ``` -### Test File Names +### Nommage des Fichiers de Test ###### [Style [Y122](#style-y122)] - - Name test specifications similar to the component they test with a suffix of `spec`. + - Les spécifications du nommage des tests est similaire à celui du composant qu'il teste avec un suffixe `spec`. - *Why?*: Provides a consistent way to quickly identify components. + *Pourquoi ?* : Fournit une façon cohérente d'identifier rapidement les composants. - *Why?*: Provides pattern matching for [karma](http://karma-runner.github.io/) or other test runners. + *Pourquoi ?* : Permet le pattern matching pour [karma](http://karma-runner.github.io/) ou d'autres moteurs de tests. ```javascript /** - * recommended + * recommandé */ avengers.controller.spec.js logger.service.spec.js @@ -1799,18 +1799,18 @@ Alors que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'a ét avenger-profile.directive.spec.js ``` -### Controller Names +### Nommage des Controlleurs ###### [Style [Y123](#style-y123)] - - Use consistent names for all controllers named after their feature. Use UpperCamelCase for controllers, as they are constructors. + - Utilisez des noms cohérents pour tous les controlleurs nommés d'après leur fonctionnalité. Utilisez le CamelCaseEnMajuscule, puisque ce sont des constructeurs. - *Why?*: Provides a consistent way to quickly identify and reference controllers. + *Pourquoi ?* : Fournit une façon cohérente d'identifier rapidement et de référencer les controlleurs. - *Why?*: UpperCamelCase is conventional for identifying object that can be instantiated using a constructor. + *Pourquoi ?* : Le CamelCaseEnMajuscules est la convention pour identifier les objets qui peuvent être instanciés avec un controleur. ```javascript /** - * recommended + * recommandé */ // avengers.controller.js @@ -1821,18 +1821,18 @@ Alors que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'a ét function HeroAvengers(){ } ``` -### Controller Name Suffix +### Suffixe des Noms de Controlleurs ###### [Style [Y124](#style-y124)] - - Append the controller name with the suffix `Controller` or with no suffix. Choose 1, not both. + - Ajoutez au nom du controlleur le suffixe ˋControllerˋ ou pas de suffixe du tout. Choississez une des deux conventions, pas les deux à la fois. - *Why?*: The `Controller` suffix is more commonly used and is more explicitly descriptive. + *Pourquoi ?* : Le suffixe ˋControllerˋ est utilisé souvent et il est plus explicitement descriptif. - *Why?*: Omitting the suffix is more succinct and the controller is often easily identifiable even without the suffix. + *Pourquoi ?* : Omettre le suffixe est plus succint et le controlleur est souvent facilement identifiable même sans le suffixe. ```javascript /** - * recommended: Option 1 + * recommandé: Option 1 */ // avengers.controller.js @@ -1845,7 +1845,7 @@ Alors que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'a ét ```javascript /** - * recommended: Option 2 + * recommandé: Option 2 */ // avengers.controller.js @@ -1856,16 +1856,16 @@ Alors que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'a ét function AvengersController(){ } ``` -### Factory Names +### Nommage des Factory ###### [Style [Y125](#style-y125)] - - Use consistent names for all factories named after their feature. Use camel-casing for services and factories. + - Utilisez des noms cohérents pour toutes les foactories nommées d'après la fonctionnalitée. Utilisez le camel-case pour les services et les factories. - *Why?*: Provides a consistent way to quickly identify and reference factories. + *Pourquoi ?* : Fournit une façon cohérente d'identifier rapidement et de référencer les factories. ```javascript /** - * recommended + * recommandé */ // logger.service.js @@ -1876,16 +1876,16 @@ Alors que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'a ét function logger(){ } ``` -### Directive Component Names +### Nommage des Directives de Composants ###### [Style [Y126](#style-y126)] - - Use consistent names for all directives using camel-case. Use a short prefix to describe the area that the directives belong (some example are company prefix or project prefix). + - Utilisez des noms cohérents pour toutes les directives en utilisant le camel-case. Utilisez un préfixe court pour décrire le domaine à laquelle les directives appartiennent (exemples : préfixe de la société ou préfixe du projet). - *Why?*: Provides a consistent way to quickly identify and reference components. + *Pourquoi ?* : Fournit une façon cohérente d'identifier rapidement et de référencer les composants. ```javascript /** - * recommended + * recommandés */ // avenger-profile.directive.js @@ -1893,7 +1893,7 @@ Alors que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'a ét .module .directive('xxAvengerProfile', xxAvengerProfile); - // usage is + // l'usage est function xxAvengerProfile(){ } ``` @@ -1901,27 +1901,27 @@ Alors que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'a ét ### Modules ###### [Style [Y127](#style-y127)] - - When there are multiple modules, the main module file is named `app.module.js` while other dependent modules are named after what they represent. For example, an admin module is named `admin.module.js`. The respective registered module names would be `app` and `admin`. + - Lorqu'il y a de multiples modules, le fichier du module principal est nommé ˋapp.module.jsˋ tandis que les autres modules dépendants sont nommés d'après ce qu'ils représentent. Par exemple, un module d'admin est nommé ˋadmin.module.jsˋ. Les noms des modules déclarés seraient respectivement ˋappˋ et ˋadminˋ. - *Why?*: Provides consistency for multiple module apps, and for expanding to large applications. + *Pourquoi ?* : Fournit de la cohérence pour les applications multi-modules, et pour les applications qui grossissent. - *Why?*: Provides easy way to use task automation to load all module definitions first, then all other angular files (for bundling). + *Pourquoi ?* : Fournit une façon aisée d'utiliser l'automatisation des tâches afin de charger toutes les définitions de modules en premier, puis ensuite tous les autres fichiers angular (pour l'assemblage). ### Configuration ###### [Style [Y128](#style-y128)] - - Separate configuration for a module into its own file named after the module. A configuration file for the main `app` module is named `app.config.js` (or simply `config.js`). A configuration for a module named `admin.module.js` is named `admin.config.js`. + - Séparer la configuration d'un module dans son propre fichier nommé d'après le module. Un fichier de configuration du module principal ˋappˋ est nommé ˋapp.config.jsˋ (ou simplement ˋconfig.jsˋ). Une configuration pour un module nommé ˋadmin.module.jsˋ est nommé ˋadmin.config.jsˋ. - *Why?*: Separates configuration from module definition, components, and active code. + *Pourquoi ?* : Sépare la configuration de la définition du module, du composant et du code actif. - *Why?*: Provides a identifiable place to set configuration for a module. + *Pourquoi ?* : Fournit un endroit bien identifié pour mettre la configuration d'un module. ### Routes ###### [Style [Y129](#style-y129)] - - Separate route configuration into its own file. Examples might be `app.route.js` for the main module and `admin.route.js` for the `admin` module. Even in smaller apps I prefer this separation from the rest of the configuration. + - Séparez la configuration de la route dans son propre fichier. Un exemple pourrait être ˋapp.route.jsˋ pour le module principal et ˋadmin.route.jsˋ pour le module d'ˋadminˋ. Même pour de petites applications, il est préférable de privilégier cette séparation du reste de la configuration. -**[Back to top](#table-of-contents)** +**[Retour en haut de page](#table-des-matières)** ## Application Structure LIFT Principle ### LIFT From 485765d81c9bb9e33f0f24597a5b8a4a53b06b77 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89ric=20Le=20Merdy?= Date: Mon, 26 Jan 2015 08:49:08 +0100 Subject: [PATCH 159/567] [FR] Application Structure LIFT Principle --- i18n/fr-FR.md | 42 +++++++++++++++++++++--------------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/i18n/fr-FR.md b/i18n/fr-FR.md index 9b8612aa..581baea2 100644 --- a/i18n/fr-FR.md +++ b/i18n/fr-FR.md @@ -1923,27 +1923,27 @@ Alors que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'a ét **[Retour en haut de page](#table-des-matières)** -## Application Structure LIFT Principle +## Le Principe LIFT de Structuration de l'Application ### LIFT ###### [Style [Y140](#style-y140)] - - Structure your app such that you can `L`ocate your code quickly, `I`dentify the code at a glance, keep the `F`lattest structure you can, and `T`ry to stay DRY. The structure should follow these 4 basic guidelines. + - Structurez votre application afin de pouvoir `L`ocaliser le code plus rapidement, `I`dentifier le code d'un seul coup, garder la structure la plus platte possible (`F`lattest), et essayez (`T`ry) de rester DRY (Don't Repeat Yourself). La structure doit suivre ces 4 règles de bases. - *Why LIFT?*: Provides a consistent structure that scales well, is modular, and makes it easier to increase developer efficiency by finding code quickly. Another way to check your app structure is to ask yourself: How quickly can you open and work in all of the related files for a feature? + *Pourquoi LIFT ?* : Fournit une structure cohérente qui passe bien à l'échelle, qui est modulaire, et facilite l'augmentation de l'efficacité du développeur. Une autre façon de valider la structure de votre application est de vous demander : à quelle vitesse vous pouvez ouvrir et travailler dans tous les fichiés liés à une fonctionnalité ? - When I find my structure is not feeling comfortable, I go back and revisit these LIFT guidelines + Lorsque je trouve que ma structure n'est pas confortable, je reviens en arrière et je revisite les règles LIFT. - 1. `L`ocating our code is easy - 2. `I`dentify code at a glance - 3. `F`lat structure as long as we can - 4. `T`ry to stay DRY (Don’t Repeat Yourself) or T-DRY + 1. `L`ocaliser le code est facile + 2. `I`dentifier le code d'un coup + 3. `F`lat (platte) structure autant que possible + 4. `T`ry (essayer) de rester DRY (Don’t Repeat Yourself, Ne Pas Se Répéter) ou T-DRY -### Locate +### Localisation ###### [Style [Y141](#style-y141)] - - Make locating your code intuitive, simple and fast. + - Rendez la localisation du code intuitive, simple et rapide. - *Why?*: I find this to be super important for a project. If the team cannot find the files they need to work on quickly, they will not be able to work as efficiently as possible, and the structure needs to change. You may not know the file name or where its related files are, so putting them in the most intuitive locations and near each other saves a ton of time. A descriptive folder structure can help with this. + *Pourquoi ?* : Je trouve que c'est super important pour un projet. Si l'équipe ne peut pas trouver rapidement les fichiers sur lesquels elle doit travailler, ils ne vont pas être en mesure de travailler aussi efficacement que possible, et la structure devra changer. Vous ne connaissez peut-être pas le nom du fichier où la position des fichiers liés, alors les placer dans les endroits les plus intuitifs et proches les uns les autres permet de gagner un paquet de temps. Une structure de répertoire descriptive peut aider à ça. ``` /bower_components @@ -1963,28 +1963,28 @@ Alors que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'a ét .bower.json ``` -### Identify +### Identification ###### [Style [Y142](#style-y142)] - - When you look at a file you should instantly know what it contains and represents. + - Lorsque vous regardez un fichier vous devriez instantanément savoir ce qu'il contient ce qu'il représente. - *Why?*: You spend less time hunting and pecking for code, and become more efficient. If this means you want longer file names, then so be it. Be descriptive with file names and keeping the contents of the file to exactly 1 component. Avoid files with multiple controllers, multiple services, or a mixture. There are deviations of the 1 per file rule when I have a set of very small features that are all related to each other, they are still easily identifiable. + *Pourquoi ?* : Vous passez moins de temps à fouiller et vous perdre pour cherche le code, et devenez de plus en plus efficient. Si ça implique des noms de fichier plus long, alors d'accord. Soyez descriptif avec les noms de fichier et leur contenu ne doit contenir exactement qu'un seul composant. Éviter les fichier avec plusieurs controlleurs, plusieurs services, ou un mélange. On pourrait admettre une exception à cette règle si j'ai un ensemble de fonctionnalités très petites qui sont toutes reliées entre elles, elles sont toujours facilement identifiables. -### Flat +### Plat ###### [Style [Y143](#style-y143)] - - Keep a flat folder structure as long as possible. When you get to 7+ files, begin considering separation. + - Gardez une structure de répertoire à plat le plus longtemps possible. Lorsque vous avez 7 fichiers ou plus, commencez à penser à séparer. - *Why?*: Nobody wants to search 7 levels of folders to find a file. Think about menus on web sites … anything deeper than 2 should take serious consideration. In a folder structure there is no hard and fast number rule, but when a folder has 7-10 files, that may be time to create subfolders. Base it on your comfort level. Use a flatter structure until there is an obvious value (to help the rest of LIFT) in creating a new folder. + *Pourquoi ?* : Personne ne souhaite rechercher dans 7 niveaux de répertoires pour trouver un fichier. Pensez aux menus des sites web… rien de plus profond que 2 niveaux ne devrait être sérieursement pris en considération. Dans une structure de répertoire, il n'y a pas de nombre d'or, mais lorsqu'un répertoire à entre 7 et 10 fichiers, il serait temps de créer des sous-répertoires. Basez cela sur votre niveau de confort. Utilisez une structure plus plate jusqu'à ce qu'il y ait un évident intérêt (pour respecter les autres principes LIFT) à créer un sous-répertoire. -### T-DRY (Try to Stick to DRY) +### T-DRY (Essayer de respecter DRY) ###### [Style [Y144](#style-y144)] - - Be DRY, but don't go nuts and sacrifice readability. + - Ne vous répétez pas (DRY), mais pas bêtement à tout prix ni en sacrifiant la lisibilité. - *Why?*: Being DRY is important, but not crucial if it sacrifices the others in LIFT, which is why I call it T-DRY. I don’t want to type session-view.html for a view because, well, it’s obviously a view. If it is not obvious or by convention, then I name it. + *Pourquoi ?* : Ne pas se répéter (DRY) est important, mais pas cricial si vous en êtesréduit à sacrifier les autres principes LIFT, c'est que qu'on peut appeller T-DRY (Essayer de ne pas se répéter). Je ne voudrai pas écrire session-view.html pour une vue, parce que, c'est évidemment une vue. Si ce n'est pas évident ou par convention, alors nommez-le. -**[Back to top](#table-of-contents)** +**[Retour en haut de page](#table-des-matières)** ## Application Structure From 199b272c2041f307c9e162b74b102199d96e226c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89ric=20Le=20Merdy?= Date: Tue, 27 Jan 2015 19:17:57 +0100 Subject: [PATCH 160/567] [FR] Application Structure --- i18n/fr-FR.md | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/i18n/fr-FR.md b/i18n/fr-FR.md index 581baea2..70e3baef 100644 --- a/i18n/fr-FR.md +++ b/i18n/fr-FR.md @@ -1986,38 +1986,38 @@ Alors que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'a ét **[Retour en haut de page](#table-des-matières)** -## Application Structure +## Structure de l'Application -### Overall Guidelines +### Règles Générales ###### [Style [Y150](#style-y150)] - - Have a near term view of implementation and a long term vision. In other words, start small and but keep in mind on where the app is heading down the road. All of the app's code goes in a root folder named `app`. All content is 1 feature per file. Each controller, service, module, view is in its own file. All 3rd party vendor scripts are stored in another root folder and not in the `app` folder. I didn't write them and I don't want them cluttering my app (`bower_components`, `scripts`, `lib`). + - Vous devez avoir une vue court terme et une vision à long terme. En d'autres mots, commencez petit et garder en tête là où en est votre application. Tout le code de l'appli va dans un répertoire racine nommé `app`. Tout contenu fonctionnel doit être rangé dans son propre fichier. Chaque controlleur, service, module, vue doit avoir son propre fichier. Tous les scripts provenant de fournisseurs extérieurs doivent être rangés dans un autre répertoire racine et non dans le répertoire `app`. Le code que l'on écrit pas soi-même ne doit pas se mélanger avec son appli (`bower_components`, `script`, `lib`). - Note: Find more details and reasoning behind the structure at [this original post on application structure](http://www.johnpapa.net/angular-app-structuring-guidelines/). + Note : Vous trouverez plus de détails et les justifications derrière la structure sur [ce post original sur la structure des applications](http://www.johnpapa.net/angular-app-structuring-guidelines/). ### Layout ###### [Style [Y151](#style-y151)] - - Place components that define the overall layout of the application in a folder named `layout`. These may include a shell view and controller may act as the container for the app, navigation, menus, content areas, and other regions. + - Placez les composants qui définissent le layout principal de l'application dans un répertoire nommé `layout`. Il devrait inclure une vue noyau et le controlleur devrait agir comme conteneur pour l'appli, la nivigation, les menus, les zones de contenu, et les autres régions. - *Why?*: Organizes all layout in a single place re-used throughout the application. + *Pourquoi ?* : Organise tout le layout à un seul endroit réutilisé dans l'application. -### Folders-by-Feature Structure +### Structure en Répertoires-par-Fonctionnalités ###### [Style [Y152](#style-y152)] - - Create folders named for the feature they represent. When a folder grows to contain more than 7 files, start to consider creating a folder for them. Your threshold may be different, so adjust as needed. + - Créez des répertoires nommés d'après les fonctionnalités qu'elles représentent. Lorsqu'un répertoire grossit jusqu'à atteindre plus de 7 fichiers, commencez à penser la création d'un répertoire pour ceux-ci. Si votre seuil est différent, ajustez-le au besoin. - *Why?*: A developer can locate the code, identify what each file represents at a glance, the structure is flat as can be, and there is no repetitive nor redundant names. + *Pourquoi ?* : Un développeur peut localiser, identifier ce que représente chaque fichier en sune seule fois, la structure est aussi plate que possible, et il n'y a ni répétitions ni noms redondants. - *Why?*: The LIFT guidelines are all covered. + *Pourquoi ?* : Les règles LIFT sont toutes couvertes. - *Why?*: Helps reduce the app from becoming cluttered through organizing the content and keeping them aligned with the LIFT guidelines. + *Pourquoi ?* : Aide à diminuer l'entropie de l'appli en organizant le contenu et en le maintenant aligné avec les principes LIFT. - *Why?*: When there are a lot of files (10+) locating them is easier with a consistent folder structures and more difficult in flat structures. + *Pourquoi ?* : Lorsqu'il y a de nombreux fichiers (+ de 10) les repérer est plus facile avec une structure de répertoires cohérente et plus difficile dans une structure à plat. ```javascript /** - * recommended + * recommandé */ app/ @@ -2053,15 +2053,15 @@ Alors que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'a ét session-detail.controller.js ``` - ![Sample App Structure](https://raw.githubusercontent.com/johnpapa/angularjs-styleguide/master/assets/modularity-2.png) + ![Structure d'une Appli Exemple](https://raw.githubusercontent.com/johnpapa/angularjs-styleguide/master/assets/modularity-2.png) - Note: Do not use structuring using folders-by-type. This requires moving to multiple folders when working on a feature and gets unwieldy quickly as the app grows to 5, 10 or 25+ views and controllers (and other features), which makes it more difficult than folder-by-feature to locate files. + Note : N'utilisez pas une structuration de répertoires-par-type. Cela requiert de se déplacer entre de multiples répertoires lorsqu'on travaille sur une fonctionnalité et cela devient rapidement difficile à manier lorsque l'application grossit à 5, 10 ou plus de 25 vues et controlleurs (et autres), ce qui complique la localisation par rapport à des répertoires-par-fonctionnalité. ```javascript /* - * avoid - * Alternative folders-by-type. - * I recommend "folders-by-feature", instead. + * à éviter + * Trouver une alternative aux répertoires-par-type. + * Je vous conseille les "répertoires-par-fonctionnalité", à la place. */ app/ @@ -2096,7 +2096,7 @@ Alors que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'a ét topnav.html ``` -**[Back to top](#table-of-contents)** +**[Retour en haut de page](#table-des-matières)** ## Modularity From 15bc761576aaee4cc4a5150f013dbcd31901e13f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89ric=20Le=20Merdy?= Date: Tue, 27 Jan 2015 23:54:13 +0100 Subject: [PATCH 161/567] [FR] Modularity --- i18n/fr-FR.md | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/i18n/fr-FR.md b/i18n/fr-FR.md index 70e3baef..a13cd39d 100644 --- a/i18n/fr-FR.md +++ b/i18n/fr-FR.md @@ -2098,30 +2098,30 @@ Alors que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'a ét **[Retour en haut de page](#table-des-matières)** -## Modularity +## Modularité -### Many Small, Self Contained Modules +### De Nombreux Petits Modules Auto-Suffisants ###### [Style [Y160](#style-y160)] - - Create small modules that encapsulate one responsibility. + - Créez de petits modules qui encapsulent une responsabilité. - *Why?*: Modular applications make it easy to plug and go as they allow the development teams to build vertical slices of the applications and roll out incrementally. This means we can plug in new features as we develop them. + *Pourquoi ?* : Les Applications modulaires rendent faciles le branchement rapide puisqu'elles permettent aux équipes de développement de construire des sections verticales de l'application et de livrer incrémentalement. Cela signifie que nous pouvons brancher de nouvelles fonctionnalités à mesure que nous les développons. -### Create an App Module +### Création d'un Module Applicatif ###### [Style [Y161](#style-y161)] - - Create an application root module whose role is pull together all of the modules and features of your application. Name this for your application. + - Créez un module racine pour l'application dont le rôle est d'assembler tous les modules et fonctionnalités de votre application. Nommez-le comme votre application. - *Why?*: AngularJS encourages modularity and separation patterns. Creating an application root module whose role is to tie your other modules together provides a very straightforward way to add or remove modules from your application. + *Pourquoi ?* : AngularJS encourage la modularité et la séparation des responsabilités. La création d'un module racine pour l'application dont le rôle est de lier ensemble les autres modules fournit un moyen très direct d'ajouter et de retirer des modules à votre application. -### Keep the App Module Thin +### Garder le Module Applicatif Léger ###### [Style [Y162](#style-y162)] - - Only put logic for pulling together the app in the application module. Leave features in their own modules. + - Ne placez dans le module applicatif que la logique d'assemblage de l'application. Laissez les fonctionnalités dans leurs propres modules. - *Why?*: Adding additional roles to the application root to get remote data, display views, or other logic not related to pulling the app together muddies the app module and make both sets of features harder to reuse or turn off. + *Pourquoi ?* : Ajouter des responsabilités supplémentaires à l'application racine pour récupérer des données, afficher des vues, ou toute autre logique non reliée à l'assemblage de l'application trouble le module applicatif rend plus difficile à réutiliser ou éteindre les ensembles de fonctionnalités. - *Why?*: The app module becomes a manifest that describes which modules help define the application. + *Pourquoi ?* : Le module applicatif devient une déclaration qui montre quels modules aident à constituer l'application. ### Feature Areas are Modules ###### [Style [Y163](#style-y163)] From c96e0e40e9617fedd0be60715576b12d1384b2e0 Mon Sep 17 00:00:00 2001 From: Eric Date: Thu, 29 Jan 2015 22:56:05 +0100 Subject: [PATCH 162/567] [FR] Modules --- i18n/fr-FR.md | 40 ++++++++++++++++++++-------------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/i18n/fr-FR.md b/i18n/fr-FR.md index a13cd39d..22334599 100644 --- a/i18n/fr-FR.md +++ b/i18n/fr-FR.md @@ -1,12 +1,12 @@ -# Le Guide Stylistique AngularJS +# Le Guide de Style AngularJS -*Le guide d'un certain point de vue stylistique sur AngularJS par [@john_papa](//twitter.com/john_papa)* +*Le guide d'un point de vue personnel sur le style AngularJS par [@john_papa](//twitter.com/john_papa)* -Si vous cherchez un guide d'un certain point de vue stylistique pour la syntaxe, les conventions, et la structuration d'application AngularJS, alors vous êtes au bon endroit. Ces styles sont basés sur mon expérience de dévelopement avec [AngularJS](//angularjs.org), mes présentations, [mes cours sur Pluralsight](http://pluralsight.com/training/Authors/Details/john-papa) et mon travail au sein des équipes. +Si vous cherchez un guide de style pour la syntaxe, les conventions, et la structuration d'application AngularJS, alors vous êtes au bon endroit. Ces styles sont basés sur mon expérience de dévelopement avec [AngularJS](//angularjs.org), mes présentations, [mes cours sur Pluralsight](http://pluralsight.com/training/Authors/Details/john-papa) et mon travail au sein des équipes. >Si vous appréciez ce guide, visitez mon cours [AngularJS Patterns: Clean Code](http://jpapa.me/ngclean) sur Pluralsight. -Le but de ce guide stylistique est de proposer des conseils sur le développement d'applications AngularJS en montrant les conventions que j'utilise et, plus important encore, les raisons des choix que j'ai pris. +Le but de ce guide de style est de proposer des conseils sur le développement d'applications AngularJS en montrant les conventions que j'utilise et, plus important encore, les raisons des choix que j'ai pris. ## Supprématie de la Communauté et Remerciements Ne jamais travailler dans le vide. J'ai trouvé que la communauté AngularJS est un incroyable groupe dont les membres ont à coeur de partager leurs expériences. Ainsi, un ami et expert AngularJS Todd Motto et moi avons collaboré sur de nombreux styles et conventions. Nous sommes d'accord sur la plupart, et nous divergeons sur d'autres. Je vous encourage à visiter [les guideslines de Todd](https://github.com/toddmotto/angularjs-styleguide) pour vous faire un sentiment sur son approche et en quoi elle est comparable. @@ -2123,42 +2123,42 @@ Alors que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'a ét *Pourquoi ?* : Le module applicatif devient une déclaration qui montre quels modules aident à constituer l'application. -### Feature Areas are Modules +### Les Macro Fonctionnalités en tant que Modules ###### [Style [Y163](#style-y163)] - - Create modules that represent feature areas, such as layout, reusable and shared services, dashboards, and app specific features (e.g. customers, admin, sales). + - Créez des modules qui représentent des macro fonctionnalités, comme le layout, les services ré-utilisables et partagés, les dashboards, et les fonctionnalités applicatives spécifiques (par exemple : clients, admin, ventes). - *Why?*: Self contained modules can be added to the application with little or no friction. + *Pourquoi ?* : Les modules auto-suffisants peuvent être ajoutés à l'application avec peu ou pas de friction. - *Why?*: Sprints or iterations can focus on feature areas and turn them on at the end of the sprint or iteration. + *Pourquoi ?* : Les sprints ou itérations peuvent se focaliser sur les macro-fonctionnalités et les activer à la fin de l'itération. - *Why?*: Separating feature areas into modules makes it easier to test the modules in isolation and reuse code. + *Pourquoi ?* : Séparer les macros-fonctionnalités rend plus facile les tests des modules en isolation et la réutilisation du code. -### Reusable Blocks are Modules +### Les Blocks Ré-Utilisables en tant que Modules ###### [Style [Y164](#style-y164)] - - Create modules that represent reusable application blocks for common services such as exception handling, logging, diagnostics, security, and local data stashing. + - Créez des modules qui représentent des blocs d'application ré-utilisables pour les services en commun tels que la gestion d'exceptions, les logs, les diagnostics, la sécurité et la gestion des données en locale. - *Why?*: These types of features are needed in many applications, so by keeping them separated in their own modules they can be application generic and be reused across applications. + *Pourquoi ?* : Ces types de fonctinnalités sont requises dans de nombreuses application, donc en les gardant séparées dans leur propres modules elles peuvent être génériques par rapport aux applications et peuvent être ré-utilisées pour d'autres applications. -### Module Dependencies +### Dependences Entre Modules ###### [Style [Y165](#style-y165)] - - The application root module depends on the app specific feature modules and any shared or reusable modules. + - Le module racine de l'application dépend des modules des fonctionnalités spécifiques et de certains modules partagés et ré-utilisables. ![Modularity and Dependencies](https://raw.githubusercontent.com/johnpapa/angularjs-styleguide/master/assets/modularity-1.png) - *Why?*: The main app module contains a quickly identifiable manifest of the application's features. + *Pourquoi?* : Le module principal de l'appli continent une déclaration rapidement identifible des fonctionnalités de l'application. - *Why?*: Each feature area contains a manifest of what it depends on, so it can be pulled in as a dependency in other applications and still work. + *Pourquoi ?* : Chaque groupe de fonctionnalité contient une déclaration de ce dont il dépend, de ce fait il peut être tiré comme dépendance dans d'autres applications et continuer à fonctionner. - *Why?*: Intra-App features such as shared data services become easy to locate and share from within `app.core` (choose your favorite name for this module). + *Pourquoi ?* : Les fonctionalités propres à l'appli tels que les services de données partagées deviennent faciles à repérer et partager au sein d'un `app.core` (choisissez un nom de votre choix pour ce module. - Note: This is a strategy for consistency. There are many good options here. Choose one that is consistent, follows AngularJS's dependency rules, and is easy to maintain and scale. + Note : C'est un stratégie pour la cohérence. Il y a ici beaucoup de bons choix. Choisisez-en une qui soit cohérente, suivez les règles des dépendances d'AngularJS, et la maintenance et la montée en charge sera facilitée. - > My structures vary slightly between projects but they all follow these guidelines for structure and modularity. The implementation may vary depending on the features and the team. In other words, don't get hung up on an exact like-for-like structure but do justify your structure using consistency, maintainability, and efficiency in mind. + > Mes structures peuvent varier légèrement entre les projets mais elles suivent toutes ces règles pour la structure et la modularité. L'implémentation peut varier en fonction des fonctionnalités et de l'équipe. En d'autres termes, ne vous paralysez pas sur une structure exactement semblable mais soumettez votre structure aux critères de cohérence, maintenance, et efficacité. - > In a small app, you can also consider putting all the shared dependencies in the app module where the feature modules have no direct dependencies. This makes it easier to maintain the smaller application, but makes it harder to reuse modules outside of this application. + > Dans de petites applic, vous pouvez aussi mettre toutes vos dépendances partagées dans le module applicatif où les modules fonctionnels n'ont pas de dépendances directes. Cela pourra rendre la maintenance de cette petite application plus facile, mais rendez difficile la ré-utilisation de ces modules en dehors de cette application. **[Back to top](#table-of-contents)** From b47d01ff6cc3463d59d88b4e3e3f68469436345e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89ric=20Le=20Merdy?= Date: Tue, 3 Feb 2015 21:03:15 +0100 Subject: [PATCH 163/567] [FR] Startup logic --- i18n/fr-FR.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/i18n/fr-FR.md b/i18n/fr-FR.md index 22334599..9ca747ba 100644 --- a/i18n/fr-FR.md +++ b/i18n/fr-FR.md @@ -2162,14 +2162,14 @@ Alors que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'a ét **[Back to top](#table-of-contents)** -## Startup Logic +## Logique de Démarrage ### Configuration ###### [Style [Y170](#style-y170)] - - Inject code into [module configuration](https://docs.angularjs.org/guide/module#module-loading-dependencies) that must be configured before running the angular app. Ideal candidaes include providers and constants. + - Injectez le code à l'intérieur d'une [configuration de module](https://docs.angularjs.org/guide/module#module-loading-dependencies) qui doit être configuré avant l'éxécution de l'appli angular. Parmis les candidats idéaux, on trouve les providers et les constantes. - *Why?*: This makes it easier to have a less places for configuration. + *Pourquoi ?* : Ça rend les choses plus faciles d'avoir le moins d'endroits possible pour placer la configuration. ```javascript angular @@ -2196,12 +2196,12 @@ Alors que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'a ét } ``` -### Run Blocks +### Blocs Run ###### [Style [Y171](#style-y171)] - - Any code that needs to run when an application starts should be declared in a factory, exposed via a function, and injected into the [run block](https://docs.angularjs.org/guide/module#module-loading-dependencies). + - Tout code qui nécessite de s'éxécuter lorsque l'application démarre devrait être déclaré dans une factory, exposé via une fonction, et injecté dans un [bloc run](https://docs.angularjs.org/guide/module#module-loading-dependencies). - *Why?*: Code directly in a run block can be difficult to test. Placing in a factory makes it easier to abstract and mock. + *Pourquoi ?* : Le code écrit directement dans un bloc run peut être difficile à tester. Le placer dans une factory le rend plus facile à abstraire et mocker. ```javascript angular @@ -2216,7 +2216,7 @@ Alors que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'a ét } ``` -**[Back to top](#table-of-contents)** +**[Retour en haut de page](#table-des-matières)** ## Angular $ Wrapper Services From 84d96dd962c6ac35fa2e216cc382f0a3caf6fb54 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89ric=20Le=20Merdy?= Date: Tue, 3 Feb 2015 21:14:14 +0100 Subject: [PATCH 164/567] [FR] Angular $ Wrapper Services --- i18n/fr-FR.md | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/i18n/fr-FR.md b/i18n/fr-FR.md index 9ca747ba..f5783a3c 100644 --- a/i18n/fr-FR.md +++ b/i18n/fr-FR.md @@ -2218,23 +2218,23 @@ Alors que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'a ét **[Retour en haut de page](#table-des-matières)** -## Angular $ Wrapper Services +## Les Services de Wrapper $ de Angular -### $document and $window +### $document et $window ###### [Style [Y180](#style-y180)] - - Use [`$document`](https://docs.angularjs.org/api/ng/service/$document) and [`$window`](https://docs.angularjs.org/api/ng/service/$window) instead of `document` and `window`. + - Utilisez [`$document`](https://docs.angularjs.org/api/ng/service/$document) et [`$window`](https://docs.angularjs.org/api/ng/service/$window) au lieu de `document` et `window`. - *Why?*: These services are wrapped by Angular and more easily testable than using document and window in tests. This helps you avoid having to mock document and window yourself. + *Pourquoi ?* : Ces services sont wrappés par Angular et plus facilement testables qu'en utilisant document et window dans les tests. Ils vous aident à éviter d'avoir à mocker document et window vous-même. -### $timeout and $interval +### $timeout et $interval ###### [Style [Y181](#style-y181)] - - Use [`$timeout`](https://docs.angularjs.org/api/ng/service/$timeout) and [`$interval`](https://docs.angularjs.org/api/ng/service/$interval) instead of `setTimeout` and `setInterval` . + - Utilisez [`$timeout`](https://docs.angularjs.org/api/ng/service/$timeout) et [`$interval`](https://docs.angularjs.org/api/ng/service/$interval) au lieu de `setTimeout` et `setInterval`. - *Why?*: These services are wrapped by Angular and more easily testable and handle AngularJS's digest cycle thus keeping data binding in sync. + *Pourquoi ?* : Ces services sont wrappés par Angular et plus facilement testables et gèrent le cycle de digest d'AngularJS conservant un data binding à jour. -**[Back to top](#table-of-contents)** +**[Retour en haut de page](#table-des-matières)** ## Testing Unit testing helps maintain clean code, as such I included some of my recommendations for unit testing foundations with links for more information. From 1ff9ed7da484271b5f6b0bbeaefe1c7505fd3cdd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89ric=20Le=20Merdy?= Date: Wed, 4 Feb 2015 07:57:24 +0100 Subject: [PATCH 165/567] [FR] Testing --- i18n/fr-FR.md | 48 ++++++++++++++++++++++++------------------------ 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/i18n/fr-FR.md b/i18n/fr-FR.md index f5783a3c..d12bd87f 100644 --- a/i18n/fr-FR.md +++ b/i18n/fr-FR.md @@ -2236,15 +2236,15 @@ Alors que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'a ét **[Retour en haut de page](#table-des-matières)** -## Testing -Unit testing helps maintain clean code, as such I included some of my recommendations for unit testing foundations with links for more information. +## Le Test +Les tests unitaires aident à maintenir un code propre, ainsi, j'ai inclu quelques unes de mes recommandations sur les fondamentaux du test unitaire avec des liens pour plus déinformation. -### Write Tests with Stories +### Écriture des Tests avec les Stories ###### [Style [Y190](#style-y190)] - - Write a set of tests for every story. Start with an empty test and fill them in as you write the code for the story. + - Écrivez un ensemble de tests pour chaque story. Commencer avec un test vide et complétez-les à mesure que vous écrivez le code pour la story. - *Why?*: Writing the test descriptions helps clearly define what your story will do, will not do, and how you can measure success. + *Pourquoi ?* : Écrire les descriptions de tests aident à définir clairement ce que votre story devra faire, ne devra pas faire et comment mesurer l'avancement. ```javascript it('should have Avengers controller', function() { @@ -2263,48 +2263,48 @@ Unit testing helps maintain clean code, as such I included some of my recommenda //TODO ($httpBackend?) }); - // and so on + // et ainsi de suite ``` -### Testing Library +### Librairie de Test ###### [Style [Y191](#style-y191)] - - Use [Jasmine](http://jasmine.github.io/) or [Mocha](http://visionmedia.github.io/mocha/) for unit testing. + - Utilisez [Jasmine](http://jasmine.github.io/) or [Mocha](http://visionmedia.github.io/mocha/) pour les tests unitaires. - *Why?*: Both Jasmine and Mocha are widely used in the AngularJS community. Both are stable, well maintained, and provide robust testing features. + *Pourquoi ?* : Jasmine et Mocha sont toutes deux largement utilisées dans la communauté AngularJS. Toutes les deux stables, bien maintenues, et fournissant des fonctionnalités robustes de test. - Note: When using Mocha, also consider choosing an assert library such as [Chai](http://chaijs.com). + Note : Lorsque vous utilisez Mocha, utilisez aussi une librairie d'assertion telle que [Chai](http://chaijs.com). -### Test Runner +### Lanceur de Test ###### [Style [Y192](#style-y192)] - - Use [Karma](http://karma-runner.github.io) as a test runner. + - Utilisez [Karma](http://karma-runner.github.io) comme lanceur de test. - *Why?*: Karma is easy to configure to run once or automatically when you change your code. + *Pourquoi ?* : Karma est facile à configurer pour lancer les tests une fois ou automatiquement lorsqu'un changement est fait dans le code. - *Why?*: Karma hooks into your Continuous Integration process easily on its own or through Grunt or Gulp. + *Pourquoi ?* : Karma s'intègre facilement dans votre processus d'Intégration Continue soit tout seul ou par Grunt ou Gulp. - *Why?*: Some IDE's are beginning to integrate with Karma, such as [WebStorm](http://www.jetbrains.com/webstorm/) and [Visual Studio](http://visualstudiogallery.msdn.microsoft.com/02f47876-0e7a-4f6c-93f8-1af5d5189225). + *Pourquoi ?* : Quelques EDI commencent à s'intégrer avec Karma, c'est le cas de [WebStorm](http://www.jetbrains.com/webstorm/) et [Visual Studio](http://visualstudiogallery.msdn.microsoft.com/02f47876-0e7a-4f6c-93f8-1af5d5189225). - *Why?*: Karma works well with task automation leaders such as [Grunt](http://www.gruntjs.com) (with [grunt-karma](https://github.com/karma-runner/grunt-karma)) and [Gulp](http://www.gulpjs.com) (with [gulp-karma](https://github.com/lazd/gulp-karma)). + *Pourquoi ?* : Karma fonctionne bien avec les leaders de l'automatisation de tâches tel que [Grunt](http://www.gruntjs.com) (avec [grunt-karma](https://github.com/karma-runner/grunt-karma)) ou [Gulp](http://www.gulpjs.com) (avec [gulp-karma](https://github.com/lazd/gulp-karma)). -### Stubbing and Spying +### Les Stubs et les Spy ###### [Style [Y193](#style-y193)] - - Use Sinon for stubbing and spying. + - Utilisez Sinon pour les stubs et les spy. - *Why?*: Sinon works well with both Jasmine and Mocha and extends the stubbing and spying features they offer. + *Pourquoi ?* : Sinon fonctionne bien avec Jasmine et Mocha et étend les fonctionnalités de stub et de spy qu'ils offrent. - *Why?*: Sinon makes it easier to toggle between Jasmine and Mocha, if you want to try both. + *Pourquoi ?* : Sinon rend plus facile l'alternance entre Jasmine et Mocha, si vous voulez essayer les deux. -### Headless Browser +### Navigateur sans Interface Graphique ###### [Style [Y194](#style-y194)] - - Use [PhantomJS](http://phantomjs.org/) to run your tests on a server. + - Utilisez [PhantomJS](http://phantomjs.org/) pour éxécuter les tests sur un serveur. - *Why?*: PhantomJS is a headless browser that helps run your tests without needing a "visual" browser. So you do not have to install Chrome, Safari, IE, or other browsers on your server. + *Pourquoi?* : PhantomJS est un navigateur sans interface graphique qui peut vous aider à éxécuter les tests sans avoir besoin d'un navigateur "visuel". Ainsi vous n'avez pas besoin d'installer Chrome, Safari, IE, ou d'autres navigateurs sur votre serveur. - Note: You should still test on all browsers in your environment, as appropriate for your target audience. + Note : Que cela ne vous dispense pas de tester sur tous les navigateurs dans votre environnement, d'après les clients que vous ciblez. ### Code Analysis ###### [Style [Y195](#style-y195)] From fd13248161fd7820d34d0aded640bc76d8afdca1 Mon Sep 17 00:00:00 2001 From: Eric Date: Sat, 7 Feb 2015 21:22:01 +0100 Subject: [PATCH 166/567] [FR] Code analysis --- i18n/fr-FR.md | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/i18n/fr-FR.md b/i18n/fr-FR.md index d12bd87f..35578438 100644 --- a/i18n/fr-FR.md +++ b/i18n/fr-FR.md @@ -2306,27 +2306,27 @@ Les tests unitaires aident à maintenir un code propre, ainsi, j'ai inclu quelqu Note : Que cela ne vous dispense pas de tester sur tous les navigateurs dans votre environnement, d'après les clients que vous ciblez. -### Code Analysis +### Analyse de Code ###### [Style [Y195](#style-y195)] - - Run JSHint on your tests. + - Exécutez JSHint sur vos tests. - *Why?*: Tests are code. JSHint can help identify code quality issues that may cause the test to work improperly. + *Pourquoi ?* : Les tests sont du code. JSHint peut vous aider à identifier les problèmes de qualité de code qui pourrait amener les tests à fonctionner de façon incorrecte. -### Alleviate Globals for JSHint Rules on Tests +### Atténuation des Règles JSHint avec les Golbales sur les Tests ###### [Style [Y196](#style-y196)] - - Relax the rules on your test code to allow for common globals such as `describe` and `expect`. + - Relaxez les règles sur votre code de test afin de permettre l'usage des globales telles que `describe` et `expect`. - *Why?*: Your tests are code and require the same attention and code quality rules as all of your production code. However, global variables used by the testing framework, for example, can be relaxed by including this in your test specs. + *Pourquoi ?* : Vos tests sont du code et requièrent à ce titre la même attention avec les mêmes règles de qualité de code que votre code de production. Cependant, les variables globales utilisées par les frameworks de test, par exemple, peuvent être relaxées en les incluants dans les spécifications de test. ```javascript /* global sinon, describe, it, afterEach, beforeEach, expect, inject */ ``` - ![Testing Tools](https://raw.githubusercontent.com/johnpapa/angularjs-styleguide/master/assets/testing-tools.png) + ![Outils de Test](https://raw.githubusercontent.com/johnpapa/angularjs-styleguide/master/assets/testing-tools.png) -**[Back to top](#table-of-contents)** +**[Retour en haut de page](#table-des-matières)** ## Animations From 8392de98ff5d01a5e65f115cec61e8c967fcd976 Mon Sep 17 00:00:00 2001 From: Eric Date: Sun, 8 Feb 2015 18:53:57 +0100 Subject: [PATCH 167/567] [FR] Animations --- i18n/fr-FR.md | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/i18n/fr-FR.md b/i18n/fr-FR.md index 35578438..a736e28e 100644 --- a/i18n/fr-FR.md +++ b/i18n/fr-FR.md @@ -2330,36 +2330,36 @@ Les tests unitaires aident à maintenir un code propre, ainsi, j'ai inclu quelqu ## Animations -### Usage +### Utilisation ###### [Style [Y210](#style-y210)] - - Use subtle [animations with AngularJS](https://docs.angularjs.org/guide/animations) to transition between states for views and primary visual elements. Include the [ngAnimate module](https://docs.angularjs.org/api/ngAnimate). The 3 keys are subtle, smooth, seamless. + - Utilisez de subtiles [animations avec AngularJS](https://docs.angularjs.org/guide/animations) pour la transition entre les états pour les vues et les éléments visuels premiers. Incluez le [module ngAnimate](https://docs.angularjs.org/api/ngAnimate). Les trois clés sont la subtilité, la fluidité, l'homogénéïté. - *Why?*: Subtle animations can improve User Experience when used appropriately. + *Pourquoi ?* : Des animations subtiles peuvent améliorer l'Expérience Utilisateur lorsqu'elles sont utilisées de façon appropriéés. - *Why?*: Subtle animations can improve perceived performance as views transition. + *Pourquoi ?* : Des animations subtiles peuvent améliorer la performance perçue lorsque les vues changent. -### Sub Second +### Moins d'une Seconde ###### [Style [Y211](#style-y211)] - - Use short durations for animations. I generally start with 300ms and adjust until appropriate. + - Utilisez de courtes durées pour les animations. Je commence en général par 300 milli secondes et j'ajuste jusqu'à ce que ce soit bien. - *Why?*: Long animations can have the reverse affect on User Experience and perceived performance by giving the appearance of a slow application. + *Pourquoi ?* : Les animations longues peuvent avoir un effet inverse sur l'Expérience Utilisateur et la performance perçue en donnant l'apparence d'une application lente. ### animate.css ###### [Style [Y212](#style-y212)] - - Use [animate.css](http://daneden.github.io/animate.css/) for conventional animations. + - Utilisez [animate.css](http://daneden.github.io/animate.css/) pour les animations conventionnelles. - *Why?*: The animations that animate.css provides are fast, smooth, and easy to add to your application. + *Pourquoi ?* : Les animations que fournissent animate.css sont rapides, fluides et facile a ajouter à votre application. - *Why?*: Provides consistency in your animations. + *Pourquoi ?* : Fournit de la cohérence dans vos animations. - *Why?*: animate.css is widely used and tested. + *Pourquoi ?* : animate.css est largement utilisée et testée. - Note: See this [great post by Matias Niemelä on AngularJS animations](http://www.yearofmoo.com/2013/08/remastered-animation-in-angularjs-1-2.html) + Note : Voir ce [super post par Matias Niemelä sur les animations d'AngularJS](http://www.yearofmoo.com/2013/08/remastered-animation-in-angularjs-1-2.html) -**[Back to top](#table-of-contents)** +**[Retour en haut de page](#table-des-matières)** ## Comments From babc9fbd5fd01887619f1d24b3b36083719fc6d9 Mon Sep 17 00:00:00 2001 From: Eric Date: Sun, 8 Feb 2015 18:59:44 +0100 Subject: [PATCH 168/567] [FR] Comments --- i18n/fr-FR.md | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/i18n/fr-FR.md b/i18n/fr-FR.md index a736e28e..938d4dab 100644 --- a/i18n/fr-FR.md +++ b/i18n/fr-FR.md @@ -2361,20 +2361,20 @@ Les tests unitaires aident à maintenir un code propre, ainsi, j'ai inclu quelqu **[Retour en haut de page](#table-des-matières)** -## Comments +## Commentaires ### jsDoc ###### [Style [Y220](#style-y220)] - - If planning to produce documentation, use [`jsDoc`](http://usejsdoc.org/) syntax to document function names, description, params and returns. Use `@namespace` and `@memberOf` to match your app structure. + - Si vous prévoyez de produire de la documentation de code, utilisez la syntaxe [`jsDoc`](http://usejsdoc.org/) pour documenter les noms de fonction, leur description, paramètres et valeurs de renvoi. Utilisez `@namespace` et `memberOf` pour s'adapter à la structure de votre appli. - *Why?*: You can generate (and regenerate) documentation from your code, instead of writing it from scratch. + *Pourquoi ?* : Vous pouvez générer (et re-générer) la documentation à partir de votre code, au lieu de l'écrire de zéro. - *Why?*: Provides consistency using a common industry tool. + *Pourquoi ?* : Fournit de la cohérence en utilisant un outil industriel commun. ```javascript /** - * Logger Factory + * Factory de Logger * @namespace Factories */ (function() { @@ -2384,7 +2384,7 @@ Les tests unitaires aident à maintenir un code propre, ainsi, j'ai inclu quelqu /** * @namespace Logger - * @desc Application wide logger + * @desc Logger de niveau applicatif * @memberOf Factories */ function logger($log) { @@ -2397,8 +2397,8 @@ Les tests unitaires aident à maintenir un code propre, ainsi, j'ai inclu quelqu /** * @name logError - * @desc Logs errors - * @param {String} msg Message to log + * @desc Loggue les errors + * @param {String} msg Le message à logguer * @returns {String} * @memberOf Factories.Logger */ @@ -2411,7 +2411,7 @@ Les tests unitaires aident à maintenir un code propre, ainsi, j'ai inclu quelqu })(); ``` -**[Back to top](#table-of-contents)** +**[Retour en haut de page](#table-des-matières)** ## JS Hint From db0d778c3bfed34be4f95de73ee1cd6a4acddb1c Mon Sep 17 00:00:00 2001 From: Eric Date: Sun, 8 Feb 2015 19:10:01 +0100 Subject: [PATCH 169/567] [FR] JS Hint --- i18n/fr-FR.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/i18n/fr-FR.md b/i18n/fr-FR.md index 938d4dab..48a0e869 100644 --- a/i18n/fr-FR.md +++ b/i18n/fr-FR.md @@ -2415,14 +2415,14 @@ Les tests unitaires aident à maintenir un code propre, ainsi, j'ai inclu quelqu ## JS Hint -### Use an Options File +### Utilisation d'un Fichier d'Options ###### [Style [Y230](#style-y230)] - - Use JS Hint for linting your JavaScript and be sure to customize the JS Hint options file and include in source control. See the [JS Hint docs](http://www.jshint.com/docs/) for details on the options. + - Utilisez JS Hint pour éplucher votre JavaScript et assurez-vous d'avoir personnalisé le fichier d'options JS Hint et incluez le dans le système de gestion de versions. Voir la [doc de JS Hint](http://www.jshint.com/docs/) pour les détails de chaque option. - *Why?*: Provides a first alert prior to committing any code to source control. + *Pourquoi ?* : Fournit une première alerte avant de committer son code dans le système de gestion de version. - *Why?*: Provides consistency across your team. + *Pourquoi ?* : Fournit de la cohérence dans votre équipe. ```javascript { @@ -2488,7 +2488,7 @@ Les tests unitaires aident à maintenir un code propre, ainsi, j'ai inclu quelqu } ``` -**[Back to top](#table-of-contents)** +**[Retour en haut de page](#table-des-matières)** ## Constants From f117bd7d2b50a3add86c8f0b1ef98cff15718c41 Mon Sep 17 00:00:00 2001 From: Eric Date: Sun, 8 Feb 2015 20:58:17 +0100 Subject: [PATCH 170/567] [FR] Constants --- i18n/fr-FR.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/i18n/fr-FR.md b/i18n/fr-FR.md index 48a0e869..30e9f98b 100644 --- a/i18n/fr-FR.md +++ b/i18n/fr-FR.md @@ -2492,12 +2492,12 @@ Les tests unitaires aident à maintenir un code propre, ainsi, j'ai inclu quelqu ## Constants -### Vendor Globals +### Globales des Librairies Externes ###### [Style [Y240](#style-y240)] - - Create an AngularJS Constant for vendor libraries' global variables. + - Créez une Constante AngularJS pour les variables gobales des librairies externes. - *Why?*: Provides a way to inject vendor libraries that otherwise are globals. This improves code testability by allowing you to more easily know what the dependencies of your components are (avoids leaky abstractions). It also allows you to mock these dependencies, where it makes sense. + *Pourquoi ?* : Fournit un moyen d'injecter des librairies tierces qui seraient sinon des globales. Cela améliore la testabilité du code en vous permettant de savoir plus facilement quelles sont les dépendances de vos composants évite les abstractions qui fuient). Ça vous permet aussi de mocker ces dépendances, là où cela fait sens. ```javascript // constants.js @@ -2513,7 +2513,7 @@ Les tests unitaires aident à maintenir un code propre, ainsi, j'ai inclu quelqu })(); ``` -**[Back to top](#table-of-contents)** +**[Retour en haut de page](#table-des-matières)** ## File Templates and Snippets Use file templates or snippets to help follow consistent styles and patterns. Here are templates and/or snippets for some of the web development editors and IDEs. From f2d690956f810cf8afc08577f4f0297cb22000a6 Mon Sep 17 00:00:00 2001 From: Eric Date: Sun, 8 Feb 2015 21:45:54 +0100 Subject: [PATCH 171/567] [FR] Code Templates and wqFragments --- i18n/fr-FR.md | 50 +++++++++++++++++++++++++------------------------- 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/i18n/fr-FR.md b/i18n/fr-FR.md index 30e9f98b..0303e8b0 100644 --- a/i18n/fr-FR.md +++ b/i18n/fr-FR.md @@ -2515,53 +2515,53 @@ Les tests unitaires aident à maintenir un code propre, ainsi, j'ai inclu quelqu **[Retour en haut de page](#table-des-matières)** -## File Templates and Snippets -Use file templates or snippets to help follow consistent styles and patterns. Here are templates and/or snippets for some of the web development editors and IDEs. +## Templates de Fichiers et Fragments +Utilisez des templates de fichier ou des fragments pour vous aider à suivre des styles et des patterns cohérents. Voici des templates et/ou fragments pour quelques uns des éditeurs de texte pour le développement web et EDIs. ### Sublime Text ###### [Style [Y250](#style-y250)] - - AngularJS snippets that follow these styles and guidelines. + - Fragments AngularJS qui suivent ces styles et règles. - - Download the [Sublime Angular snippets](assets/sublime-angular-snippets.zip?raw=true) - - Place it in your Packages folder - - Restart Sublime - - In a JavaScript file type these commands followed by a `TAB` + - Téléchargez les [Fragments Angular pour Sublime](assets/sublime-angular-snippets.zip?raw=true) + - Placez-les dans votre répertoire Package + - Redémarrez Sublime + - Dans un fichier de type JavaScript, tapez ces commandes suivies par la touche `TAB` ```javascript - ngcontroller // creates an Angular controller - ngdirective // creates an Angular directive - ngfactory // creates an Angular factory - ngmodule // creates an Angular module + ngcontroller // crée un controlleur Angular + ngdirective // crée une directive Angular + ngfactory // crée une factory Angular + ngmodule // crée un module Angular ``` ### Visual Studio ###### [Style [Y251](#style-y251)] - - AngularJS file templates that follow these styles and guidelines can be found at [SideWaffle](http://www.sidewaffle.com) + - Les templates de fichier qui suivent ces styles et règles peuvent être trouvées sur [SideWaffle](http://www.sidewaffle.com) - - Download the [SideWaffle](http://www.sidewaffle.com) Visual Studio extension (vsix file) - - Run the vsix file - - Restart Visual Studio + - Téléchargez l'extension [SideWaffle](http://www.sidewaffle.com) pour Visual Studio (fichier vsix) + - Éxécutez le fichier vsix + - Re-démarrez Visual Studio ### WebStorm ###### [Style [Y252](#style-y252)] - - AngularJS snippets and file templates that follow these styles and guidelines. You can import them into your WebStorm settings: + - Les fragments AngularJS et templates de fichiers qui suivent le style et les règles. Vous pouvez les importer dans les paramètres de WebStorm : - - Download the [WebStorm AngularJS file templates and snippets](assets/webstorm-angular-file-template.settings.jar?raw=true) - - Open WebStorm and go to the `File` menu - - Choose the `Import Settings` menu option - - Select the file and click `OK` - - In a JavaScript file type these commands followed by a `TAB`: + - Téléchargez les [templates de fichier et fragments WebStorm pour AngularJS](assets/webstorm-angular-file-template.settings.jar?raw=true) + - Ouvrez WebStorm et allez dans le menu `File` + - Choisissez le menu `Import Settings` + - Sélectionnez le fichier et clickez sur `OK` + - Dans un fichier de type JavaScript, tapez ces commandes suivies de la touche `TAB` : ```javascript - ng-c // creates an Angular controller - ng-f // creates an Angular factory - ng-m // creates an Angular module + ng-c // crée un controlleur Angular + ng-f // crée une factory Angular + ng-m // crée un module Angular ``` -**[Back to top](#table-of-contents)** +**[Retour en haut de page](#table-des-matières)** ## AngularJS docs For anything else, API reference, check the [Angular documentation](//docs.angularjs.org/api). From 2be975503a00490568083b00b1a76b4f7f5ec6fc Mon Sep 17 00:00:00 2001 From: Eric Date: Sun, 8 Feb 2015 21:55:49 +0100 Subject: [PATCH 172/567] [FR] Last chapter --- i18n/fr-FR.md | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/i18n/fr-FR.md b/i18n/fr-FR.md index 0303e8b0..50acc9dd 100644 --- a/i18n/fr-FR.md +++ b/i18n/fr-FR.md @@ -2563,23 +2563,23 @@ Utilisez des templates de fichier ou des fragments pour vous aider à suivre des **[Retour en haut de page](#table-des-matières)** -## AngularJS docs -For anything else, API reference, check the [Angular documentation](//docs.angularjs.org/api). +## Documentation AngularJS +Pour tout le reste, la référence des API, allez voir la [documentation Angular](//docs.angularjs.org/api). -## Contributing +## Contribuer -Open an issue first to discuss potential changes/additions. If you have questions with the guide, feel free to leave them as issues in the repository. If you find a typo, create a pull request. The idea is to keep the content up to date and use github’s native feature to help tell the story with issues and PR’s, which are all searchable via google. Why? Because odds are if you have a question, someone else does too! You can learn more here at about how to contribute. +Créez d'abord un problème pour discuter de potentiels changements ou ajouts. Si vous avez des questions sur le guide, je vous encourage à les rapporter comme problèmes dans le référentiel. Si vous trouvez une erreur de frappe, créez une pull request. L'idée est de garder le contenu à jour et d'utiliser les fonctionnalités natives de github pour aider à raporter les problèmes et les pull requests, lesquels sont recherchables via google. Pourquoi ? Parce que d'autres pourraient avoir la même question ! Vous en apprendrez plus ci-dessous pour savoir comment contribuer. -*By contributing to this repository you are agreeing to make your content available subject to the license of this repository.* +*En contribuant à ce référentiel, vous acceptez de rendre votre contenu accessible le sujet de la licence de ce référentiel.* -### Process - 1. Discuss the changes in an Issue. - 2. Open a Pull Request, reference the issue, and explain the change and why it adds value. - 3. The Pull Request will be evaluated and either merged or declined. +### Processus + 1. Discuter des changements dans une Issue. + 2. Ouvrir une Pull Request, référencer l'Issue, et expliquer le changement et la raison pour laquelle i lajoute de la valeur. + 3. La Pull Request sera évaluée et soit mergée ou abandonnée. ## License -_tldr; Use this guide. Attributions are appreciated._ +_tldr; Utilisez ce guide. Les attributions sont appréciées._ ### (The MIT License) @@ -2604,4 +2604,4 @@ 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. -**[Back to top](#table-of-contents)** +**[Retour en haut de page](#table-des-latières)** From e646b59ca5505795f21efb60232376209ff310bd Mon Sep 17 00:00:00 2001 From: Eric Date: Sun, 8 Feb 2015 22:33:21 +0100 Subject: [PATCH 173/567] [FR] Update table of contents --- i18n/fr-FR.md | 52 +++++++++++++++++++++++++-------------------------- 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/i18n/fr-FR.md b/i18n/fr-FR.md index 50acc9dd..1bccbf3d 100644 --- a/i18n/fr-FR.md +++ b/i18n/fr-FR.md @@ -27,26 +27,26 @@ Alors que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'a ét 1. [Controlleurs](#controlleurs) 1. [Services](#services) 1. [Factories](#factories) - 1. [Data Services](#data-services) + 1. [Services de données](#services-de-données) 1. [Directives](#directives) - 1. [Resolving Promises for a Controller](#resolving-promises-for-a-controller) - 1. [Manual Annotating for Dependency Injection](#manual-annotating-for-dependency-injection) - 1. [Minification and Annotation](#minification-and-annotation) + 1. [Résolution des Promesses pour un controlleur](#résolution-des-promesses-pour-un-controlleur) + 1. [Annoter Manuellement pour l'Injection de Dépendances](#annoter-manuellement-pour-l-injection-de-dépendances) + 1. [Minification et Annotation](#minification-et-annotation) 1. [Gestion des Exceptions](#gestion-des-exceptions) - 1. [Naming](#naming) - 1. [Application Structure LIFT Principle](#application-structure-lift-principle) - 1. [Application Structure](#application-structure) - 1. [Modularity](#modularity) - 1. [Startup Logic](#startup-logic) - 1. [Angular $ Wrapper Services](#angular--wrapper-services) - 1. [Testing](#testing) + 1. [Nommage](#nommage) + 1. [Le Principe LIFT de Structuration de l'Application](#le-principe-lift-de-structuration-de-l-application) + 1. [Structure de l'Application](#structure-de-l-application) + 1. [Modularité](#modularité) + 1. [Logique de Démarrage](#logique-de-démarrage) + 1. [Les Services de Wrapper $ de Angular](#les-services-de-wrapper--de-angular) + 1. [Le Test](#le-test) 1. [Animations](#animations) - 1. [Comments](#comments) + 1. [Commentaires](#commentaires) 1. [JSHint](#js-hint) - 1. [Constants](#constants) - 1. [File Templates and Snippets](#file-templates-and-snippets) - 1. [AngularJS Docs](#angularjs-docs) - 1. [Contributing](#contributing) + 1. [Constantes](#constantes) + 1. [Templates de Fichiers et Fragments](#templates-de-fichiers-et-fragments) + 1. [Documentation AngularJS](#documentation-angularjs) + 1. [Contribuer](#contribuer) 1. [License](#license) ## Responsabilité Unique @@ -669,7 +669,7 @@ Alors que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'a ét ``` -**[Retour en haut de page](#table-of-contents)** +**[Retour en haut de page](#table-des-matières)** ## Services @@ -708,7 +708,7 @@ Alors que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'a ét } ``` -**[Retour en faut de page](#table-of-contents)** +**[Retour en faut de page](#table-des-matières)** ## Factories @@ -1004,7 +1004,7 @@ Alors que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'a ét } ``` - **[Retour en haut de page](#table-des-matières)** +**[Retour en haut de page](#table-des-matières)** ## Directives ### Limite de 1 Par Fichier @@ -1241,9 +1241,9 @@ Alors que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'a ét
min={{vm.min}}
``` -**[Retour en haut de la page](#table-des-matieres)** +**[Retour en haut de page](#table-des-matieres)** -## Resolving Promises for a Controller +## Résolution des Promesses pour un Controlleur ### Promesses d'Activation du Controller ###### [Style [Y080](#style-y080)] @@ -1348,7 +1348,7 @@ Alors que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'a ét Note : Les dépendances dans l'exemple de code sur `movieService` ne sont pas directement compatibles avec la minification. Pour les détails sur la façon de rendre ce code compatible avec la minification, voir la section sur l'[injection de dépendance](#manual-annotating-for-dependency-injection) et sur [la minification et les annotations](#minification-and-annotation). -**[Retour en haut de page](#table-of-contents)** +**[Retour en haut de page](#table-des-matières)** ## Annoter Manuellement pour l'Injection de Dépendances @@ -1479,7 +1479,7 @@ Alors que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'a ét } ``` -**[Retour en haut de page](#table-des-matieres)** +**[Retour en haut de page](#table-des-matières)** ## Minification et Annotation @@ -1698,7 +1698,7 @@ Alors que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'a ét } ``` -**[Retour en haut de page](#table-des-matieres)** +**[Retour en haut de page](#table-des-matières)** ## Nommage @@ -2160,7 +2160,7 @@ Alors que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'a ét > Dans de petites applic, vous pouvez aussi mettre toutes vos dépendances partagées dans le module applicatif où les modules fonctionnels n'ont pas de dépendances directes. Cela pourra rendre la maintenance de cette petite application plus facile, mais rendez difficile la ré-utilisation de ces modules en dehors de cette application. -**[Back to top](#table-of-contents)** +**[Retour en haut de page](#table-des-matières)** ## Logique de Démarrage @@ -2604,4 +2604,4 @@ 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. -**[Retour en haut de page](#table-des-latières)** +**[Retour en haut de page](#table-des-matières)** From 5bbe6a0262bfe4c6b3f8352d475b9ea306c93bb4 Mon Sep 17 00:00:00 2001 From: Eric Date: Sun, 8 Feb 2015 22:34:44 +0100 Subject: [PATCH 174/567] [FR] fix typos --- i18n/fr-FR.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/i18n/fr-FR.md b/i18n/fr-FR.md index 1bccbf3d..6d74457b 100644 --- a/i18n/fr-FR.md +++ b/i18n/fr-FR.md @@ -30,12 +30,12 @@ Alors que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'a ét 1. [Services de données](#services-de-données) 1. [Directives](#directives) 1. [Résolution des Promesses pour un controlleur](#résolution-des-promesses-pour-un-controlleur) - 1. [Annoter Manuellement pour l'Injection de Dépendances](#annoter-manuellement-pour-l-injection-de-dépendances) + 1. [Annoter Manuellement pour l'Injection de Dépendances](#annoter-manuellement-pour-linjection-de-dépendances) 1. [Minification et Annotation](#minification-et-annotation) 1. [Gestion des Exceptions](#gestion-des-exceptions) 1. [Nommage](#nommage) - 1. [Le Principe LIFT de Structuration de l'Application](#le-principe-lift-de-structuration-de-l-application) - 1. [Structure de l'Application](#structure-de-l-application) + 1. [Le Principe LIFT de Structuration de l'Application](#le-principe-lift-de-structuration-de-lapplication) + 1. [Structure de l'Application](#structure-de-lapplication) 1. [Modularité](#modularité) 1. [Logique de Démarrage](#logique-de-démarrage) 1. [Les Services de Wrapper $ de Angular](#les-services-de-wrapper--de-angular) @@ -1241,7 +1241,7 @@ Alors que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'a ét
min={{vm.min}}
``` -**[Retour en haut de page](#table-des-matieres)** +**[Retour en haut de page](#table-des-matières)** ## Résolution des Promesses pour un Controlleur @@ -2490,7 +2490,7 @@ Les tests unitaires aident à maintenir un code propre, ainsi, j'ai inclu quelqu **[Retour en haut de page](#table-des-matières)** -## Constants +## Constantes ### Globales des Librairies Externes ###### [Style [Y240](#style-y240)] From 451136b28f1e7ac9155c7985f5c7f847d9845752 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89ric=20Le=20Merdy?= Date: Wed, 11 Feb 2015 03:34:09 +0100 Subject: [PATCH 175/567] [FR] Apply changes since fork in december (yeoman, routing, task automation) --- i18n/fr-FR.md | 261 ++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 242 insertions(+), 19 deletions(-) diff --git a/i18n/fr-FR.md b/i18n/fr-FR.md index 6d74457b..5ddf2e6b 100644 --- a/i18n/fr-FR.md +++ b/i18n/fr-FR.md @@ -4,9 +4,11 @@ Si vous cherchez un guide de style pour la syntaxe, les conventions, et la structuration d'application AngularJS, alors vous êtes au bon endroit. Ces styles sont basés sur mon expérience de dévelopement avec [AngularJS](//angularjs.org), mes présentations, [mes cours sur Pluralsight](http://pluralsight.com/training/Authors/Details/john-papa) et mon travail au sein des équipes. +Le but de ce guide de style est de proposer des conseils sur le développement d'applications AngularJS en montrant les conventions que j'utilise et, plus important encore, les raisons des choix que j'ai pris. + >Si vous appréciez ce guide, visitez mon cours [AngularJS Patterns: Clean Code](http://jpapa.me/ngclean) sur Pluralsight. -Le but de ce guide de style est de proposer des conseils sur le développement d'applications AngularJS en montrant les conventions que j'utilise et, plus important encore, les raisons des choix que j'ai pris. + [![AngularJs Patterns: Clean Code](https://raw.githubusercontent.com/johnpapa/angularjs-styleguide/master/assets/ng-clean-code-banner.png)](http://jpapa.me/ngclean) ## Supprématie de la Communauté et Remerciements Ne jamais travailler dans le vide. J'ai trouvé que la communauté AngularJS est un incroyable groupe dont les membres ont à coeur de partager leurs expériences. Ainsi, un ami et expert AngularJS Todd Motto et moi avons collaboré sur de nombreux styles et conventions. Nous sommes d'accord sur la plupart, et nous divergeons sur d'autres. Je vous encourage à visiter [les guideslines de Todd](https://github.com/toddmotto/angularjs-styleguide) pour vous faire un sentiment sur son approche et en quoi elle est comparable. @@ -45,6 +47,9 @@ Alors que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'a ét 1. [JSHint](#js-hint) 1. [Constantes](#constantes) 1. [Templates de Fichiers et Fragments](#templates-de-fichiers-et-fragments) + 1. [Générateur Yeoman](#générateur-yeoman) + 1. [Routage](#routage) + 1. [Automatisation des Tâches](#automatisation-des-taches) 1. [Documentation AngularJS](#documentation-angularjs) 1. [Contribuer](#contribuer) 1. [License](#license) @@ -591,7 +596,6 @@ Alors que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'a ét ``` ```javascript - /* recommandé */ function Order(creditService) { var vm = this; @@ -1032,7 +1036,6 @@ Alors que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'a ét /* directive spinner pouvant être utilisée n'importe où dans l'application */ .directive('sharedSpinner', sharedSpinner); - function orderCalendarRange() { /* détails de l'implémentation */ } @@ -1208,15 +1211,17 @@ Alors que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'a ét }, link: linkFunc, controller : ExampleController, - controllerAs: 'vm' + controllerAs: 'vm', + bindToController: true // parce que le scope est isolé }; return directive; function linkFunc(scope, el, attr, ctrl) { - console.log('LINK: scope.max = %i', scope.max); - console.log('LINK: scope.vm.min = %i', scope.vm.min); - console.log('LINK: scope.vm.max = %i', scope.vm.max); + console.log('LINK: scope.min = %s *** should be undefined', scope.min); + console.log('LINK: scope.max = %s *** should be undefined', scope.max); + console.log('LINK: scope.vm.min = %s', scope.vm.min); + console.log('LINK: scope.vm.max = %s', scope.vm.max); } } @@ -1227,15 +1232,63 @@ Alors que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'a ét var vm = this; vm.min = 3; - vm.max = $scope.max; - console.log('CTRL: $scope.max = %i', $scope.max); - console.log('CTRL: vm.min = %i', vm.min); - console.log('CTRL: vm.max = %i', vm.max); + + console.log('CTRL: $scope.vm.min = %s', $scope.vm.min); + console.log('CTRL: $scope.vm.max = %s', $scope.vm.max); + console.log('CTRL: vm.min = %s', vm.min); + console.log('CTRL: vm.max = %s', vm.max); } ``` ```html - /* example.directive.html */ + +
hello world
+
max={{vm.max}}
+
min={{vm.min}}
+ ``` + +###### [Style [Y076](#style-y076)] + + - Utilisez `bindToController = true` lorsque vous utilisez la syntaxe `controller as` avec une directive quand vous voulez binder le scope externe au scope du controlleur de la directive. + + *Pourquoi ?* : Cela rend plus facile de binder le scope externe au scope du controlleur de la directive. + + Note : `bindToController` a été introduit à partir de Angular 1.3.0. + + ```html +
+ ``` + + ```javascript + angular + .module('app') + .directive('myExample', myExample); + + function myExample() { + var directive = { + restrict: 'EA', + templateUrl: 'app/feature/example.directive.html', + scope: { + max: '=' + }, + controller: ExampleController, + controllerAs: 'vm', + bindToController: true + }; + + return directive; + } + + function ExampleController() { + var vm = this; + vm.min = 3; + console.log('CTRL: vm.min = %s', vm.min); + console.log('CTRL: vm.max = %s', vm.max); + } + ``` + + ```html +
hello world
max={{vm.max}}
min={{vm.min}}
@@ -1251,8 +1304,11 @@ Alors que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'a ét - Résolvez la logique de démarrage d'un controlleur dans une fonction `activate`. *Pourquoi ?* : Placer la logique de démarrage toujours au même endroit permet de le rendre plus facile à localiser, plus cohérent à tester, et permet d'éviter la dispersion de la logique d'activation à travers le controlleur. + + *Pourquoi ?* : La fonction `activate` d'un controlleur rend pratique la ré-utilisation de la logique pour un refraichissement du controlleur ou de la vue, garde cette logique à un seul endroit, envoie l'utilisateur plus rapidement à la Vue, rend les animations faciles sur la `ng-view` ou l'`ui-view`, et c'est rendu plus vif à l'utilisateur. + *Why?*: The controller `activate` makes it convenient to re-use the logic for a refresh for the controller/View, keeps the logic together, gets the user to the View faster, makes animations easy on the `ng-view` or `ui-view`, and feels snappier to the user. - Note : Si vous avez besoin d'annuler sous conditions la route avant de vous mettre à utiliser le controlleur, utilisez une résolution de route à la place. + Note : Si vous avez besoin d'annuler sous conditions la route avant de vous mettre à utiliser le controlleur, utilisez une [résolution de route](#style-y081) à la place. ```javascript /* à éviter */ @@ -1291,10 +1347,16 @@ Alors que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'a ét ### Promesses de Résolution de Route ###### [Style [Y081](#style-y081)] - - Lorsqu'un controlleur dépend d'une promesse qui doit être résolue, résolvez ces dépendances dans le `$routeProvider` avant que la logique du controlleur soit éxécutée. Si vous avez besoin d'annuler une route sous certaines conditions avant que le controlleur soit activé, utilisez un resolver de route. + - Lorsqu'un controlleur dépend d'une promesse qui doit être résolue avant qu'un controlleur soit activé, résolvez ces dépendances dans le `$routeProvider`. Si vous avez besoin d'annuler une route sous certaines conditions avant que le controlleur soit activé, utilisez un resolver de route. + + - Utilisez un resolver de route dès lors que vous voulez décider d'annuler la route avant même de commencer à naviguer vers la Vue. *Pourquoi ?* : Un controlleur pourrait avoir besoin de données avant qu'il se charge. Cette donnée pourrait venir d'une promesse via une factory personnalisée ou de [$http](https://docs.angularjs.org/api/ng/service/$http). Utiliser une [resolution de route](https://docs.angularjs.org/api/ngRoute/provider/$routeProvider) permet à la promesse de se résoudre avant que la logique du controlleur s'éxécute, ainsi on peut prendre des actions basées sur cette donnée à partir de la promesse. + *Pourquoi ?* : Le code s'éxécute après la route et dans la fonction activate du controlleur. La Vue commence à se charger tout de suite. Le data binding démarre quand la promesse d'activation se résoud. Une animation de "chargement" peut être affichée pendant que la vue opère la transition (via ng-view ou ui-view). + + Note : Le code s'éxécute avant la route via une promesse. Le rejet de la promesse annule le routage. Sa résolution met la nouvelle vue en attente de la résolution du routage. Une animation de "chargement" peut être affichée avant la résolution et lorsque la vue entre en transition. Si vous voulez aller à la Vue plus vite et que vous n'avez pas besoin d'un point pour décider si vous voulez atteindre la Vue, il est conseillé d'utiliser la [technique de l'activation de controlleur](#style-y080) à la place. + ```javascript /* à éviter */ angular @@ -1344,8 +1406,45 @@ Alors que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'a ét var vm = this; vm.movies = moviesPrepService.movies; } - ``` + ``` + + Note : L'exemple ci-dessous montre que la résolution de routage pointe vers une fonction nommée, laquelle est plus facile à débugguer et dont l'injection de dépendance est plus facile à gérer. + + ```javascript + /* encore mieux */ + // route-config.js + angular + .module('app') + .config(config); + + function config($routeProvider) { + $routeProvider + .when('/avengers', { + templateUrl: 'avengers.html', + controller: 'Avengers', + controllerAs: 'vm', + resolve: { + moviesPrepService: moviesPrepService + } + }); + } + + function moviePrepService(movieService) { + return movieService.getMovies(); + } + + // avengers.js + angular + .module('app') + .controller('Avengers', Avengers); + + Avengers.$inject = ['moviesPrepService']; + function Avengers(moviesPrepService) { + var vm = this; + vm.movies = moviesPrepService.movies; + } + ``` Note : Les dépendances dans l'exemple de code sur `movieService` ne sont pas directement compatibles avec la minification. Pour les détails sur la façon de rendre ce code compatible avec la minification, voir la section sur l'[injection de dépendance](#manual-annotating-for-dependency-injection) et sur [la minification et les annotations](#minification-and-annotation). **[Retour en haut de page](#table-des-matières)** @@ -2269,7 +2368,7 @@ Les tests unitaires aident à maintenir un code propre, ainsi, j'ai inclu quelqu ### Librairie de Test ###### [Style [Y191](#style-y191)] - - Utilisez [Jasmine](http://jasmine.github.io/) or [Mocha](http://visionmedia.github.io/mocha/) pour les tests unitaires. + - Utilisez [Jasmine](http://jasmine.github.io/) or [Mocha](http://mochajs.org) pour les tests unitaires. *Pourquoi ?* : Jasmine et Mocha sont toutes deux largement utilisées dans la communauté AngularJS. Toutes les deux stables, bien maintenues, et fournissant des fonctionnalités robustes de test. @@ -2291,7 +2390,7 @@ Les tests unitaires aident à maintenir un code propre, ainsi, j'ai inclu quelqu ### Les Stubs et les Spy ###### [Style [Y193](#style-y193)] - - Utilisez Sinon pour les stubs et les spy. + - Utilisez [Sinon](http://sinonjs.org/) pour les stubs et les spy. *Pourquoi ?* : Sinon fonctionne bien avec Jasmine et Mocha et étend les fonctionnalités de stub et de spy qu'ils offrent. @@ -2326,6 +2425,33 @@ Les tests unitaires aident à maintenir un code propre, ainsi, j'ai inclu quelqu ![Outils de Test](https://raw.githubusercontent.com/johnpapa/angularjs-styleguide/master/assets/testing-tools.png) +### Organizing Tests +###### [Style [Y197](#style-y197)] + + - Placez les fichiers des tests unitaires (specs) côte-à-côte du code client. Placez les specs qui couvrent l'intégration avec le serveur ou les celles qui testent plusieurs composants dans un répertoire `tests` séparé. + + *Pourquoi ?* : Les tests unitaires sont en corrélation directe avec un composant spécifique et un fichier dans le code source. + + *Pourquoi ?* : Il est plus facile de les mettre à jour pluisqu'ils sont toujours les uns en face des autres. Quand vous développez, que vous fassiez du TDD, des tests en meme temps que l'implémentation ou des tests après l'implémentation, les specs sont côte-à-côte et jamais loin ni des yeux ni de l'esprit, et ainsi ils ont plus de chance d'etre maintenus ce qui permet aussi de tenir une bonne couverture de code. + + *Pourquoi ?* : Quand vous mettez à jour le code source, il est plus facile de mettre à jour les tests en même temps. + + *Pourquoi ?* : Les placer côte-à-côte les rend plus facile à trouver et facile à déplacer si vous déplacez les sources. + + *Pourquoi ?* : Avoir les specs proches permet au lecteur du code source d'apprendre comment le composant est supposé être utilisé et découvrir les limitations connues. + + *Pourquoi ?* : La séparation des specs afin qu'ils ne soient pas inclus dans le build est facile avec grunt ou gulp. + + ``` + /src/client/app/customers/customer-detail.controller.js + /customer-detail.controller.spec.js + /customers.controller.spec.js + /customers.controller-detail.spec.js + /customers.module.js + /customers.route.js + /customers.route.spec.js + ``` + **[Retour en haut de page](#table-des-matières)** ## Animations @@ -2511,6 +2637,31 @@ Les tests unitaires aident à maintenir un code propre, ainsi, j'ai inclu quelqu .constant('toastr', toastr) .constant('moment', moment); })(); + ``` + +###### [Style [Y241](#style-y241)] + + - Utilisez les constantes pour les valeurs qui ne changent pas et ne viennent pas d'un autre service. Quand des contantes ne sont utilisées que par un module qui peut être ré-utilisé dans d'autres applications, placez les constantes dans un seul fichier par module nommé comme le module. Tant que c'est possible, gardez les constantes dans le module principal dans un fichier `constants.js`. + + *Pourquoi ?* : Une valeur qui peut changer, même rarement, devrait être récupérée d'un service afin de ne pas avoir à changer le code source. Par exemple, une URL pour un service de données pourrait être définit comme constante mais il serait mieux de lire cette valeur par appel à un web service. + + *Pourquoi ?* : Les constantes peuvent être injectées dans un composant angular, y compris les providers. + + *Pourquoi ?* : Quand une application est divisée en modules qui peuvent être ré-utilisés dans d'autres applications, chacun de ces modules individiuel devrait pouvoir fonctioner tout seul, y compris avec les constantes dépendantes. + + ```javascript + // Constantes utilisées par toute l'appli + angular + .module('app.core') + .constant('moment', moment); + + // Constantes utilisées seulement par le module de vente + angular + .module('app.sales') + .constant('events', { + ORDER_CREATED: 'event_order_created', + INVENTORY_DEPLETED: 'event_inventory_depleted' + }); ``` **[Retour en haut de page](#table-des-matières)** @@ -2560,6 +2711,78 @@ Utilisez des templates de fichier ou des fragments pour vous aider à suivre des ng-f // crée une factory Angular ng-m // crée un module Angular ``` + + **[Retour en haut de page](#table-des-matières)** + +## Generateur Yeoman +###### [Style [Y260](#style-y260)] + +Vous pouvez utiliser le [générateur yeoman HotTowel](http://jpapa.me/yohottowel) pour créer une appli pour démarrer avec Angular en suivant ce guide de style. + +1. Installer generator-hottowel + + ``` + npm install -g generator-hottowel + ``` + +2. Créer un nouveau répertoire et aller dans ce répertoire + + ``` + mkdir myapp + cd myapp + ``` + +3. Éxécuter le générateur + + ``` + yo hottowel helloWorld + ``` + +**[Retour en haut de page](#table-des-matières)** + +## Routage +Le routage côté client est important pour créer un flux de navigation entre les vues et la composition des vues constituées de nombreux plus petits templates et directives. + +###### [Style [Y270](#style-y270)] + + - Utilisez [Routeur AngularUI](http://angular-ui.github.io/ui-router/) pour faire le routage côté client. + + *Pourquoi ?* : UI Router offre toutes les fonctionnalités du routeur Angular plus quelques autres parmis lesquels les routes imbriquées et les états. + + *Pourquoi ?* : La syntaxe est quasiement similaire au routeur Angular et il est facile de migrer à UI Router. + +###### [Style [Y271](#style-y271)] + + - Définissez les routes pour les vues d'un module à l'endroit où elles existent. Chaque module devrait contenir le routage de ses vues. + + *Pourquoi ?* : Chaque module devrait avoir la cohérence de définir ses propres routes. + + *Pourquoi ?* : Si on ajoute ou enlève un module, on souhaite que l'appli ne contienne que les routes vers des vues existantes. + + *Pourquoi ?* : Cela rend facile l'activation ou la désactivation de portions de l'application sans se préoccuper des routes orphelines. + +**[Retour en haut de page](#table-des-matières)** + +## Automatisation des Tâches +Utilisez [Gulp](http://gulpjs.com) ou [Grunt](http://gruntjs.com) pour créer des tâches automatisées. Gulp favorise le code plutôt que la configuration tandis que Grunt tend vers la configuration plutôt que le code. Je préfère personnellement Gulp car il me semble plus facile à lire et écrire, mais les deux sont excellents. + +###### [Style [Y400](#style-y400)] + + - Utilisez l'automatisation des tâches pour lister les fichiers de définition de module `*.module.js` avant tout autre fichier JavaScript de l'application. + + *Pourquoi ?* : Angular a besoin que la définition des modules soit déclarée avant qu'ils puissent être utilisés. + + *Pourquoi ?* : Nommer les modules avec un pattern spécifique tel que `*.module.js` les rends faciles à aller chercher avec une expression englobante et à les lister en premier. + + ```javascript + var clientApp = './src/client/app/'; + + // Toujours aller chercher les fichiers de module en premier + var files = [ + clientApp + '**/*.module.js', + clientApp + '**/*.js' + ]; + ``` **[Retour en haut de page](#table-des-matières)** @@ -2573,8 +2796,8 @@ Créez d'abord un problème pour discuter de potentiels changements ou ajouts. S *En contribuant à ce référentiel, vous acceptez de rendre votre contenu accessible le sujet de la licence de ce référentiel.* ### Processus - 1. Discuter des changements dans une Issue. - 2. Ouvrir une Pull Request, référencer l'Issue, et expliquer le changement et la raison pour laquelle i lajoute de la valeur. + 1. Discuter des changements dans une Issue GitHub. + 2. Ouvrir une Pull Request sur la branche develop, référencer l'Issue, et expliquer le changement et la raison pour laquelle ce changement est pertinent. 3. La Pull Request sera évaluée et soit mergée ou abandonnée. ## License From 23817375ba2ee448028404e5d6f781fcb02862e4 Mon Sep 17 00:00:00 2001 From: Vasiliy Mazhekin Date: Mon, 9 Feb 2015 16:57:00 +0200 Subject: [PATCH 176/567] Russian translation added ru-RU.md Update ru-RU.md Update ru-RU.md --- i18n/ru-RU.md | 2775 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 2775 insertions(+) create mode 100644 i18n/ru-RU.md diff --git a/i18n/ru-RU.md b/i18n/ru-RU.md new file mode 100644 index 00000000..46e822d2 --- /dev/null +++ b/i18n/ru-RU.md @@ -0,0 +1,2775 @@ +# Руководство по стилям для AngularJS + +*AngularJS соглашения по стилям для команд разработчиков, предложенные [@john_papa](//twitter.com/john_papa)* + +*Перевел на русский язык [Василий Мажекин](https://github.com/mazhekin)* + +Если вам нужны стандарты написания кода, соглашения, и руководства структурирования приложений AngularJS, то вы находитесь в правильном месте. Эти соглашения основаны на моем опыте программирования на [AngularJS](//angularjs.org), на моих презентациях [Pluralsight training courses](http://pluralsight.com/training/Authors/Details/john-papa), а также на совместной работе в командах разработчиков. + +Главной целью этого документа является желание предоставить вам наиболее полные инструкции для построения приложений AngularJS. Рекомендуя данные соглашения, я стараюсь акцентировать ваше внимание на цели и причины, зачем их нужно придерживаться. +>Если это руководство вам понравится, то вы можете также оценить мой курс [AngularJS Patterns: Clean Code](http://jpapa.me/ngclean), который размещен на сайте Pluralsight. + + [![AngularJs Patterns: Clean Code](https://raw.githubusercontent.com/johnpapa/angularjs-styleguide/master/assets/ng-clean-code-banner.png)](http://jpapa.me/ngclean) + +## Признательность сообществу и коллегам +Никогда не работайте в вакууме. Я считаю AngularJS-сообщество невероятно открытым, которое активно обменивается опытом и заботится об этом. Также как и мой друг Todd Motto (отличный AngularJS эксперт), я работал со многими стилями и соглашениями. Мы с ним сходимся во многом, но иногда и противоречим друг другу. Я предлагаю вам ознакомиться с курсом [Todd's guidelines](https://github.com/toddmotto/angularjs-styleguide) дабы почувствовать разницу подходов. + +Многие из моих стилей взяты в ходе моих программистских сессий с [Ward Bell](http://twitter.com/wardbell). А так как мы не всегда были согласны друг с другом, то мой друг Ward оказал очень сильное влияние на эволюцию и окончательную редакцию этого документа. + +## Смотрите стили и шаблоны в приложении-примере +Пока данное руководство объясняет *что*, *почему* и *как*, я сразу же показываю, как это работает на практике. Все, что я предлагаю и описываю сопровождается примером-приложения, которое соблюдает и демонстрирует приведенные стили и шаблоны. Вы можете найти [пример приложения (имя modular) здесь](https://github.com/johnpapa/ng-demos) в папке `modular`. Свободно скачивайте, клонируйте и перемещайте эти примеры в свои хранилища. [Инструкциии по запуску примеров находятся в файлах readme](https://github.com/johnpapa/ng-demos/tree/master/modular). + +## Переводы +[Переводы данного руководства по Angular-стилям](https://github.com/johnpapa/angularjs-styleguide/tree/master/i18n) поддерживаются соообществом разработчиков и могут быть найдены здесь. + +## Table of Contents + + 1. [Единственная обязанность (Single Responsibility)](#single-responsibility) + 1. [IIFE](#iife) + 1. [Модули (Modules)](#modules) + 1. [Контроллеры (Controllers)](#controllers) + 1. [Сервисы (Services)](#services) + 1. [Фабрики (Factories)](#factories) + 1. [Сервисы данных (Data Services)](#data-services) + 1. [Директивы (Directives)](#directives) + 1. [Resolving Promises for a Controller (Работа с Объектами Promise в Контроллерe)](#resolving-promises-for-a-controller) + 1. [Manual Annotating for Dependency Injection (Аннотация для Внедренной Зависимости)](#manual-annotating-for-dependency-injection) + 1. [Minification and Annotation (Минификация и аннотация)](#minification-and-annotation) + 1. [Exception Handling (Обработка Исключений)](#exception-handling) + 1. [Naming (Именования)](#naming) + 1. [Application Structure LIFT Principle (Структура Приложения по Приниципу LIFT)](#application-structure-lift-principle) + 1. [Application Structure (Структура Приложения)](#application-structure) + 1. [Modularity (Модульность)](#modularity) + 1. [Startup Logic (Логика Запуска Приложения)](#startup-logic) + 1. [Angular $ Wrapper Services (Angular и Интерфейсные Сервисы)](#angular--wrapper-services) + 1. [Testing (Тестирование)](#testing) + 1. [Animations (Анимации)](#animations) + 1. [Comments (Комментарии)](#comments) + 1. [JSHint](#js-hint) + 1. [Constants (Константы)](#constants) + 1. [File Templates and Snippets (Шаблоны Файлов и Сниппеты)](#file-templates-and-snippets) + 1. [Yeoman Generator](#yeoman-generator) + 1. [Routing (Маршрутизация)](#routing) + 1. [Task Automation (Автоматизация)](#task-automation) + 1. [AngularJS Docs (AngularJS документация)](#angularjs-docs) + 1. [Contributing (Сотрудничество)](#contributing) + 1. [License](#license) + +## Single Responsibility + +### Правило 1 +###### [Style [Y001](#style-y001)] + + - Определяйте 1 компонент в одном файле. + + В следующем примере в одном и том же файле определяется модуль(module) `app` вместе с его зависимостями, определяется контроллер(controller), а также сервис(factory). + + ```javascript + /* избегайте этого */ + angular + .module('app', ['ngRoute']) + .controller('SomeController', SomeController) + .factory('someFactory', someFactory); + + function SomeController() { } + + function someFactory() { } + ``` + + А теперь каждый компонент разнесен в свой отдельный файл. + + ```javascript + /* рекомендовано */ + + // app.module.js + angular + .module('app', ['ngRoute']); + ``` + + ```javascript + /* рекомендовано */ + + // someController.js + angular + .module('app') + .controller('SomeController', SomeController); + + function SomeController() { } + ``` + + ```javascript + /* рекомендовано */ + + // someFactory.js + angular + .module('app') + .factory('someFactory', someFactory); + + function someFactory() { } + ``` + +**[К Содержанию](#table-of-contents)** + +## IIFE +### Замыкания JavaScript +###### [Style [Y010](#style-y010)] + + - Оборачивайте компоненты AngularJS в Немедленно Исполняемые Функции(IIFE - Immediately Invoked Function Expression). + + *Зачем?*: IIFE удаляют переменные из глобальной области видимости. Этот прием не дает существовать переменным и функциям дольше, чем это необходимо в глобальной области видимости. Иначе это может вызвать непредсказуемые коллизии во время исполнения всего приложения. + + *Зачем?*: Когда ваш код будет сжат и упакован (bundled and minified) в один файл для размещения его на рабочем сервере, то коллизий станет намного больше, чем их было до минификации. IIFE защитит ваш код, обеспечивая область видимости переменных только в немедленно исполняемых функциях(IIFE), которые оборачивают ваш код. + + ```javascript + /* избегайте этого */ + // logger.js + angular + .module('app') + .factory('logger', logger); + + // функция logger добавлена как глобальная переменная + function logger() { } + + // storage.js + angular + .module('app') + .factory('storage', storage); + + // функция storage добавлена как глобальная переменная + function storage() { } + ``` + + ```javascript + /** + * рекомендовано + * + * больше нет глобальных переменных + */ + + // logger.js + (function() { + 'use strict'; + + angular + .module('app') + .factory('logger', logger); + + function logger() { } + })(); + + // storage.js + (function() { + 'use strict'; + + angular + .module('app') + .factory('storage', storage); + + function storage() { } + })(); + ``` + + - Замечание: Только для краткости, в остальных примерах мы не будем прописывать синтаксис с функциями IIFE. + + - Замечание: IIFE не дает тестировать приватный код, так как предотвращает доступ к нему, например, регулярные выражения или вспомогательные функции, которые нужно оттестировать в модульных тестах (unit test) напрямую. Как выход, вы можете тестировать через специальные методы, используемые только в тестах (accessible members) или выставить нужные внутренние функции в собственном компоненте. Например, поместите вспомогательные функции, регулярные выражения или константы в собственную фабрику(factory) или константу(constant). + +**[К Содержанию](#table-of-contents)** + +## Modules + +### Избегайте коллизий имен +###### [Style [Y020](#style-y020)] + + - Используйте конвенцию уникальных имен с разделителями для подмодулей. + + *Почему?*: Уникальные имена помогают избежать коллизий в именах модулей. Разделители определяет сам модуль и его подмодульную иерархию. Например, `app` может быть вашим корневым модулем, а модули `app.dashboard` и `app.users` могут использоваться как имена модулей, зависимые от `app`. + +### Сеттеры (Setters) +###### [Style [Y021](#style-y021)] + + - Объявляйте модули без переменных, используйте сеттеры (setters). + + *Почему?*: Так как обычно в файле 1 компонент, поэтому вряд ли потребуется вводить переменную для модуля. + + ```javascript + /* избегайте этого */ + var app = angular.module('app', [ + 'ngAnimate', + 'ngRoute', + 'app.shared', + 'app.dashboard' + ]); + ``` + + Используйте простой синтаксис сеттера. + + ```javascript + /* рекомендовано */ + angular + .module('app', [ + 'ngAnimate', + 'ngRoute', + 'app.shared', + 'app.dashboard' + ]); + ``` + +### Геттеры (Getters) +###### [Style [Y022](#style-y022)] + + - Когда нужно использовать модуль, избегайте использования переменных, а используйте вместо этого цепочку геттеров. + + *Почему?*: Так вы производите более читаемый код, а также избегаете утечек и коллизий переменных. + + ```javascript + /* избегайте этого */ + var app = angular.module('app'); + app.controller('SomeController', SomeController); + + function SomeController() { } + ``` + + ```javascript + /* рекомендовано */ + angular + .module('app') + .controller('SomeController', SomeController); + + function SomeController() { } + ``` + +### Определение и получение модулей +###### [Style [Y023](#style-y023)] + + - Определите модуль один раз и получайте его во всех других сущностях. + + *Почему?*: Модуль должен быть определен только один раз, а потом используйте его во всех остальных местах. + + - Используйте `angular.module('app', []);` для определения модуля. + - Используйте `angular.module('app');` чтобы получить модуль. + +### Именованные или Анонимные Функции +###### [Style [Y024](#style-y024)] + + - Используйте именованные функции, не передавайте анонимные функции обратного вызова в качестве параметров. + + *Почему?*: Так вы производите более читаемый код, его легче отлаживать, и это уменьшает число вложенных функций обратного вызова. + + ```javascript + /* избегайте этого */ + angular + .module('app') + .controller('Dashboard', function() { }) + .factory('logger', function() { }); + ``` + + ```javascript + /* рекомендовано */ + + // dashboard.js + angular + .module('app') + .controller('Dashboard', Dashboard); + + function Dashboard() { } + ``` + + ```javascript + // logger.js + angular + .module('app') + .factory('logger', logger); + + function logger() { } + ``` + +**[К Содержанию](#table-of-contents)** + +## Controllers + +### Синтаксис controllerAs в представлении +###### [Style [Y030](#style-y030)] + + - Используйте синтаксис [`controllerAs`](http://www.johnpapa.net/do-you-like-your-angular-controllers-with-or-without-sugar/), который работает поверх синтаксиса `классический контроллер со $scope`. + + *Почему?*: Контроллер создается, как JavaScript-объект с ключевым словом "new" и затем предоставляется этот единственный экземпляр объекта. То есть синтаксис `controllerAs` намного ближе и похожее на конструктор языка JavaScript, чем `классический синтаксис $scope`. + + *Почему?*: Это позволяет использовать в представлении связывание на свойство объекта "через точку" (например вместо `name` будет `customer.name`), что является более концептуальным, проще для чтения, и помогает избегать многих ссылочных проблем, которые могут возникнуть без использования "точки". + + *Почему?*: Помогает избежать использование вызовов `$parent` в представлениях с вложенными контроллерами. + + ```html + +
+ {{ name }} +
+ ``` + + ```html + +
+ {{ customer.name }} +
+ ``` + +### Синтаксис controllerAs в контроллере +###### [Style [Y031](#style-y031)] + + - Используйте синтаксис `controllerAs` поверх синтаксиса `классический контроллер со $scope`. + + - Синтаксис `controllerAs` использует внутри контроллеров ключевую переменную `this`, которая привязывается к `$scope`. + + *Почему?*: `controllerAs` - это только синтаксический сахар поверх `$scope`. Вы все равно можете использовать связывание в представлениях и все равно имеете доступ к методам `$scope`. + + *Почему?*: Избавляет от искушения использования методов `$scope` внутри контроллера, когда это не требуется явно, и это позволяет перенести методы в фабрику(factory). Предпочтительнее использовать `$scope` в фабрике, а в контроллере только если это действительно необходимо. Например, когда мы подписываемся и рассылаем события с помощью [`$emit`](https://docs.angularjs.org/api/ng/type/$rootScope.Scope#$emit), [`$broadcast`](https://docs.angularjs.org/api/ng/type/$rootScope.Scope#$broadcast), or [`$on`](https://docs.angularjs.org/api/ng/type/$rootScope.Scope#$on) перенесите эти сервисы в фабрику, и вызывайте методы фабрики в контроллере. + + ```javascript + /* избегайте этого */ + function Customer($scope) { + $scope.name = {}; + $scope.sendMessage = function() { }; + } + ``` + + ```javascript + /* рекомендовано - но изучите следующую секцию */ + function Customer() { + this.name = {}; + this.sendMessage = function() { }; + } + ``` + +### Синтаксис controllerAs с переменной vm +###### [Style [Y032](#style-y032)] + + - Сохраните `this` в переменную, когда используете синтаксис `controllerAs`. Выберите постоянное имя для переменной, такое как `vm`, что будет значить ViewModel. + + *Почему?*: Ключевое слово `this` контекстное, и когда его потребуется использовать внутри любой другой функции контроллера, то его содержимое будет другим. Сохранение `this` в переменной `vm` позволит избежать этих проблем. + + ```javascript + /* избегайте этого */ + function Customer() { + this.name = {}; + this.sendMessage = function() { }; + } + ``` + + ```javascript + /* рекомендовано */ + function Customer() { + var vm = this; + vm.name = {}; + vm.sendMessage = function() { }; + } + ``` + + Замечание: Вы можете избежать любые [jshint](http://www.jshint.com/) предупреждения, если разместите над строкой кода комментарий, как приведенный ниже в примере. Это не требуется, если функция названа с помощью ВерхнегоРегистра(UpperCasing), так как согласно этой конвециии, это значит, что функция является контруктором контроллера Angular. + + ```javascript + /* jshint validthis: true */ + var vm = this; + ``` + + Замечание: Когда создаете наблюдающие функции(watcher) в контроллерах типа `controller as`, вы можете наблюдать за переменной следующего вида `vm.*`. (Создавайте наблюдающие функции с предупреждением, что они создают дополнительную нагрузку на цикл digest.) + + ```html + + ``` + + ```javascript + function SomeController($scope, $log) { + var vm = this; + vm.title = 'Some Title'; + + $scope.$watch('vm.title', function(current, original) { + $log.info('vm.title was %s', original); + $log.info('vm.title is now %s', current); + }); + } + ``` + +### Привязываемые Члены Сверху +###### [Style [Y033](#style-y033)] + + - Помещайте привязываемые члены в верхней части контроллера, в алфавитном порядке, и не раскидывайте их в коде контроллера где попало. + + *Почему?*: Размещение привязываемых членов наверху, упрощает чтение и позволяет мгновенно определить, какие члены контроллера привязаны и используются в представлении. + + *Почему?*: Написание анонимных функций по месту использования может конечно и проще, но когда такие функции содержат много строк кода, то это значительно снижает читабельность кода. Определяйте функции ниже привязываемых членов, тем самым вы перенесете детали реализации вниз отдельно. Функции определяйте как hoisted, то есть они будут подняты наверх области видимости. А привязываемые члены наверху повысят читабельность кода. + + ```javascript + /* избегайте этого */ + function Sessions() { + var vm = this; + + vm.gotoSession = function() { + /* ... */ + }; + vm.refresh = function() { + /* ... */ + }; + vm.search = function() { + /* ... */ + }; + vm.sessions = []; + vm.title = 'Sessions'; + ``` + + ```javascript + /* рекомендовано */ + function Sessions() { + var vm = this; + + vm.gotoSession = gotoSession; + vm.refresh = refresh; + vm.search = search; + vm.sessions = []; + vm.title = 'Sessions'; + + //////////// + + function gotoSession() { + /* */ + } + + function refresh() { + /* */ + } + + function search() { + /* */ + } + ``` + + ![Controller Using "Above the Fold"](https://raw.githubusercontent.com/johnpapa/angularjs-styleguide/master/assets/above-the-fold-1.png) + + Замечание: Если функция однострочная, то разместите ее и наверху, но так чтобы это не усложняло читабельность. + + ```javascript + /* избегайте этого */ + function Sessions(data) { + var vm = this; + + vm.gotoSession = gotoSession; + vm.refresh = function() { + /** + * эти + * строки + * кода + * ухудшают + * читабельность + */ + }; + vm.search = search; + vm.sessions = []; + vm.title = 'Sessions'; + ``` + + ```javascript + /* рекомендовано */ + function Sessions(dataservice) { + var vm = this; + + vm.gotoSession = gotoSession; + vm.refresh = dataservice.refresh; // одна строка, все OK + vm.search = search; + vm.sessions = []; + vm.title = 'Sessions'; + ``` + +### Определения Функций Для Скрытия Деталей Реализации +###### [Style [Y034](#style-y034)] + + - Используйте определения функций для скрытия деталей реализации. Держите свои привязываемые члены наверху. Если нужно в контроллере сделать функцию привязываемой, укажите это в группе привязываемых членов и ссылайтесь на данную функцию, которая реализована ниже. Это подробно описано в секции Привязываемые Члены Сверху. Подробнее смотрите [здесь](http://www.johnpapa.net/angular-function-declarations-function-expressions-and-readable-code). + + *Почему?*: Размещение привязываемых членов наверху делает код читабельнее, и позволяет мгновенно определить, какие члены привязаны и используются в представлении. (Выше описано тоже самое.) + + *Почему?*: Размещение деталей реализации функции внизу скрывает эту сложность ниже и таким образом все важные вещи находятся на видном месте сверху. + + *Почему?*: Функции определены как hoisted (определены в самом верху области видимости), поэтому не надо заботиться об их использовании перед объявлением, так как это было бы с объявлениями выражений функций (function expressions). + + *Почему?*: Вам не надо волноваться, о том в каком порядке объявлены функции. Также как и изменение порядка функций не будет ломать код из-за зависимостей. + + *Почему?*: С выражениями функций(function expressions) порядок будет критичен. + + ```javascript + /** + * избегайте этого + * Использование выражений функций (function expressions). + */ + function Avengers(dataservice, logger) { + var vm = this; + vm.avengers = []; + vm.title = 'Avengers'; + + var activate = function() { + return getAvengers().then(function() { + logger.info('Activated Avengers View'); + }); + } + + var getAvengers = function() { + return dataservice.getAvengers().then(function(data) { + vm.avengers = data; + return vm.avengers; + }); + } + + vm.getAvengers = getAvengers; + + activate(); + } + ``` + + Заметьте, в предыдущем примере важный материал размещен в контроллере в разных местах. А в примере ниже, все важные моменты размещены сверху, в нашем случае, это члены, привязанные к контроллеру такие как `vm.avengers` и `vm.title`. Подробности реализации смещены вниз. Такой код проще читать. + + ```javascript + /* + * рекомендовано + * Объявления функций и + * привязанные члены смещены вверх. + */ + function Avengers(dataservice, logger) { + var vm = this; + vm.avengers = []; + vm.getAvengers = getAvengers; + vm.title = 'Avengers'; + + activate(); + + function activate() { + return getAvengers().then(function() { + logger.info('Activated Avengers View'); + }); + } + + function getAvengers() { + return dataservice.getAvengers().then(function(data) { + vm.avengers = data; + return vm.avengers; + }); + } + } + ``` + +### Логика Контроллера Отдельно +###### [Style [Y035](#style-y035)] + + - Переносите логику контроллера в сервисы и фабрики. + + *Почему?*: Логика может использоваться несколькими контроллерами, если она помещена в сервис и выставлена в виде функции. + + *Почему?*: Вся логика в сервисе может быть легко изолирована в модульном тесте, а вызовы этой логики в контроллере могут фиктивно реализованы (mocked). + + *Почему?*: Из контроллера удаляются зависимости и скрываются подробности реализации. + + ```javascript + + /* избегайте этого */ + function Order($http, $q, config, userInfo) { + var vm = this; + vm.checkCredit = checkCredit; + vm.isCreditOk; + vm.total = 0; + + function checkCredit() { + var settings = {}; + // Get the credit service base URL from config + // Set credit service required headers + // Prepare URL query string or data object with request data + // Add user-identifying info so service gets the right credit limit for this user. + // Use JSONP for this browser if it doesn't support CORS + return $http.get(settings) + .then(function(data) { + // Unpack JSON data in the response object + // to find maxRemainingAmount + vm.isCreditOk = vm.total <= maxRemainingAmount + }) + .catch(function(error) { + // Interpret error + // Cope w/ timeout? retry? try alternate service? + // Re-reject with appropriate error for a user to see + }); + }; + } + ``` + + ```javascript + /* рекомендовано */ + function Order(creditService) { + var vm = this; + vm.checkCredit = checkCredit; + vm.isCreditOk; + vm.total = 0; + + function checkCredit() { + return creditService.isOrderTotalOk(vm.total) + .then(function(isOk) { vm.isCreditOk = isOk; }) + .catch(showServiceError); + }; + } + ``` + +### Один Контроллер - Одно Представление +###### [Style [Y037](#style-y037)] + + - Определяйте контроллер для одного представления, и не пытайтесь использовать этот контроллер для других представлений. Вместо этого, выносите повторно используемую логику в фабрики. Старайтесь держать контроллер простым и сфокусированным только на свое представление. + + *Почему?*: Использование контроллера с несколькими представлениями хрупко и ненадежно. А для больших приложений требуется хорошее покрытие тестами end to end (e2e) для проверки стабильности. + +### Получение Контроллеров +###### [Style [Y038](#style-y038)] + + - Когда контроллер и его представление уже создано, и если нужно что-то повторно использовать (контроллер и представление), определяйте экземпляр контроллера вместе с его маршрутом (route). + + Замечание: Если представление загружается не через маршрут, тогда используйте синтаксис `ng-controller="Avengers as vm"`. + + *Почему?*: Указание экземпляра контроллера в определении маршрута позволяет различным маршрутам вызывать различные пары контроллеров и представлений. А когда контроллеры указаны в представлении с помощью [`ng-controller`](https://docs.angularjs.org/api/ng/directive/ngController), то представление будет всегда ассоциировано с одним и тем же контроллером. + + ```javascript + /* избегайте этого - когда используется маршрут и необходимо динамическое назначение контроллера и представления */ + + // route-config.js + angular + .module('app') + .config(config); + + function config($routeProvider) { + $routeProvider + .when('/avengers', { + templateUrl: 'avengers.html' + }); + } + ``` + + ```html + +
+
+ ``` + + ```javascript + /* рекомендовано */ + + // route-config.js + angular + .module('app') + .config(config); + + function config($routeProvider) { + $routeProvider + .when('/avengers', { + templateUrl: 'avengers.html', + controller: 'Avengers', + controllerAs: 'vm' + }); + } + ``` + + ```html + +
+
+ ``` + +**[К Содержанию](#table-of-contents)** + +## Services + +### Синглтоны +###### [Style [Y040](#style-y040)] + + - Сервисы создаются с помощью ключевого слова `new`. Используйте `this` для публичных методов и переменных. Так как они очень похожи на фабрики, то используйте фабрики для согласованности. + + Замечание: [Все AngularJS сервисы являются синглтонами](https://docs.angularjs.org/guide/services). Это значит, что создается только один экземпляр сервиса на один инжектор. + + ```javascript + // service + angular + .module('app') + .service('logger', logger); + + function logger() { + this.logError = function(msg) { + /* */ + }; + } + ``` + + ```javascript + // factory + angular + .module('app') + .factory('logger', logger); + + function logger() { + return { + logError: function(msg) { + /* */ + } + }; + } + ``` + +**[К Содержанию](#table-of-contents)** + +## Factories + +### Единственная Обязанность (Single Responsibility) +###### [Style [Y050](#style-y050)] + + - Фабрики дожны иметь [единственную обязанность](http://en.wikipedia.org/wiki/Single_responsibility_principle), это следует из их контекста. Если фабрика начинает превышать ту цель для которой она создана, то нужно создать другую фабрику. + +### Синглтон +###### [Style [Y051](#style-y051)] + + - Фабрики это синглтоны, которые возвращают объект, содержащий свойства и методы сервиса. + + Замечание: [Все AngularJS сервисы являются синглтонами](https://docs.angularjs.org/guide/services). + +### Доступные Члены Наверх +###### [Style [Y052](#style-y052)] + + - Помещайте вызываемые члены сервиса (интерфейс) наверх, используя технику [Revealing Module Pattern](http://addyosmani.com/resources/essentialjsdesignpatterns/book/#revealingmodulepatternjavascript). + + *Почему?*: Размещение вызываемых членов в верхней части улучшает читабельность и дает вам возможность быстро определить, какие члены сервиса могут быть вызваны и должны быть модульно оттестированы (либо фиктивно имплементированы - mocked). + + *Почему?*: Это особенно полезно, когда файл становится очень длинным, и вынуждает прокручивать текст кода, чтобы посмотреть, какие методы или свойства сервис предоставляет. + + *Почему?*: Размещение функций в обычном прямом порядке может быть и проще, но когда эти функции становятся многострочными, это снижает читабельность и вынуждает много скроллить. Определяя вызываемый интерфейс(в виде возвращаемого сервиса), вы убираете детали реализации вниз. А размещенный сверху интерфейс улучшает читабельность. + + ```javascript + /* избегайте этого */ + function dataService() { + var someValue = ''; + function save() { + /* */ + }; + function validate() { + /* */ + }; + + return { + save: save, + someValue: someValue, + validate: validate + }; + } + ``` + + ```javascript + /* рекомендовано */ + function dataService() { + var someValue = ''; + var service = { + save: save, + someValue: someValue, + validate: validate + }; + return service; + + //////////// + + function save() { + /* */ + }; + + function validate() { + /* */ + }; + } + ``` + +Такой способ привязки реализовывается во всем объекте, и приватные члены не моут быть изменены из-за примененного паттерна Revealing Module. + + ![Factories Using "Above the Fold"](https://raw.githubusercontent.com/johnpapa/angularjs-styleguide/master/assets/above-the-fold-2.png) + +### Определения Функций для Скрытия Деталей Реализации +###### [Style [Y053](#style-y053)] + + - Используйте определения функций, чтобы скрыть детали реализации. Держите вызываемые члены фабрики в верхней части. Свяжите их с определениями функций, которые распололжены ниже в файле. Подробную информацию смотрите [здесь](http://www.johnpapa.net/angular-function-declarations-function-expressions-and-readable-code). + + *Почему?*: Размещение вызываемых членов в верхней части улучшает читабельность и помогает быстро определить, какие функции фабрики могут быть вызваны извне. + + *Почему?*: Размещение функций с деталями реализации в нижней части файла выносит сложные вещи из поля зрения, так что только важные детали вы видите в верхней части файла. + + *Почему?*: Функции определены в самом верху области видимости (hoisted), то есть их можно вызывать до их определения. (что было бы не возможно с выражениями функций) + + *Почему?*: Вам не надо беспокоиться о порядке определений функций. Перестановка зависимых друг от друга функций не ломает код. + + *Why?*: А для выражений функций порядок критичен. + + ```javascript + /** + * избегайте этого + * Использование выражений функций + */ + function dataservice($http, $location, $q, exception, logger) { + var isPrimed = false; + var primePromise; + + var getAvengers = function() { + // детали реализации здесь + }; + + var getAvengerCount = function() { + // детали реализации здесь + }; + + var getAvengersCast = function() { + // детали реализации здесь + }; + + var prime = function() { + // детали реализации здесь + }; + + var ready = function(nextPromises) { + // детали реализации здесь + }; + + var service = { + getAvengersCast: getAvengersCast, + getAvengerCount: getAvengerCount, + getAvengers: getAvengers, + ready: ready + }; + + return service; + } + ``` + + ```javascript + /** + * рекомендовано + * Использование определений функций + * и вызываемые члены расположены в верхней части. + */ + function dataservice($http, $location, $q, exception, logger) { + var isPrimed = false; + var primePromise; + + var service = { + getAvengersCast: getAvengersCast, + getAvengerCount: getAvengerCount, + getAvengers: getAvengers, + ready: ready + }; + + return service; + + //////////// + + function getAvengers() { + // детали реализации здесь + } + + function getAvengerCount() { + // детали реализации здесь + } + + function getAvengersCast() { + // детали реализации здесь + } + + function prime() { + // детали реализации здесь + } + + function ready(nextPromises) { + // детали реализации здесь + } + } + ``` + +**[К Содержанию](#table-of-contents)** + +## Data Services + +### Отделите вызовы данных +###### [Style [Y060](#style-y060)] + + - Делайте рефакторинг логики работы с данными и взаимодействия этих данных с фабрикой. Создавайте сервисы данных, ответственных за вызовы XHR, локальное хранилище(local storage), работу с памятью или за любые другие операции с данными. + + *Почему?*: Ответственность контроллера - это предоставление или сбор информации для представления. Он не должен заботиться о том, как работать с данными, он только должен знать кого попросить об этом. В сервисы для данных переносится вся логика работы с данными. Это делает контроллер более простым и более сфокусированным для работы с представлением. + + *Почему?*: Это позволяет более проще тестировать (фиктивно или реально) вызовы данных в контроллере, который использует сервис для данных. + + *Почему?*: Реализация сервиса данных может иметь очень специфичный код для операций с хранилищем данных. Могут использоваться заголовки для взаимодействовия с данными, или другие сервисы типа $http. Логика в сервисе данных инкапсулируется в одном месте и скрывает реализацию для внешних потребителей (контроллеров), также будет гораздо проще изменить реализацию в случае необходимости. + + ```javascript + /* рекомендовано */ + + // фабрика сервиса данных + angular + .module('app.core') + .factory('dataservice', dataservice); + + dataservice.$inject = ['$http', 'logger']; + + function dataservice($http, logger) { + return { + getAvengers: getAvengers + }; + + function getAvengers() { + return $http.get('/api/maa') + .then(getAvengersComplete) + .catch(getAvengersFailed); + + function getAvengersComplete(response) { + return response.data.results; + } + + function getAvengersFailed(error) { + logger.error('XHR Failed for getAvengers.' + error.data); + } + } + } + ``` + + Замечание: Сервис данных вызывается потребителем (контроллером), и скрывает реализацию от потребителя. Это показано ниже. + + ```javascript + /* рекомендовано */ + + // контроллер вызывает фабрику сервиса данных + angular + .module('app.avengers') + .controller('Avengers', Avengers); + + Avengers.$inject = ['dataservice', 'logger']; + + function Avengers(dataservice, logger) { + var vm = this; + vm.avengers = []; + + activate(); + + function activate() { + return getAvengers().then(function() { + logger.info('Activated Avengers View'); + }); + } + + function getAvengers() { + return dataservice.getAvengers() + .then(function(data) { + vm.avengers = data; + return vm.avengers; + }); + } + } + ``` + +### Возвращение Объекта Promise для Контроллера +###### [Style [Y061](#style-y061)] + + - Если сервис данных возвращает promise типа $http, то в вызывающей функции возвращайте promise тоже. + + *Почему?*: Вы можете объединить в цепочку объекты promise, и после того как вызов данных закончится, выполнить дальнейшие действия для принятия или отклонения объекта promise. + + ```javascript + /* рекомендовано */ + + activate(); + + function activate() { + /** + * Шаг 1 + * Запрашиваем функцию getAvengers function + * для получения данных и ждем promise + */ + return getAvengers().then(function() { + /** + * Шаг 4 + * Выполняем действие принятия финального объекта promise + */ + logger.info('Activated Avengers View'); + }); + } + + function getAvengers() { + /** + * Шаг 2 + * Запрашиваем сервис для данных + * и ждем promise + */ + return dataservice.getAvengers() + .then(function(data) { + /** + * Шаг 3 + * инициализируем данные и принимаем promise + */ + vm.avengers = data; + return vm.avengers; + }); + } + ``` + +**[К Содержанию](#table-of-contents)** + +## Directives +### Одна Директива - Один Файл +###### [Style [Y070](#style-y070)] + + - Создавайте только одну директиву в файле. Называйте файл именем директивы. + + *Почему?*: Конечно можно поместить директивы в один файл. Но потом их трудно будет разделить по приложениям, и по модулям. Например, нужна будет только одна из директив для определенного модуля. + + *Почему?*: Одну директиву в файле легче поддерживать. + + ```javascript + /* избегайте этого */ + /* directives.js */ + + angular + .module('app.widgets') + + /* директива для заказа, которая специфична для модуля заказов */ + .directive('orderCalendarRange', orderCalendarRange) + + /* директива продажи, которая может быть использована везде в модуле продаж */ + .directive('salesCustomerInfo', salesCustomerInfo) + + /* директива крутилки (spinner), которая может быть использована во всех модулях */ + .directive('sharedSpinner', sharedSpinner); + + function orderCalendarRange() { + /* детали реализации */ + } + + function salesCustomerInfo() { + /* детали реализации */ + } + + function sharedSpinner() { + /* детали реализации */ + } + ``` + + ```javascript + /* рекомендовано */ + /* calendarRange.directive.js */ + + /** + * @desc директива заказа, которая специфична модулю заказов в компании Acme + * @example
+ */ + angular + .module('sales.order') + .directive('acmeOrderCalendarRange', orderCalendarRange); + + function orderCalendarRange() { + /* детали реализации */ + } + ``` + + ```javascript + /* рекомендовано */ + /* customerInfo.directive.js */ + + /** + * @desc директива продажи, которая может быть использована везде в модуле продаж компании Acme + * @example
+ */ + angular + .module('sales.widgets') + .directive('acmeSalesCustomerInfo', salesCustomerInfo); + + function salesCustomerInfo() { + /* implementation details */ + } + ``` + + ```javascript + /* рекомендовано */ + /* spinner.directive.js */ + + /** + * @desc директива крутилки (spinner), которая может быть использована во всех модулях компании Acme + * @example
+ */ + angular + .module('shared.widgets') + .directive('acmeSharedSpinner', sharedSpinner); + + function sharedSpinner() { + /* детали реализации */ + } + ``` + + Замечание: Существует много способов для именования директив, особенно это зависит от широты области использования (локально или глобально). Выбирайте тот способ, который определяет директиву и ее файл четко и ясно. Несколько примеров будет ниже, но в основном смотрите рекомендации в секции именований. + +### Манипулирование Элементами DOM в Директиве +###### [Style [Y072](#style-y072)] + + - Используйте директивы, если нужно манипулировать элементами DOM напрямую. Но если существуют альтернативные способы, то используйте лучше их. Например, для изменения стилей используйте CSS, для эффектов [сервисы анимации](https://docs.angularjs.org/api/ngAnimate), для управления видимостью используйте [`ngShow`](https://docs.angularjs.org/api/ng/directive/ngShow) и [`ngHide`](https://docs.angularjs.org/api/ng/directive/ngHide). + + *Почему?*: Манипулирование элементами DOM тяжело тестить, отлаживать, и зачастую существуют более лучшие способы для реализации поставленной задачи (например CSS, анимации, шаблоны) + +### Добавляйте Директивам Уникальный Префикс +###### [Style [Y073](#style-y073)] + + - Добавляйте директивам короткий, уникальный, пояснительный префикс, такой как `acmeSalesCustomerInfo`, директива будет объявлена в HTML как `acme-sales-customer-info`. + + *Почему?*: Уникальный короткий префикс говорит о контексте и происхождении директивы. Например, префикс `cc-` может рассказать нам, что директива является частью приложения CodeCamper, а `acme-` это директива для компании Acme. + + Замечание: Не используйте префикс `ng-` для своих директив, так как он зарезервирован для директив AngularJS. Также исследуйте префиксы широко используемых директив для избежания конфликтов имен, например, префикс `ion-` используется для директив [Ionic Framework](http://ionicframework.com/). + +### Ограничивайте Элементы и Атрибуты +###### [Style [Y074](#style-y074)] + + - При создании директивы, которая планируется как самостоятельный элемент, применяйте ограничение `E` (разработано, как элемент) или по необходимости ограничение `A` (разработано, как атрибут). В основном, если директива разрабатывается как элемент, ограничения `E` вполне достаточно. Хотя AngularJS позволяет использовать `EA`, но все же лучше определится как реализовывать директиву, либо как самостоятельный отдельный элемент, либо как атрибут для улучшения функциональности существующего DOM-элемента. + + *Почему?*: Это имееет смысл. + + *Почему?*: Конечно мы можем использовать директиву в атрибуте class, но если директива действует как элемент, то лучше объявлять ее как элемент, ну или по крайней мере как атрибут. + + Замечание: EA используется по умолчанию для AngularJS 1.3 + + + ```html + +
+ ``` + + ```javascript + /* избегайте этого */ + angular + .module('app.widgets') + .directive('myCalendarRange', myCalendarRange); + + function myCalendarRange() { + var directive = { + link: link, + templateUrl: '/template/is/located/here.html', + restrict: 'C' + }; + return directive; + + function link(scope, element, attrs) { + /* */ + } + } + ``` + + ```html + + +
+ ``` + + ```javascript + /* рекомендовано */ + angular + .module('app.widgets') + .directive('myCalendarRange', myCalendarRange); + + function myCalendarRange() { + var directive = { + link: link, + templateUrl: '/template/is/located/here.html', + restrict: 'EA' + }; + return directive; + + function link(scope, element, attrs) { + /* */ + } + } + ``` + +### Директивы и ControllerAs +###### [Style [Y075](#style-y075)] + + - Используйте синтактис`controller as` в директиве, чтобы директива была согласована с использованием синтаксиса `controller as` в паре контроллера и представлении. + + *Почему?*: Это имет смысл и не так сложно. + + Замечание: Директива ниже демонстрирует некоторые способы, при которых вы можете использовать объект $scope внутри ссылки и контроллере директивы. Я сделал инлайновый шаблон для того, чтобы держать все в одном месте. + + Замечание: Что касается внедренной зависимости, смотрите [Определение зависимостей вручную](#manual-annotating-for-dependency-injection). + + Замечание: Заметьте, что контроллер директивы находится снаружи самой директивы. Такой подход исключает проблемы, когда инжектор создается в недосягаемом код после, например, 'return'. + + ```html +
+ ``` + + ```javascript + angular + .module('app') + .directive('myExample', myExample); + + function myExample() { + var directive = { + restrict: 'EA', + templateUrl: 'app/feature/example.directive.html', + scope: { + max: '=' + }, + link: linkFunc, + controller: ExampleController, + controllerAs: 'vm' + }; + + return directive; + + function linkFunc(scope, el, attr, ctrl) { + console.log('LINK: scope.max = %i', scope.max); + console.log('LINK: scope.vm.min = %i', scope.vm.min); + console.log('LINK: scope.vm.max = %i', scope.vm.max); + } + } + + ExampleController.$inject = ['$scope']; + + function ExampleController($scope) { + // Внедрение $scope сразу для параметра сравнения + var vm = this; + + vm.min = 3; + vm.max = $scope.max; + console.log('CTRL: $scope.max = %i', $scope.max); + console.log('CTRL: vm.min = %i', vm.min); + console.log('CTRL: vm.max = %i', vm.max); + } + ``` + + ```html + /* example.directive.html */ +
hello world
+
max={{vm.max}}
+
min={{vm.min}}
+ ``` + +**[К Содержанию](#table-of-contents)** + +## Resolving Promises for a Controller + +### Активация объектов promise в контроллере +###### [Style [Y080](#style-y080)] + + - Размещайте стартовую начальную логику для контроллера в функции `activate`. + + *Почему?*: Размещение стартовой логики в согласованом месте контроллера позволяет ее быстрее находить, более согласованно тестить, и позволить не разбразывать по всему контроллеру логику активации. + + *Почему?*: Функция `activate` делает удобным повторное использование логики для обновления контроллера/представления, держит все логику вместе, делает более быстрой работу пользователя с представлением, делает анимацию более простой в директивами `ng-view` и `ui-view`, ну и делает ориентирование разработчика в коде более энергичным и быстрым. + + Замечание: Если вам нужно при каком-то условии отменить маршрут перед началом использования контроллера, используйте для этого [route resolve](#style-y081). + + ```javascript + /* избегайте этого */ + function Avengers(dataservice) { + var vm = this; + vm.avengers = []; + vm.title = 'Avengers'; + + dataservice.getAvengers().then(function(data) { + vm.avengers = data; + return vm.avengers; + }); + } + ``` + + ```javascript + /* рекомендовано */ + function Avengers(dataservice) { + var vm = this; + vm.avengers = []; + vm.title = 'Avengers'; + + activate(); + + //////////// + + function activate() { + return dataservice.getAvengers().then(function(data) { + vm.avengers = data; + return vm.avengers; + }); + } + } + ``` + +### Работа с Объектами Promise в Маршрутах +###### [Style [Y081](#style-y081)] + + - Если контроллер зависит от объекта promise, от результата которого зависит активация контроллера, то разрешайте/получайте эти зависимости в `$routeProvider`, перед тем как логика контроллера будет выполена. Если вам нужно по какому-то условию отменить маршрут перед активацией контроллера, то используйте обработчик маршрутов. + + - Используйте обработчик маршрутов, если вы решили в последствии отменить маршут до перехода к представлению. + + *Почему?*: Контроллер может потребовать данные перед своей загрузкой. Эти данные могут прийти из promise объекта через пользовательскую фабрику или [$http](https://docs.angularjs.org/api/ng/service/$http). Использование [route resolve](https://docs.angularjs.org/api/ngRoute/provider/$routeProvider) дает возможность объекту promise разрешиться перед тем, как логика контроллера выполнится, тогда мы сможем выполнить действие, зависящее от результата объекта promise. + + *Почему?*: Код выполняется после маршрута и в активационной функции контроллера. После этого, сразу же начинает загружаться представление. Связывание данных начинается, когда активационнный объект promisе разрешился/выполнился. Анимация "прогресса" может быть показана время передачи представления (via ng-view or ui-view). + + Замечание: Код запускается перед маршрутом через объект promise. Отклонение promise отменяет маршрут. Разрешение заставляет ожидать новое представление, когда маршрут разрешится. Анимация “прогресса” может быть показана перед разрешением и через передачу представления. Если вам нужно получить представление быстрее и вам не нужна точка решения, получать ли представление, используйте тогда [controller `activate` technique](#style-y080). + + ```javascript + /* избегайте этого */ + angular + .module('app') + .controller('Avengers', Avengers); + + function Avengers(movieService) { + var vm = this; + // не определено + vm.movies; + // определено асинхронно + movieService.getMovies().then(function(response) { + vm.movies = response.movies; + }); + } + ``` + + ```javascript + /* это лучше */ + + // route-config.js + angular + .module('app') + .config(config); + + function config($routeProvider) { + $routeProvider + .when('/avengers', { + templateUrl: 'avengers.html', + controller: 'Avengers', + controllerAs: 'vm', + resolve: { + moviesPrepService: function(movieService) { + return movieService.getMovies(); + } + } + }); + } + + // avengers.js + angular + .module('app') + .controller('Avengers', Avengers); + + Avengers.$inject = ['moviesPrepService']; + function Avengers(moviesPrepService) { + var vm = this; + vm.movies = moviesPrepService.movies; + } + ``` + + Замечание: В примере ниже показано, как разрешение маршрута указывает на именованную функцию, которую легче отлаживать и легче оперировать встроенной зависимостью. + + ```javascript + /* еще лучше */ + + // route-config.js + angular + .module('app') + .config(config); + + function config($routeProvider) { + $routeProvider + .when('/avengers', { + templateUrl: 'avengers.html', + controller: 'Avengers', + controllerAs: 'vm', + resolve: { + moviesPrepService: moviesPrepService + } + }); + } + + function moviePrepService(movieService) { + return movieService.getMovies(); + } + + // avengers.js + angular + .module('app') + .controller('Avengers', Avengers); + + Avengers.$inject = ['moviesPrepService']; + function Avengers(moviesPrepService) { + var vm = this; + vm.movies = moviesPrepService.movies; + } + ``` + Замечание: Пример кода зависимости от `movieService` не безопасен для минификации. Подробности от том как сделать этот код безопасным для минификации, смотрите секции [dependency injection](#manual-annotating-for-dependency-injection) и [minification and annotation](#minification-and-annotation). + +**[К Содержанию](#table-of-contents)** + +## Manual Annotating for Dependency Injection + +### Уязвимости от Минификации +###### [Style [Y090](#style-y090)] + + - Избегайте объявления зависимостей без использования безопасного для минификации подхода. + + *Почему?*: Параметры для компонент (типа контроллер, фабрика и т.п.) будут преобразованы в усеченные переменные. Например, `common` и `dataservice` превратятся `a` или `b` и не будут найдены средой AngularJS. + + ```javascript + /* избегайте этого - не безопасно для минификации */ + angular + .module('app') + .controller('Dashboard', Dashboard); + + function Dashboard(common, dataservice) { + } + ``` + + После минификации будут производится усеченные переменные и это будет вызывать ошибки выполнения. + + ```javascript + /* избегайте этого- не безопасно для минификации */ + angular.module('app').controller('Dashboard', d);function d(a, b) { } + ``` + +### Определяйте Зависимости Вручную +###### [Style [Y091](#style-y091)] + + - Используйте `$inject` для ручного определения ваших зависимостей для AngulaJS. + + *Почему?*: Этот техника отражает технику использованную в [`ng-annotate`](https://github.com/olov/ng-annotate), которую я рекомендую для автоматического создания зависимостей, безопасных для минификации. Если `ng-annotate` обнаруживает вставку(injection), которая уже была, то она не будет продублирована. + + *Почему?*: Это гарантирует вашим зависимостям защиту от повреждений, которую может нанести минификация, путем урезания и укорачивания переменных. Например, `common` и `dataservice` превратятся `a` и `b`, и не будут найдены средой AngularJS. + + *Почему?*: Избегайте создания однострочных зависимостей в виде длинных списков, которые трудно читаемы в массиве. Еще в вводят в конфуз, то что такие массивы состоят из элементов строк, а последний элемент - это функция. + + ```javascript + /* избегайте этого */ + angular + .module('app') + .controller('Dashboard', + ['$location', '$routeParams', 'common', 'dataservice', + function Dashboard($location, $routeParams, common, dataservice) {} + ]); + ``` + + ```javascript + /* избегайте этого */ + angular + .module('app') + .controller('Dashboard', + ['$location', '$routeParams', 'common', 'dataservice', Dashboard]); + + function Dashboard($location, $routeParams, common, dataservice) { + } + ``` + + ```javascript + /* рекомендовано */ + angular + .module('app') + .controller('Dashboard', Dashboard); + + Dashboard.$inject = ['$location', '$routeParams', 'common', 'dataservice']; + + function Dashboard($location, $routeParams, common, dataservice) { + } + ``` + + Замечание: Если функция снизу является возращаемым значением, то $inject может быть недостижымым (это может случится в директиве). Это можно решить перемещением $inject выше, чем возращаемое значение, либо использовать альтернативный синтаксис массива вставок. + + Замечание: [`ng-annotate 0.10.0`](https://github.com/olov/ng-annotate) ввело возможность, когда `$inject` переносится туда, где оно доступно. + + ```javascript + // внутри определения директивы + function outer() { + return { + controller: DashboardPanel, + }; + + DashboardPanel.$inject = ['logger']; // Недоступный код + function DashboardPanel(logger) { + } + } + ``` + + ```javascript + // внутри определения директивы + function outer() { + DashboardPanel.$inject = ['logger']; // Доступный код + return { + controller: DashboardPanel, + }; + + function DashboardPanel(logger) { + } + } + ``` + +### Определяйте Маршрутных Обработчиков Зависимостей Вручную +###### [Style [Y092](#style-y092)] + + - Используйте $inject, чтобы вручную определить ваш маршрутный обработчик зависимостей для компонентов AngularJS. + + *Почему?*: Эта техника убирает анонимные функции для маршрутных обработчиков, делая чтение такого код проще. + + *Почему?*: Оператор $inject` может предшествовать обработчику для того, чтобы сделать любую минификацию зависимостей безопасной. + + ```javascript + /* рекомендовано */ + function config($routeProvider) { + $routeProvider + .when('/avengers', { + templateUrl: 'avengers.html', + controller: 'Avengers', + controllerAs: 'vm', + resolve: { + moviesPrepService: moviePrepService + } + }); + } + + moviePrepService.$inject = ['movieService']; + function moviePrepService(movieService) { + return movieService.getMovies(); + } + ``` + +**[К Содержанию](#table-of-contents)** + +## Minification and Annotation + +### ng-annotate +###### [Style [Y100](#style-y100)] + + - Используйте [ng-annotate](//github.com/olov/ng-annotate) для [Gulp](http://gulpjs.com) или [Grunt](http://gruntjs.com) и комментируйте функции, которые нуждаются в автоматической вставке зависимостей, используйте `/** @ngInject */`. + + *Why?*: Это гарантирует, что в вашем коде нет зависимостей, которые не используют защиту для повреждений от минификации. + + *Why?*: [`ng-min`](https://github.com/btford/ngmin) не рекомендуется для применения, выводится из употребления + + >Я предпочитаю Gulp, так как для меня он проще для чтения, написания кода и отладки. + + Следующий код не использует защиту зависимостей от минификации. + + ```javascript + angular + .module('app') + .controller('Avengers', Avengers); + + /* @ngInject */ + function Avengers(storageService, avengerService) { + var vm = this; + vm.heroSearch = ''; + vm.storeHero = storeHero; + + function storeHero() { + var hero = avengerService.find(vm.heroSearch); + storageService.save(hero.name, hero); + } + } + ``` + + Если код выше запустить через ng-annotate, то будет произведен код с аннотацией `$inject`, и код станет устойчив к минификации. + + ```javascript + angular + .module('app') + .controller('Avengers', Avengers); + + /* @ngInject */ + function Avengers(storageService, avengerService) { + var vm = this; + vm.heroSearch = ''; + vm.storeHero = storeHero; + + function storeHero() { + var hero = avengerService.find(vm.heroSearch); + storageService.save(hero.name, hero); + } + } + + Avengers.$inject = ['storageService', 'avengerService']; + ``` + + Замечание: Если `ng-annotate` обнаруживает вставки которые уже сделаны (например `@ngInject` был обнаружен), он не будет дублирован в коде `$inject`. + + Замечание: Если используется маршрутный обработчик, то вы можете перед встраиваемой функцией подставить `/* @ngInject */` и это будет производить корректный аннотационный код, делающий каждую вставленную зависимость безопасной для минификации. + + ```javascript + // Используем @ngInject аннотацию + function config($routeProvider) { + $routeProvider + .when('/avengers', { + templateUrl: 'avengers.html', + controller: 'Avengers', + controllerAs: 'vm', + resolve: { /* @ngInject */ + moviesPrepService: function(movieService) { + return movieService.getMovies(); + } + } + }); + } + ``` + + > Замечание: Начиная с AngularJS 1.3 используйте [`ngApp`](https://docs.angularjs.org/api/ng/directive/ngApp) директивный параметр `ngStrictDi`. При наличии инжектора будет создан режим "strict-di", который не даст приложению работать, если обнаружит функции, которые не используют явные аннотации (например, для защиты от минификации). Отладочная информация будет отображаться в консоли, чтобы помочь разработчику выявить код, ломающий приложение. + `` + +### Используйте Gulp или Grunt для ng-annotate +###### [Style [Y101](#style-y101)] + + - Используйте [gulp-ng-annotate](https://www.npmjs.org/package/gulp-ng-annotate) или [grunt-ng-annotate](https://www.npmjs.org/package/grunt-ng-annotate) для автоматических билдов. Вставляйте `/* @ngInject */` перед любой функцией, которая имеет зависимости. + + *Почему?*: ng-annotate будет отлавливать большинство зависимостей, но иногда требуются вставлять подсказки в виде синтаксиса `/* @ngInject */`. + + Следующий код является примером gulp задания с использованием ngAnnotate. + + ```javascript + gulp.task('js', ['jshint'], function() { + var source = pkg.paths.js; + return gulp.src(source) + .pipe(sourcemaps.init()) + .pipe(concat('all.min.js', {newLine: ';'})) + // Annotate before uglify so the code get's min'd properly. + .pipe(ngAnnotate({ + // true helps add where @ngInject is not used. It infers. + // Doesn't work with resolve, so we must be explicit there + add: true + })) + .pipe(bytediff.start()) + .pipe(uglify({mangle: true})) + .pipe(bytediff.stop()) + .pipe(sourcemaps.write('./')) + .pipe(gulp.dest(pkg.paths.dev)); + }); + + ``` + +**[К Содержанию](#table-of-contents)** + +## Exception Handling + +### декораторы +###### [Style [Y110](#style-y110)] + + - Используйте [decorator](https://docs.angularjs.org/api/auto/service/$provide#decorator), во время конфигурации, применяя сервис [`$provide`](https://docs.angularjs.org/api/auto/service/$provide), пользовательские действия будут происходить в сервисе [`$exceptionHandler`](https://docs.angularjs.org/api/ng/service/$exceptionHandler), если произойдут исключения. + + *Почему?*: Это дает постоянный надежный способ обработки необработанных исключений AngularJS во время разработки и во время выполнения. + + Замечание: Другим способом является переопределение сервиса, вместо использования декоратора. Это прекрасный способ, но если вы хотите сохранить поведение по умолчанию, и просто дополнить это поведение, то декоратоор крайне рекомендуем. + + ```javascript + /* рекомендовано */ + angular + .module('blocks.exception') + .config(exceptionConfig); + + exceptionConfig.$inject = ['$provide']; + + function exceptionConfig($provide) { + $provide.decorator('$exceptionHandler', extendExceptionHandler); + } + + extendExceptionHandler.$inject = ['$delegate', 'toastr']; + + function extendExceptionHandler($delegate, toastr) { + return function(exception, cause) { + $delegate(exception, cause); + var errorData = { + exception: exception, + cause: cause + }; + /** + * Здесь можно добавить ошибку в сервисную коллекцию, + * добавить ошибки в $rootScope, логировать ошибки на удаленный сервер + * или записывать их локально. Или просто бросить ошибку дальше. Это полностью зависит от вас. + * throw exception; + */ + toastr.error(exception.msg, errorData); + }; + } + ``` + +### Обработчики Исключений +###### [Style [Y111](#style-y111)] + + - Создайте фабрику, которая предоставит интерфейс для перехвата и изящной обработки исключений. + + *Почему?*: Это дает постоянный и надежный способ для перехвата исключений, которые могут возникнуть в вашем коде (например, во время вызовов объекта XHR или сбоев в работе объектов promise). + + Замечание: Перехватчик исключений хорош для отлавливания и реагирования на специфические исключения для вызовов, про которые вы точно знаете, что они могут бросить только одно исключение. Например, вы делаете вызов XHR для получения данных с удаленного сервера и хотите поймать все исключения этого сервиса и обработать их индивидуально. + + ```javascript + /* рекомендовано */ + angular + .module('blocks.exception') + .factory('exception', exception); + + exception.$inject = ['logger']; + + function exception(logger) { + var service = { + catcher: catcher + }; + return service; + + function catcher(message) { + return function(reason) { + logger.error(message, reason); + }; + } + } + ``` + +### Маршрутные ошибки +###### [Style [Y112](#style-y112)] + + - Обрабатывайте и логгируйте все маршрутные ошибки используя [`$routeChangeError`](https://docs.angularjs.org/api/ngRoute/service/$route#$routeChangeError). + + *Почему?*: Это дает постоянный и устойчивый способ обработки всех маршрутных ошибок. + + *Почему?*: Потенциально мы получим лучший способ обработки маршрутных ошибок и научимся перенаправлять их на более дружественный экран описания ошибки с большими подробностями и указаниями к восстановлению до нормальной ситуации. + + ```javascript + /* рекомендовано */ + function handleRoutingErrors() { + /** + * Отмена маршрута: + * Во время маршрутной ошибки, мы переходим на информационную панель. + * Не забудьте реализовать выход, если происходит попытка перехода дважды. + */ + $rootScope.$on('$routeChangeError', + function(event, current, previous, rejection) { + var destination = (current && (current.title || current.name || current.loadedTemplateUrl)) || + 'unknown target'; + var msg = 'Error routing to ' + destination + '. ' + (rejection.msg || ''); + /** + * Опционально мы можем записать логи, используя пользовательский сервис или $log. + * (Не забудьте инжектировать пользовательский сервис) + */ + logger.warning(msg, [current]); + } + ); + } + ``` + +**[К Содержанию](#table-of-contents)** + +## Naming + +### Рекомендации для именований +###### [Style [Y120](#style-y120)] + + - Используйте согласованные имена для всех компонентов по шаблону, который описывает особенность(feature) компонента, а затем (опционально) его тип. Я рекомендую шаблон - `feature.type.js`. Существует два типа имен для большинства случаев: + * имя файла (`avengers.controller.js`) + * имя компонента, которое зарегистрировано Angular (`AvengersController`) + + *Почему?*: Соглашения об именованиях дает постояннный надежный способ поиска содержимого быстрым беглым взглядом. Согласованность в проекте жизненно важна. Согласованность в команде очень важна. Согласованность между компаниями дает огромную эффективность. + + *Почему?*: Соглашения об именованиях просто должны помочь найти вам свой код быстрее, и сделать его проще для понимания. +### Характерные Имена Файлов +###### [Style [Y121](#style-y121)] + + - Используйте согласованные имена для всех компонентов используя шаблон, который описывает компонентную особенность, затем опционально его тип. Я рекомендую шаблон - `feature.type.js`. + + *Почему?*: Это надежный способ для быстрой идентификации компонентов. + + *Почему?*: Автоматизирует рабочий процесс. + + ```javascript + /** + * общие настройки + */ + + // Контроллеры + avengers.js + avengers.controller.js + avengersController.js + + // Сервисы/Фабрики + logger.js + logger.service.js + loggerService.js + ``` + + ```javascript + /** + * рекомендовано + */ + + // контроллеры + avengers.controller.js + avengers.controller.spec.js + + // сервисы/фабрики + logger.service.js + logger.service.spec.js + + // константы + constants.js + + // определение модуля + avengers.module.js + + // маршруты + avengers.routes.js + avengers.routes.spec.js + + // конфигурация + avengers.config.js + + // директивы + avenger-profile.directive.js + avenger-profile.directive.spec.js + ``` + + Замечание: Другим общим соглашением является именование файлов контроллера без слова `controller`, например, называем файл `avengers.js` вместо `avengers.controller.js`. Все остальные соглашения все же должны содержать суффикс типа. Просто контроллеры наиболее общий тип компонентов, и таким образом, мы экономим время печатая имя, но контроллеры все равно прекрасно идентифицируются. Я рекомендую выбрать один тип соглашения и быть на одной волне со своей командой. + + ```javascript + /** + * рекомендовано + */ + // Controllers + avengers.js + avengers.spec.js + ``` + +### Имена Тестовых Файлов +###### [Style [Y122](#style-y122)] + + - Имя тестовой спецификации подобно имени компонента, которая его тестит, только к ней еще добавляется суффикс `spec`. + + *Почему?*: Это надежный способ для быстрой идентификации компонентов. + + *Why?*: Это шаблон соответствующий [karma](http://karma-runner.github.io/) или другим движкам для запуска тестов. + + ```javascript + /** + * рекомендовано + */ + avengers.controller.spec.js + logger.service.spec.js + avengers.routes.spec.js + avenger-profile.directive.spec.js + ``` + +### Имена Контроллеров +###### [Style [Y123](#style-y123)] + + - Используйте согласованные имена для всех контроллеров, именованных по их характерной особенности. Используйте UpperCamelCase (ВерхнийВерблюжийРегистр) для контроллеров, так как они являются конструкторами. + + *Почему?*: Это дает надежный и понятный способ для быстрой идентификации и применения контроллеров. + + *Почему?*: UpperCamelCase является традиционным форматом для идентификации объектов, которые могут быть созданы с помощью конструктора. + + ```javascript + /** + * рекомендовано + */ + + // avengers.controller.js + angular + .module + .controller('HeroAvengers', HeroAvengers); + + function HeroAvengers() { } + ``` + +### Суффикс Имени Контроллера +###### [Style [Y124](#style-y124)] + + - Добавляйте к имени контроллера суффикс `Controller` или не добавляйте. Выберите одно правило т придерживайтесь его везде. + + *Почему?*: Суффикс `Controller` более общеупотребим и наиболее явно описателен. + + *Почему?*: Если не указывать суффикс, то получатся более краткие имена, но контроллеры все равно будут легко идентифицируемы, даже без суффикса. + + ```javascript + /** + * рекомендовано: Вариант 1 + */ + + // avengers.controller.js + angular + .module + .controller('Avengers', Avengers); + + function Avengers() { } + ``` + + ```javascript + /** + * рекомендовано: Вариант 2 + */ + + // avengers.controller.js + angular + .module + .controller('AvengersController', AvengersController); + + function AvengersController() { } + ``` + +### Имена Фабрик +###### [Style [Y125](#style-y125)] + + - Используйте согласованные имена для всех фабрик, именуйте их по характерной особенности. Используйте camel-casing для сервисов и фабрик. + + *Почему?*: Это дает надежный и понятный способ для быстрой идентификации и применения фабрик. + + ```javascript + /** + * рекомендовано + */ + + // logger.service.js + angular + .module + .factory('logger', logger); + + function logger() { } + ``` + +### Имена Директивных Компонент +###### [Style [Y126](#style-y126)] + + - Используйте согласованные имена для всех директив, применяя camel-case. Добавляйте короткий префикс для описания области, которой эти директивы принадлежат (иногда это может быть префикс компании, иногда префикс проекта). + + *Почему?*: Это дает надежный и понятный способ для быстрой идентификации и применения компонент. + + ```javascript + /** + * рекомендовано + */ + + // avenger-profile.directive.js + angular + .module + .directive('xxAvengerProfile', xxAvengerProfile); + + // применять так + + function xxAvengerProfile() { } + ``` + +### Модули +###### [Style [Y127](#style-y127)] + + - Если разрабатываются несколько модулей, файл главного модуля будет называться `app.module.js`, а другие модули получат свое название по своему назначению (то что они представляют). Например, модуль администрирования будет назван `admin.module.js`. Соответствующие зарегистрированные имена модулей будут `app` и `admin`. + + *Почему?*: Это дает согласованность для многих модулей приложения, а также позволяет расширяться в огромные приложения. + *Почему?*: Получаем простой способ автоматизировать работу для первоначальной загрузки всех модульных определений, а затем уже остальных файлов angular. + +### Конфигурация +###### [Style [Y128](#style-y128)] + + - Отделяйте конфигурационную информацию от модуля в отдельном файле, называйте такой файл по названию модульного файла. Конфигурационный файл для главного `app` модуля называем `app.config.js` (или просто `config.js`). Конфигурацию для модуля `admin.module.js` называем соответственно `admin.config.js`. + + *Почему?*: Конфигурация отделяется от определения модуля, компонентов и активного кода. + + *Why?*: Мы получаем идентифицируемое место для установки конфигурации модуля. + +### Маршруты +###### [Style [Y129](#style-y129)] + + - Выделяйте конфигурацию маршрута в свой собственный файл. Примеры могут быть такими: `app.route.js` для главного модуля и `admin.route.js` для модуля `admin`. Даже в маленьких приложениях я предпочитаю такое разделение от остальной конфигурации. + +**[К Содержанию](#table-of-contents)** + +## Application Structure LIFT Principle +### LIFT +###### [Style [Y140](#style-y140)] + + - Структура вашего приложения должна быть построена таким образом, чтобы вы могли: `L` - размещать ваш код быстро (`L`ocate your code quickly), `I` - идентифицировать код практически с первого взгляда (`I`dentify the code at a glance), `F` - держать структуру плоской, насколько это возможно (keep the `F`lattest structure you can), и стараться оставаться DRY (Don’t Repeat Yourself) - Не Повторяйте Себя - (`T`ry to stay DRY - Don’t Repeat Yourself). Структура должна придерживаться этим основным 4 правилам. + + *Почему LIFT?*: Получаем согласованную структуру, которая хорошо масштабируется, разбита на модули, и легко позволяет увеличить эффективность разработчика, путем быстрого нахождения кода. Другой способ проверить структуру вашего приложения - это спросить себя: Как быстро я могу открыть все сооответствующие файлы, чтобы работать над нужной функциональностью? + + Когда я чувствую, что работать с моей структурой некомфортно, я возвращаюсь к принципам LIFT. + + 1. `L`Размещать наш код легко (`L`ocating our code is easy) + 2. `I`Идентифицировать код быстро (`I`dentify code at a glance) + 3. `F`Держать структуру ровной как можно дольше (`F`lat structure as long as we can) + 4. `T`Старайтесь оставаться DRY или T-DRY (Don’t Repeat Yourself) - Не Повторяйте Себя (`T`ry to stay DRY - Don’t Repeat Yourself) + +### Размещение +###### [Style [Y141](#style-y141)] + + - Размещайте свой код интуитивно, просто и быстро. + + *Почему?*: Я считаю, это должно быть супер важно для проекта. Если команда не может быстро найти файлы, с которыми нужно работать, то команда не будет работать настолько эффективно, насколько это возможно. Такая структура должна быть изменена. Если не можете найти файл по имени, а также сопутствующие файлы, тогда поместите их в наиболее интуитивно подходящее место, рядом друг другом, и это сэкономит кучу времени. Описательная структура папок может помочь с этим. + + ``` + /bower_components + /client + /app + /avengers + /blocks + /exception + /logger + /core + /dashboard + /data + /layout + /widgets + /content + index.html + .bower.json + ``` + +### Идентификация +###### [Style [Y142](#style-y142)] + + - Когда вы смотрите на файл вы должны мгновенно знать и понимать, что он содержит и представляет. + + *Почему?*: Вы потратите меньше времени на охоту и клевание кода, и станете более эффективным. Если для этого потребуется более длинные имена файлов, то пусть будет так. Делайте имена файлов описательными, и держите в файле только один компонент. Не размещайте в файле несколько контроллеров, несколько сервисов или вообще смесь всего. Могут быть конечно отклонения от правила одного компонента в файле, напрмер, когда я прописываю в одном файле очень маленькие сущности, которые связаны друг с другом, но они все равно очень легко идентифицируемы. + +### Плоская структура +###### [Style [Y143](#style-y143)] + + - Держите структуру папок плоской, как можно дольше. Когда у вас больше 7 файлов, начните думать о разделении. + + *Почему?*: Никто не хочет искать файл в семи уровнях папок. Вспомните о меню на веб-сайтах … все что глубже второго уровня требует серьезного размышления. В организации структуры папок нет жестких правил, но если папка содержит 7-10 файлов, нужно делать подпапку. Основывайтесь на уровне вашего комфорта. Используйте плоскую структуру, пока не станет точно очевидно, что нужно создать новую папку (и это поможет соблюсти принципы LIFT). + +### T-DRY (Try to Stick to DRY) T-DRY (Старайтесь придерживаться принципов DRY) +###### [Style [Y144](#style-y144)] + + - Примечание переводчика: Аббревиатура DRY значит Don`t Repeat Yourself (Не повторяйте себя). + + - Придерживайтесь DRY, но не сходите с ума и не жертвуйте читабельностью. + + *Почему?*: Быть DRY - это важно, но не критично, если в жертву приносятся другие принципы LIFT. Поэтому я и назвал это T-DRY (Try DRY - попытайтесь быть DRY). Напрмер, я не хочу печатать session-view.html для представления, потому что и так понятно, что это представление(view). Но если это не очевидно или это определено соглашением, тогда нужно давать полное имя. + +**[К Содержанию](#table-of-contents)** + +## Application Structure + +### Общее руководство +###### [Style [Y150](#style-y150)] + + - Имейте короткую перспективу реализации и долгосрочное видение проекта. Другими словами, начинайте с малого, но держите всегда в голове, куда развивается ваше приложение. Весь код приложения идет в корневую папку `app`. Все содержимое распределяется, как один компонент на один файл. Каждый контроллер, сервис, модуль, представление - каждый в своем файле. Все скрипты сторонних производителей помещаются в другую корневую папку, а не в папку `app`. Я их не писал и я не хочу, чтобы они загромождали мое приложение (`bower_components`, `scripts`, `lib`). + + Замечание: Найти более подробную информацию и объяснение структуры: [тут оригинальная статья о структуре приложения](http://www.johnpapa.net/angular-app-structuring-guidelines/). + +### Общие элементы +###### [Style [Y151](#style-y151)] + + - Размещайте компоненты, которые определяют общий каркас приложения в папке `layout`. Там могут быть представление-оболочка и контроллер, которые являются контейнером для приложения, навигация, меню, регионы содержимого (content areas) и другие общие элементы. + + *Почему?*: Так организуются все элементы общего назначения, которые размещаются в одном месте и используются во всем приложении. + +### Структура Папки-по-Функциональностям (Folders-by-Feature) +###### [Style [Y152](#style-y152)] + + - Создавайте папки и называйте их по функциональным особенностям, которые они представляют и реализуют. Если папка растет и превышает семь файлов, то начинайте рассматривать возможность создания новой папки. Ваш порог может быть разный, так что регулируйте такую структуру по необходимости. + + *Почему?*: Разработчик легко ориентируется в коде, быстро определяет, что каждый файл реализует. В приложении поддерживается плоская структура, насколько это возможно. Повторяющиеся и избыточные имена отсутствуют. + + *Почему?*: Правила LIFT выполнены все. + + *Почему?*: Помогает уменьшить приложение, путем устранения неразберихи. Содержимое организуется понятно и соблюдаются принципы LIFT. + + *Почему?*: Когда набралось много файлов (более 10), то их размещение в структуре последовательных согласованных папок намного проще, чем в плоской структуре . + + ```javascript + /** + * рекомендовано + */ + + app/ + app.module.js + app.config.js + app.routes.js + components/ + calendar.directive.js + calendar.directive.html + user-profile.directive.js + user-profile.directive.html + layout/ + shell.html + shell.controller.js + topnav.html + topnav.controller.js + people/ + attendees.html + attendees.controller.js + speakers.html + speakers.controller.js + speaker-detail.html + speaker-detail.controller.js + services/ + data.service.js + localstorage.service.js + logger.service.js + spinner.service.js + sessions/ + sessions.html + sessions.controller.js + session-detail.html + session-detail.controller.js + ``` + + ![Пример Структуры Приложения](https://raw.githubusercontent.com/johnpapa/angularjs-styleguide/master/assets/modularity-2.png) + + Замечание: Не используйте структуру папки-по-типу. Так файлы одной функциональности разбрасываются по нескольким папкам, и далее все быстро становится очень громоздким. Как только в приложении создаются 5, 10, или 25+ представлений и контроллеров (и других компонентов), то работа становится очень сложной, в отличиии от структуры папки-по-функциональностям. + + ```javascript + /* + * избегайте этого + * Альтернативный способ "папки-по-типу". + * Я рекомендую "папки-по-функциональностям". + */ + + app/ + app.module.js + app.config.js + app.routes.js + controllers/ + attendees.js + session-detail.js + sessions.js + shell.js + speakers.js + speaker-detail.js + topnav.js + directives/ + calendar.directive.js + calendar.directive.html + user-profile.directive.js + user-profile.directive.html + services/ + dataservice.j + localstorage.js + logger.js + spinner.js + views/ + attendees.html + session-detail.html + sessions.html + shell.html + speakers.html + speaker-detail.html + topnav.html + ``` + +**[К Содержанию](#table-of-contents)** + +## Modularity + +### Много Маленьких Самодостаточных Модулей +###### [Style [Y160](#style-y160)] + + - Создавайте небольшие модули, которые включают в себя одну ответственность. + + *Почему?*: Модульные приложения позволяют легко подключать и отключать модули, это дает командам разработчиков строить вертикальные срезы приложения и раскатывать их постепенно. Это значит, мы можем добавлять новые модули в приложение по мере их готовности. + +### Создайте Модуль Приложения +###### [Style [Y161](#style-y161)] + + - Создайте корневой модуль приложения, который будет собирать вместе все модули и функциональности вашего приложения. Назовите этот модуль именем вашего приложения. + + *Почему?*: AngularJS специально разработан для поддержки модульности и принципов разделения сущностей. А создание корневого модуля приложения, который связывает все ваши остальные модули вместе, предоставляет очень простой способ добавления и удаления модулей из приложения. + +### Держите Модуль Приложения Тонким +###### [Style [Y162](#style-y162)] + + - Поместите в модуль приложения только логику сборки приложения. Функциональности оставте в их собственных модулях. + + *Почему?*: Добавление дополнительных ролей в корень приложения, типа получения или удаления данных, отображение представлений или другой подобной логики, не связанной со сборкой частей приложения вместе, загрязняет модуль приложения, а сами добавленные функциональности будет труднее повторно использовать или отключить. + + *Почему?*: Модуль приложения становится манифестом, который описывает какие модули подключаются к приложению. + +### Функциональные Области и Модули +###### [Style [Y163](#style-y163)] + + - Создавайте модули, которые представляют функциональные области, такие как папка общей компоновки (layout), повторно используемые и общие сервисы, информационные панели, и специфические функциональности приложения (типа клиенты, администратор, продажи). + + *Почему?*: Автономные модули могут быть добавлены с небольшиими доработками или вообще без них. + + *Почему?*: Спринты или итерации могут сосредоточиться на функциональных областях, и включить их по завершению спринта или итерации. + + *Почему?*: Оформление функциональных областей в модули позволяет проще их тестировать в изолированном или повторно используемом коде. + +### Повторно Используемые Блоки и Модули +###### [Style [Y164](#style-y164)] + + - Создавайте модули, которые представляют из себя повторно используемые блоки приложения для общих сервисов таких как обработка исключений, логгирование, диагностика, безопасность и локальная работа с данными. + + *Почему?*: Эти типы функциональностей нужны во многих приложениях. Поэтому держите их отдельно в своих собственных модулях, применяйте универсально и повторно используйте во многих приложениях. + +### Зависимости модулей +###### [Style [Y165](#style-y165)] + + - Корневой модуль приложения зависит от специфичных функциональных модулей и от любых общих или повторно используемых модулей. + + ![Модульность и Зависимости](https://raw.githubusercontent.com/johnpapa/angularjs-styleguide/master/assets/modularity-1.png) + + *Почему?*: Главный модуль приложения содержит хорошо читаемый манифест функциональностей приложения. + + *Почему?*: Каждая функциональная область содержит манифест, поясняющий от чего она зависит, таким образом эта область может быть подключена к любому приложению вместе с ее зависимостями и все будет работать. + + *Почему?*: Функциональности приложения для внутреннего пользования (intra-app) такие как общие сервисы данных становится проще размещать и делится из модуля `app.core` (выберите это имя для такого модуля). + + Замечание: Это стратегия для согласованности. Здесь очень много хороших вариантов. Выберите тот, который следует правилам зависимостей AngularJS, и его проще поддерживать и масштабировать. + + > Мои структуры слегка отличаются от проекта к проекту, но они всегда следовали этим руководствам структуры и модульности. Реализация может менятся в зависимости от особенностей проекта и команды. Другими словами, не зацикливайтесь на точных воспроизведениях структуры. Регулируйте свою структуру учитывая согласованность, способность поддерживать код и эффективность. + + > В небольшом приложении вы можете конечно объединить все общие зависимости в модуль приложения, где функциональные модули не имеют прямых зависимостей. Это проще поддерживать в маленьких приложениях, использовать это вне приложения будет очень затруднительно. + +**[К Содержанию](#table-of-contents)** + +## Startup Logic + +### Конфигурация +###### [Style [Y170](#style-y170)] + + - Вставьте код в [конфигурацию модуля](https://docs.angularjs.org/guide/module#module-loading-dependencies), который должен быть сконфигурирован перед запуском angular-приложения. Идеальные кандидаты для этого - провайдеры и константы. + + *Почему?*: Чем меньше мест для конфигурации, тем лучше. + + ```javascript + angular + .module('app') + .config(configure); + + configure.$inject = + ['routerHelperProvider', 'exceptionHandlerProvider', 'toastr']; + + function configure (routerHelperProvider, exceptionHandlerProvider, toastr) { + exceptionHandlerProvider.configure(config.appErrorPrefix); + configureStateHelper(); + + toastr.options.timeOut = 4000; + toastr.options.positionClass = 'toast-bottom-right'; + + //////////////// + + function configureStateHelper() { + routerHelperProvider.configure({ + docTitle: 'NG-Modular: ' + }); + } + } + ``` + +### Блоки Run +###### [Style [Y171](#style-y171)] + + - Весь код, который должен запуститься, во время старта приложения, должен быть объявлен в фабрике, предоставлен в виде функции, и вставлен в [блок run](https://docs.angularjs.org/guide/module#module-loading-dependencies). + + *Почему?*: Если код поместить сразу в блок run, то его будет тяжело тестить. Размещение кода в фабрике облегчает абстрагирование и использование фиктивных объектов для тестов. + + ```javascript + angular + .module('app') + .run(runBlock); + + runBlock.$inject = ['authenticator', 'translator']; + + function runBlock(authenticator, translator) { + authenticator.initialize(); + translator.initialize(); + } + ``` + +**[К Содержанию](#table-of-contents)** + +## Angular $ Wrapper Services + +### $document and $window +###### [Style [Y180](#style-y180)] + + - Используйте [`$document`](https://docs.angularjs.org/api/ng/service/$document) и [`$window`](https://docs.angularjs.org/api/ng/service/$window) вместо `document` и `window`. + + *Почему?*: Эти сервисы являются оберткой среды Angular, они более проще тестируются, чем объекты document и window. Это дает вам возможность не создавать самим фиктивные объекты document and window. + +### $timeout and $interval +###### [Style [Y181](#style-y181)] + + - Используйте [`$timeout`](https://docs.angularjs.org/api/ng/service/$timeout) и [`$interval`](https://docs.angularjs.org/api/ng/service/$interval) вместо `setTimeout` и `setInterval` . + + *Почему?*: Эти сервисы являются оберткой среды Angular, они более легко тестируемы и еще они обрабатываются циклом digest среды AngularJS, таким образом синхронизируя данные. + +**[К Содержанию](#table-of-contents)** + +## Testing +Модульное тестирование помогает поддерживать чистый код. Я включил некоторые мои рекомендации по основам модульного тестирования в виде ссылок для более подробной информации. + +### Пишите Тесты с Историями +###### [Style [Y190](#style-y190)] + + - Пишите набор тестов для каждой истории. Начните пустой тест и заполняйте его по мере написания кода для истории. + + *Почему?*: Описания тестов помогают ясно определить, что ваша история будет делать, чего не будет, и как вы можете оценить успешность тестов. + + ```javascript + it('should have Avengers controller', function() { + // TODO + }); + + it('should find 1 Avenger when filtered by name', function() { + // TODO + }); + + it('should have 10 Avengers', function() { + // TODO (mock data?) + }); + + it('should return Avengers via XHR', function() { + // TODO ($httpBackend?) + }); + + // and so on + ``` + +### Библиотеки для тестирования +###### [Style [Y191](#style-y191)] + + - Используйте [Jasmine](http://jasmine.github.io/) или [Mocha](http://mochajs.org) для модульного тестирования. + + *Почему?*: И Jasmine и Mocha широко распространены в сообществе AngularJS. Обе они стабильны, хорошо поддерживаются, и предоставляют отличные возможности для тестирования. + + Замечание: Если используется Mocha, то дополнительно нужно использовать assert-библиотеку, например [Chai](http://chaijs.com). + +### Движок Запуска Тестов +###### [Style [Y192](#style-y192)] + + - Используйте [Karma](http://karma-runner.github.io) в качестве движка для запуска тестов. + + *Почему?*: Karma просто конфигурируется, она просто запускается вручную или автоматически (как только вы измените код). + + *Why?*: Karma просто внедряется в ваш процесс Continuous Integration, как самостоятельно, так и через Grunt или Gulp. + + *Почему?*: Некоторые средства разработки (IDE) начали интегрировать в себя библиотеку Karma, это - [WebStorm](http://www.jetbrains.com/webstorm/) и [Visual Studio](http://visualstudiogallery.msdn.microsoft.com/02f47876-0e7a-4f6c-93f8-1af5d5189225). + + *Почему?*: Karma очень хорошо работает с такими лидерами автоматизации как [Grunt](http://www.gruntjs.com) (вместе [grunt-karma](https://github.com/karma-runner/grunt-karma)) и [Gulp](http://www.gulpjs.com) (вместе [gulp-karma](https://github.com/lazd/gulp-karma)). + +### Stubbing и Spying +###### [Style [Y193](#style-y193)] + + - Используйте [Sinon](http://sinonjs.org/) для stubbing и spying. + + *Почему?*: Sinon хорошо работает и с Jasmine и с Mocha. Он расширяет возможности stubbing и spying, которые предлагают Jasmine и Mocha. + + *Почему?*: Sinon просто переключается между Jasmine и Mocha, это если вы хотите использовать сразу обе библиотеки. + +### Невизуальный Браузер +###### [Style [Y194](#style-y194)] + + - Используйте [PhantomJS](http://phantomjs.org/) для запуска тестов на сервере. + + *Почему?*: PhantomJS - невизуальный браузер, который помогает запускать тесты, не используя обычные визуальные браузеры. Таким образом, вам не нужно устанавливать на ваш сервер Chrome, Safari, IE, или другие браузеры. + + Замечание: Все же проведите тесты на всех браузерах, особенно на браузерах вашей целевой аудитории. + +### Анализ Кода +###### [Style [Y195](#style-y195)] + + - Запустите JSHint на ваших тестах. + + *Почему?*: Тесты это код. JSHint помогает идентифицировать проблемы качества кода, которые могут причиной некорректной работы тестов. + +### Разрешите Глобальные Переменные для Правил JSHint на Тестах +###### [Style [Y196](#style-y196)] + + - Смягчите правила для кода ваших тестов, чтобы разрешить общие глобальные переменные такие как `describe` и `expect`. + + *Почему?*: Ваши тесты - это код и он требует того же самого внимания и соблюдения правил качества, как и весь ваш рабочий код. Все же, глобальные переменные используются средой тестирования, и правила для них нужно ослабить в спецификации тестов. + + ```javascript + /* global sinon, describe, it, afterEach, beforeEach, expect, inject */ + ``` + + ![Средства Тестирования](https://raw.githubusercontent.com/johnpapa/angularjs-styleguide/master/assets/testing-tools.png) + +### Организация Тестов +###### [Style [Y197](#style-y197)] + + - Размещайте файлы модульных тестов (specs) рядом со своим клиентским кодом. А тестовые файлы (specs), которые покрывают интеграцию с сервером или тестируют сразу несколько компонентов, в отдельной папке `tests`. + + *Почему?*: Модульные тесты имеют прямое отношение к определенному компоненту и файлу с исходным кодом. + + *Почему?*: Так легче держать тесты актуальными, потому что они всегда на виду. Во время написания кода, применяете ли вы технику TDD или тестируете во время разработки или тестируете после разработки, тестовые файлы (specs) всегда рядом, они никогда не пропадают не из вида не из мыслей. Таким образом, тестам будет всегда уделено внимание, а это поможет поддерживать покрытие кода тестами. + + *Почему?*: Когда вы изменяете исходный код, всегда проще сразу обновить тесты. + + *Почему?*: Размещение файла кода и теста рядом упрощает их поиск и в случае необходимости, перенос в другое место обоих файлов не составляет большого труда. + + *Почему?*: Отделить тестовые файлы(specs), так чтобы они не попали в рабочую сборку можно с помощью grunt или gulp. + + ``` + /src/client/app/customers/customer-detail.controller.js + /customer-detail.controller.spec.js + /customers.controller.spec.js + /customers.controller-detail.spec.js + /customers.module.js + /customers.route.js + /customers.route.spec.js + ``` + +**[К Содержанию](#table-of-contents)** + +## Animations + +### Применение +###### [Style [Y210](#style-y210)] + + - Используйте subtle [анимации AngularJS](https://docs.angularjs.org/guide/animations) чтобы перемещать состояния представлений и первичные визуальные элементы. Подключите [модуль ngAnimate](https://docs.angularjs.org/api/ngAnimate). Есть три ключа - тонкий (subtle), плавный (smooth), цельный (seamless). + + *Почему?*: При правильном использовании тонкая анимация может улучшить удобство работы. + + *Почему?*: Тонкие анимации могут воспринимаемую эффективность при изменениии представлений. + +### Длительность Анимаций +###### [Style [Y211](#style-y211)] + + - Используйте короткую длительность анимаций. Я в основном начинаю с 300 миллисекунд и регулирую до нужного состояния. + *Почему?*: Долгие анимации могут иметь обратный эффект для пользователя, приложение будет восприниматься как медленно работающее. + +### animate.css +###### [Style [Y212](#style-y212)] + + - Используйте [animate.css](http://daneden.github.io/animate.css/) для обычных анимаций. + + *Почему?*: Анимации, предоставляемые animate.css, быстрые, плавные и их легко добавить в приложение. + + *Почему?*: Это дает согласованность ваших анимаций. + + *Почему?*: animate.css широко используем и оттестирован. + + Замечание: Посмотрите эту [замечательную статью от Matias Niemelä об анимациях AngularJS](http://www.yearofmoo.com/2013/08/remastered-animation-in-angularjs-1-2.html) + +**[К Содержанию](#table-of-contents)** + +## Comments + +### jsDoc +###### [Style [Y220](#style-y220)] + + - Если планируется производство документации, используйте синтаксис [`jsDoc`](http://usejsdoc.org/) для документирования имен функций, описаний, параметров и возвращаемых значений. Используйте `@namespace` и `@memberOf` для соответствия структуре приложения. + + *Почему?*: Вы можете сгенерировать (и перегенерировать) документацию из вашего кода, чтобы не писать ее с нуля. + + *Почему?*: С помощью общеиспользуемого промышленного инстумента вы получаете согласованность. + + ```javascript + /** + * Logger Factory + * @namespace Factories + */ + (function() { + angular + .module('app') + .factory('logger', logger); + + /** + * @namespace Logger + * @desc Application wide logger + * @memberOf Factories + */ + function logger($log) { + var service = { + logError: logError + }; + return service; + + //////////// + + /** + * @name logError + * @desc Logs errors + * @param {String} msg Message to log + * @returns {String} + * @memberOf Factories.Logger + */ + function logError(msg) { + var loggedMsg = 'Error: ' + msg; + $log.error(loggedMsg); + return loggedMsg; + }; + } + })(); + ``` + +**[К Содержанию](#table-of-contents)** + +## JS Hint + +### Используйте Файл Настроек +###### [Style [Y230](#style-y230)] + + - Используйте JS Hint для проверки вашего кода JavaScript и проверьте файл настроек самого JS Hint, а также включите этот файл с систему управления исходным кодом (source control). Смотрите [JS Hint docs](http://www.jshint.com/docs/) для точного описания настроек. + + *Почему?*: Если код некорректен, то получаем предупреждения, перед тем, как отправить изменения в систему управления исходным кодом. + + *Почему?*: Обеспечивается согласованность для всей команды. + + ```javascript + { + "bitwise": true, + "camelcase": true, + "curly": true, + "eqeqeq": true, + "es3": false, + "forin": true, + "freeze": true, + "immed": true, + "indent": 4, + "latedef": "nofunc", + "newcap": true, + "noarg": true, + "noempty": true, + "nonbsp": true, + "nonew": true, + "plusplus": false, + "quotmark": "single", + "undef": true, + "unused": false, + "strict": false, + "maxparams": 10, + "maxdepth": 5, + "maxstatements": 40, + "maxcomplexity": 8, + "maxlen": 120, + + "asi": false, + "boss": false, + "debug": false, + "eqnull": true, + "esnext": false, + "evil": false, + "expr": false, + "funcscope": false, + "globalstrict": false, + "iterator": false, + "lastsemic": false, + "laxbreak": false, + "laxcomma": false, + "loopfunc": true, + "maxerr": false, + "moz": false, + "multistr": false, + "notypeof": false, + "proto": false, + "scripturl": false, + "shadow": false, + "sub": true, + "supernew": false, + "validthis": false, + "noyield": false, + + "browser": true, + "node": true, + + "globals": { + "angular": false, + "$": false + } + } + ``` + +**[К Содержанию](#table-of-contents)** + +## Constants + +### Глобальные Переменные Сторонних Производителей (Vendors) +###### [Style [Y240](#style-y240)] + + - Создайте константы AngularJS для глобальных переменных из библиотек сторонних производителей. + + *Почему?*: Предоставляет способ подключить сторонние библиотеки, которые являются глобальными переменными. Это улучшает тестируемость кода, позволяя вам проще узнать, какие зависимости есть у ваших компонентов. Это также позволит вам, создать фиктивные объекты этих зависимостей, если это нужно. + + ```javascript + // constants.js + + /* global toastr:false, moment:false */ + (function() { + 'use strict'; + + angular + .module('app.core') + .constant('toastr', toastr) + .constant('moment', moment); + })(); + ``` + +###### [Style [Y241](#style-y241)] + + - Используйте константы для значений, которые не изменяются и не приходят из другого сервиса. Если константы используются в модуле, который может быть использован в нескольких приложениях, то поместите константу в файле, названному по имени модуля. В противном случае держите константы в главном модуле в файле `constants.js`. + + *Почему?*: Значение может измениться, возможно это редкая ситуация, но допустим сервис возвращает нам значение, и таким образом мы не будем менять наш рабочий код, использующий этот сервис. Напрмер, url для сервиса данных мог бы быть помещен в константы, но лучше загружать его из веб сервиса. + + *Почему?*: Константы могут быть инжектированы в любой angular-компонент, включая провайдеры. + + *Почему?*: Когда приложение разделено на модули, которые могут быть использованы в других приложениях, каждый отдельный модуль должен быть способен оперировать своими собственными зависимыми константами. + + ```javascript + // Константы используются во всем приложении + angular + .module('app.core') + .constant('moment', moment); + + // Константы используются в модуле продаж + angular + .module('app.sales') + .constant('events', { + ORDER_CREATED: 'event_order_created', + INVENTORY_DEPLETED: 'event_inventory_depleted' + }); + ``` + +**[К Содержанию](#table-of-contents)** + +## File Templates and Snippets +Используйте шаблоны файлов и сниппеты, чтобы соблюсти согласованность стилей и инструкций. Здесь есть шаблоны и/или сниппеты для некоторых веб-редакторов и интегрированных средств разработки (IDE). + +### Sublime Text +###### [Style [Y250](#style-y250)] + + - AngularJS сниппеты, которые соблюдают приведенные здесь стили и руководства. + + - Скачайте [Sublime Angular сниппеты](assets/sublime-angular-snippets.zip?raw=true) + - Поместите все в вашу папку Packages + - Перезапустите Sublime + - В файле JavaScript напечатайте следующие команды после клавиши `TAB` + + ```javascript + ngcontroller // создает контроллер Angular + ngdirective // создает директиву Angular + ngfactory // создает фабрику Angular + ngmodule // создает модуль Angular + ``` + +### Visual Studio +###### [Style [Y251](#style-y251)] + + - Шаблоны файлов AngularJS, которые соблюдают приведенные здесь стили и руководства, можно найти на [SideWaffle](http://www.sidewaffle.com) + + - Скачайте [SideWaffle](http://www.sidewaffle.com) это расширение к Visual Studio (файл vsix) + - Запустите файл vsix + - Перезапустите Visual Studio + +### WebStorm +###### [Style [Y252](#style-y252)] + + - AngularJS сниппеты и шаблоны файлов, которые соблюдают приведенные здесь стили и руководства. Вы можете импортировать их в свои настройки WebStorm: + + - Скачайте [WebStorm AngularJS шаблоны файлов и сниппетов](assets/webstorm-angular-file-template.settings.jar?raw=true) + - Откройте WebStorm и перейдите в меню `File` + - Выберите пункт меню `Import Settings` + - Выберите файл и нажмите `OK` + - В файле JavaScript напечатайте следующие команды после клавиши `TAB`: + + ```javascript + ng-c // создает контроллер Angular + ng-f // создает фабрику Angular + ng-m // создает модуль Angular + ``` + +**[К Содержанию](#table-of-contents)** + +## Yeoman Generator +###### [Style [Y260](#style-y260)] + +Вы можете использовать [HotTowel yeoman generator](http://jpapa.me/yohottowel) для создания приложений Angular, которые являются стартовой точкой разработки и соблюдают правила данного руководства. + +1. Установите generator-hottowel + + ``` + npm install -g generator-hottowel + ``` + +2. Создайте новую папку и перейдите в нее. + + ``` + mkdir myapp + cd myapp + ``` + +3. Запустите генератор + + ``` + yo hottowel helloWorld + ``` + +**[К Содержанию](#table-of-contents)** + +## Routing +Клиентская маршрутизация важна для создания навигации между представлениями, а также компоновкой представлений, которые состоят из небольших маленьких шаблонов и директив. + +###### [Style [Y270](#style-y270)] + + - Используйте [AngularUI Router](http://angular-ui.github.io/ui-router/) для клиентской маршрутизации. + + *Почему?*: UI Router реализует все возможности маршрутизатора Angular, плюс предлагает дополнительную функциональность, включая вложенные маршруты и состояния. + + *Почему?*: Синтаксис почти такой же, как и у маршрутизатора Angular, и несложно мигрировать на UI Router. + +###### [Style [Y271](#style-y271)] + + - Определяйте маршруты для всех представлений в модуле, где они есть. Каждый модуль должен содержать маршруты для всех своих представлений. + + *Why?*: Каждый модуль должен быть независим. + + *Why?*: Когда мы удаляем или добавляем модуль, то приложение должно содержать только те маршруты, которые указывают на существующие представления. + + *Why?*: Так мы можем включать или исключать части приложения, не заботясь о том, что у нас останутся маршруты на несуществующие представления. + +**[К Содержанию](#table-of-contents)** + +## Task Automation +Используйте [Gulp](http://gulpjs.com) или [Grunt](http://gruntjs.com) для создания автоматизированных процессов. Gulp работает по принципу код главнее конфигурации, а Grunt наоборот конфигурация главнее кода. Я лично предпочитаю Gulp, так как мне кажется его проще читать и писать, но на самом деле они оба отличные инструменты автоматизации. + +###### [Style [Y400](#style-y400)] + + - Используйте автоматизацию для сборки всех файлов с определениями модуля `*.module.js` перед всеми остальными JavaScript-файлами приложения. + + *Why?*: Angular должен зарегистрировать все определения модулей, перед тем как их использовать. + + *Why?*: Именование модулей по специальному шаблону `*.module.js` упрощает их поиск и сборку в единую группу, для того чтобы подключить их первыми. + + ```javascript + var clientApp = './src/client/app/'; + + // Всегда собираем файлы модулей первыми + var files = [ + clientApp + '**/*.module.js', + clientApp + '**/*.js' + ]; + ``` + +**[К Содержанию](#table-of-contents)** + +## AngularJS Docs +Для дополнительной информации, описания API, смотрите [документацию Angular](//docs.angularjs.org/api). + +## Contributing + +Сначала откройте issie и объясните вопрос/проблему для того, чтобы обсудить потенциальные изменения/добавления. Если у вас есть вопросы по этому руководству, вы можете свободно задавать их, создавая в хранилище issues. Если вы нашли опечатку, создайте pull request. Идея в том, чтобы содержимое всегда дежать актуальным и используя возможности системы Github, помочь рассказать историю с вопросами или проблемами и распространить ее, чтобы она была доступна через поиск Google. Почему? Потому что, если у вас был такой вопрос, то вполне вероятно, что кто-то тоже ищет решение на этот же вопрос! Вы можете узнать больше здесь о том как можно сотрудничать. + +*Добавляя материал в данное хранилище вы согласны с тем, ваше содержимое будет доступно согласно приведенной ниже лицензии.* + +### Процесс + 1. Обсудите изменения в Issue. + 2. Откройте Pull Request, сделайте ссылку на issue, объясните изменения и их ценность. + 3. Pull Request будет проверен и далее принят или отклонен. + +## License + +_tldr; Use this guide. Attributions are appreciated._ + +### (The MIT License) + +Copyright (c) 2014 [John Papa](http://johnpapa.net) + +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. + +**[К Содержанию](#table-of-contents)** From 997ad0f214ca602280fa190589785cc4a8c1e963 Mon Sep 17 00:00:00 2001 From: John Papa Date: Wed, 11 Feb 2015 07:55:09 -0500 Subject: [PATCH 177/567] added links to french and russion translations, along with credits --- i18n/README.md | 10 ++++++---- i18n/fr-FR.md | 4 ++++ i18n/mk-MK.md | 2 +- i18n/ru-RU.md | 2 ++ i18n/zh-CN.md | 2 +- 5 files changed, 14 insertions(+), 6 deletions(-) diff --git a/i18n/README.md b/i18n/README.md index 91d02c17..92b61ced 100644 --- a/i18n/README.md +++ b/i18n/README.md @@ -4,10 +4,12 @@ The [original English version](http://jpapa.me/ngstyles) is the source of truth, *All translations are created by and maintained by the community.* -1. [Italian](it-IT.md) -1. [Macedonian](mk-MK.md) -1. [Portuguese-Brazil](PT-BR.md) -1. [Simplified Chinese](zh-CN.md) +1. [French](fr-FR.md) +2. [Italian](it-IT.md) +3. [Macedonian](mk-MK.md) +4. [Portuguese-Brazil](PT-BR.md) +5. [Russian](ru-RU.md) +6. [Simplified Chinese](zh-CN.md) ## Contributing Language translations are welcomed and encouraged. The succcess of these translations depends on the community. I highly encourage new translation contributions and help to keep them up to date. diff --git a/i18n/fr-FR.md b/i18n/fr-FR.md index 5ddf2e6b..503c2425 100644 --- a/i18n/fr-FR.md +++ b/i18n/fr-FR.md @@ -2,6 +2,10 @@ *Le guide d'un point de vue personnel sur le style AngularJS par [@john_papa](//twitter.com/john_papa)* +*Translated by [Eric Lemerdy](https://github.com/ericlemerdy)* + +>The [original English version](http://jpapa.me/ngstyles) is the source of truth, as it is maintained and updated first. + Si vous cherchez un guide de style pour la syntaxe, les conventions, et la structuration d'application AngularJS, alors vous êtes au bon endroit. Ces styles sont basés sur mon expérience de dévelopement avec [AngularJS](//angularjs.org), mes présentations, [mes cours sur Pluralsight](http://pluralsight.com/training/Authors/Details/john-papa) et mon travail au sein des équipes. Le but de ce guide de style est de proposer des conseils sur le développement d'applications AngularJS en montrant les conventions que j'utilise et, plus important encore, les raisons des choix que j'ai pris. diff --git a/i18n/mk-MK.md b/i18n/mk-MK.md index 3e670c9d..fd710f83 100644 --- a/i18n/mk-MK.md +++ b/i18n/mk-MK.md @@ -4,7 +4,7 @@ *Преведено од [Александар Богатинов](https://github.com/Bogatinov)* ->[Оригиналната англиска верзија](http://jpapa.me/ngstyles) е изворот на вистината, бидејќи е одржуванa и ажуриранa. +>The [original English version](http://jpapa.me/ngstyles) is the source of truth, as it is maintained and updated first. Доколку барате своеволен стил на кодирање за синтакса, конвенции и структурирање на AngularJS апликации, тогаш сте на правилното место. Овие стилови се базирани на моето искуство во развој на [AngularJS](//angularjs.org), презентации, [Pluralsight тренинг курсеви](http://pluralsight.com/training/Authors/Details/john-papa) и работа во тимови. diff --git a/i18n/ru-RU.md b/i18n/ru-RU.md index 46e822d2..4a779654 100644 --- a/i18n/ru-RU.md +++ b/i18n/ru-RU.md @@ -4,6 +4,8 @@ *Перевел на русский язык [Василий Мажекин](https://github.com/mazhekin)* +>The [original English version](http://jpapa.me/ngstyles) is the source of truth, as it is maintained and updated first. + Если вам нужны стандарты написания кода, соглашения, и руководства структурирования приложений AngularJS, то вы находитесь в правильном месте. Эти соглашения основаны на моем опыте программирования на [AngularJS](//angularjs.org), на моих презентациях [Pluralsight training courses](http://pluralsight.com/training/Authors/Details/john-papa), а также на совместной работе в командах разработчиков. Главной целью этого документа является желание предоставить вам наиболее полные инструкции для построения приложений AngularJS. Рекомендуя данные соглашения, я стараюсь акцентировать ваше внимание на цели и причины, зачем их нужно придерживаться. diff --git a/i18n/zh-CN.md b/i18n/zh-CN.md index 6797caec..cb12e66f 100644 --- a/i18n/zh-CN.md +++ b/i18n/zh-CN.md @@ -4,7 +4,7 @@ *由[kerncink](https://github.com/natee)翻译* ->[原始英文版本](http://jpapa.me/ngstyles)将会在第一时间维护和更新,翻译版本的更新将会在这之后。 +>The [original English version](http://jpapa.me/ngstyles) is the source of truth, as it is maintained and updated first. 如果你正在寻找一些关于语法、约定和结构化的AngularJS应用的一个有建设性的风格指南,这个repo正适合你。这里所包含的风格是基于我在团队中使用[AngularJS](//angularjs.org)的一些经验、一些演讲和[Pluralsight培训课程](http://pluralsight.com/training/Authors/Details/john-papa)。 From ae28e36b5fc3cfdb85a98e640d3f7eade8eb234a Mon Sep 17 00:00:00 2001 From: John Papa Date: Wed, 11 Feb 2015 07:56:54 -0500 Subject: [PATCH 178/567] fixed grammar typos --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index dc406ba9..2cf34ab9 100644 --- a/README.md +++ b/README.md @@ -1098,7 +1098,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see } ``` - Note: There are many naming options for directives, especially since they can be used in narrow or wide scopes. Choose one that makes the directive and it's file name distinct and clear. Some examples are below, but see the naming section for more recommendations. + Note: There are many naming options for directives, especially since they can be used in narrow or wide scopes. Choose one that makes the directive and its file name distinct and clear. Some examples are below, but see the naming section for more recommendations. ### Manipulate DOM in a Directive ###### [Style [Y072](#style-y072)] @@ -1110,7 +1110,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see ### Provide a Unique Directive Prefix ###### [Style [Y073](#style-y073)] - - Provide a short, unique and descriptive directive prefix such as `acmeSalesCustomerInfo` which is declared in HTML as `acme-sales-customer-info`. + - Provide a short, unique and descriptive directive prefix such as `acmeSalesCustomerInfo` which would be declared in HTML as `acme-sales-customer-info`. *Why?*: The unique short prefix identifies the directive's context and origin. For example a prefix of `cc-` may indicate that the directive is part of a CodeCamper app while `acme-` may indicate a directive for the Acme company. From 488056382ac7b996f020f5c426b944cadafe45c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=B5=B5=E5=8F=AF?= Date: Thu, 12 Feb 2015 14:46:07 +0800 Subject: [PATCH 179/567] Update to latest version --- i18n/zh-CN.md | 154 +++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 140 insertions(+), 14 deletions(-) diff --git a/i18n/zh-CN.md b/i18n/zh-CN.md index cb12e66f..e3316014 100644 --- a/i18n/zh-CN.md +++ b/i18n/zh-CN.md @@ -51,6 +51,9 @@ 1. [JSHint](#js-hint) 1. [常量](#常量) 1. [文件模板和片段](#文件模板和片段) + 1. [Yeoman Generator](#yeoman-generator) + 1. [路由](#路由) + 1. [任务自动化](#任务自动化) 1. [AngularJS文档](#angularjs文档) 1. [贡献](#贡献) 1. [许可](#许可) @@ -730,7 +733,7 @@ ###可访问的成员放到顶部### ###### [Style [Y052](#style-y052)] - - 使用从[显露模块模式](http://addyosmani.com/resources/essentialjsdesignpatterns/book/#revealingmodulepatternjavascript)派生出来的技术把service中可调用的成员暴露到顶部, + - 使用从[显露模块模式](http://addyosmani.com/resources/essentialjsdesignpatterns/book/#revealingmodulepatternjavascript)派生出来的技术把service(它的接口)中可调用的成员暴露到顶部, *为什么?*:把可调用的成员放到顶部使代码更加易读,并且让你可以立即识别service中的哪些成员可以被调用,哪些成员必须进行单元测试(或者被别人嘲笑)。 @@ -1097,7 +1100,7 @@ } ``` - 注:directive有很多命名选项,特别是从它们能够在一个狭隘的或者广泛的作用域中使用时,选择一个让directive和文件都清楚分明的名字。下面有一些例子,不过更多的建议去看命名章节。 + 注:directive有很多命名选项,特别是从它们能够在一个狭隘的或者广泛的作用域中使用时。选择一个让directive和它的文件名都清楚分明的名字。下面有一些例子,不过更多的建议去看命名章节。 ###在directive中操作DOM ###### [Style [Y072](#style-y072)] @@ -1209,15 +1212,17 @@ }, link: linkFunc, controller : ExampleController, - controllerAs: 'vm' + controllerAs: 'vm', + bindToController: true // because the scope is isolated }; return directive; function linkFunc(scope, el, attr, ctrl) { - console.log('LINK: scope.max = %i', scope.max); - console.log('LINK: scope.vm.min = %i', scope.vm.min); - console.log('LINK: scope.vm.max = %i', scope.vm.max); + console.log('LINK: scope.min = %s *** should be undefined', scope.min); + console.log('LINK: scope.max = %s *** should be undefined', scope.max); + console.log('LINK: scope.vm.min = %s', scope.vm.min); + console.log('LINK: scope.vm.max = %s', scope.vm.max); } } @@ -1227,23 +1232,71 @@ // Injecting $scope just for comparison var vm = this; - vm.min = 3; - vm.max = $scope.max; - console.log('CTRL: $scope.max = %i', $scope.max); - console.log('CTRL: vm.min = %i', vm.min); - console.log('CTRL: vm.max = %i', vm.max); + vm.min = 3; + + console.log('CTRL: $scope.vm.min = %s', $scope.vm.min); + console.log('CTRL: $scope.vm.max = %s', $scope.vm.max); + console.log('CTRL: vm.min = %s', vm.min); + console.log('CTRL: vm.max = %s', vm.max); } ``` ```html - /* example.directive.html */ +
hello world
max={{vm.max}}
min={{vm.min}}
``` +###### [Style [Y076](#style-y076)] + + - 当directive中使用了`controller as`语法时,如果你想把父级作用域绑定到directive的controller作用域时,使用`bindToController = true`。 + + *为什么?*:这使得绑定作用域到controller变得更加简单。 + + 注意:Angular 1.3.0才介绍了`bindToController`。 + + ```html +
+ ``` + + ```javascript + angular + .module('app') + .directive('myExample', myExample); + + function myExample() { + var directive = { + restrict: 'EA', + templateUrl: 'app/feature/example.directive.html', + scope: { + max: '=' + }, + controller: ExampleController, + controllerAs: 'vm', + bindToController: true + }; + + return directive; + } + + function ExampleController() { + var vm = this; + vm.min = 3; + console.log('CTRL: vm.min = %s', vm.min); + console.log('CTRL: vm.max = %s', vm.max); + } + ``` + + ```html + +
hello world
+
max={{vm.max}}
+
min={{vm.min}}
+ ``` + **[返回顶部](#目录)** ## 解决Controller的Promises @@ -2366,6 +2419,8 @@ *为什么?*:更新源代码的时候可以更简单地在同一时间更新测试代码。 + *为什么?*:方便源码阅读者了解组件如何使用,也便于发现其中的局限性。 + *为什么?*:方便找。 *为什么?*:方便使用grunt或者gulp。 @@ -2597,6 +2652,77 @@ **[返回顶部](#目录)** +## Yeoman Generator +###### [Style [Y260](#style-y260)] + +你可以使用[HotTowel yeoman generator](http://jpapa.me/yohottowel)来创建一个遵循本指南的Angular起步应用。 + +1. 安装generator-hottowel + + ``` + npm install -g generator-hottowel + ``` + +2. 创建一个新的文件夹并定位到它 + + ``` + mkdir myapp + cd myapp + ``` + +3. 运行生成器 + + ``` + yo hottowel helloWorld + ``` +**[返回顶部](#目录)** + +## 路由 +客户端路由对于在视图和很多小模板和指令组成的构成视图中创建导航是非常重要的。 +###### [Style [Y270](#style-y270)] + + - 用[AngularUI Router](http://angular-ui.github.io/ui-router/)来做路由控制。 + + *为什么?*:它包含了Angular路由的所有特性,并且增加了一些额外的特性,如嵌套路由和状态。 + + *为什么?*:语法和Angular路由很想,很容易迁移到UI Router。 + +###### [Style [Y271](#style-y271)] + + - Define routes for views in the module where they exist. + Each module should contain the routes for the views in the module. + + *为什么?*:每个模块应该是独立的。 + + *为什么?*:当删除或增加一个模块时,应用程序只包含指向现存视图的路由。(也就是说删除模块和增加模块都需更新路由) + + *为什么?*:这使得可以在不关心孤立的路由时很方便地启用或禁用应用程序的某些部分。 + +**[返回顶部](#目录)** + +## 任务自动化 +用[Gulp](http://gulpjs.com)或者[Grunt](http://gruntjs.com)来创建自动化任务。Gulp偏向于代码在配置之上,Grunt更倾向于配置高于代码。我更倾向于使用gulp,因为gulp写起来比较简单。 + +###### [Style [Y400](#style-y400)] + + - 用任务自动化在其它JavaScript文件之前列出所有模块的定义文件`*.module.js`。 + + *为什么?*:Angular中,模块使用之前必须先注册。 + + *为什么?*:带有特殊规则的模块命名,例如`*.module.js`,会让你很轻松地识别它们。 + + ```javascript + var clientApp = './src/client/app/'; + + // Always grab module files first + var files = [ + clientApp + '**/*.module.js', + clientApp + '**/*.js' + ]; + ``` + +**[返回顶部](#目录)** + ## AngularJS文档 [Angular文档](//docs.angularjs.org/api)。 @@ -2653,8 +2779,8 @@ ###过程 - 1. 在一个Issue中讨论这个问题。 - 2. 打开一个pull request,引用这个问题,解释你做的修改和为什么要这样做。 + 1. 在Github Issue中讨论这个问题。 + 2. 在develop分支中开一个pull request,引用这个问题,解释你做的修改和为什么要这样做。 3. pull request将会被进行评估,结果就是合并或是拒绝。 ## 许可证 From bfbd7b063150b44dfc992e0f17cef7c79917d408 Mon Sep 17 00:00:00 2001 From: angelochiello Date: Thu, 12 Feb 2015 08:56:38 +0100 Subject: [PATCH 180/567] [it-IT] Minor typos change Updated after #273 with minor typos change. --- i18n/it-IT.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/i18n/it-IT.md b/i18n/it-IT.md index 997b687b..64a532c1 100644 --- a/i18n/it-IT.md +++ b/i18n/it-IT.md @@ -1115,7 +1115,7 @@ Nonostante questa guida spieghi i *cosa*, *come* e *perché*, trovo che sia di a ### Utilizza un prefisso unico per la Directive ###### [Stile [Y073](#stile-y073)] - - Utilizza un corto, unico e descrittivo prefisso alla directive come `acmeSalesCustomerInfo` che è dichiarato in HTML come `acme-sales-customer-info`. + - Utilizza un corto, unico e descrittivo prefisso alla directive come `acmeSalesCustomerInfo` che potrebbe essere dichiarato in HTML come `acme-sales-customer-info`. *Perché?*: L'unico breve prefisso identifica il contesto delle directive e l'origine. Per esempio un prefisso `cc-` potrebbe indicare che la directive è parte di una app CodeCamper mentre `acme-` potrebbe indicare una direttiva per l'azienda Acme. From 2c508e65beef83354f0ac1fbbe66d4ee55c73f96 Mon Sep 17 00:00:00 2001 From: Jason Miazga Date: Thu, 12 Feb 2015 12:49:17 -0500 Subject: [PATCH 181/567] added a reference to a snippets package for Atom --- README.md | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/README.md b/README.md index 2cf34ab9..ac4447ba 100644 --- a/README.md +++ b/README.md @@ -2708,6 +2708,27 @@ Use file templates or snippets to help follow consistent styles and patterns. He ng-f // creates an Angular factory ng-m // creates an Angular module ``` + +### Atom +###### [Style [Y253](#style-y253)] + + - AngularJS snippets that follow these styles and guidelines. + ``` + apm install angularjs-styleguide-snippets + ``` + or + - Open Atom, then open the Package Manager (Packages -> Settings View -> Install Packages/Themes) + - Search for the package 'angularjs-styleguide-snippets' + - Click 'Install' to install the package + + - In a JavaScript file type these commands followed by a `TAB` + + ```javascript + ngcontroller // creates an Angular controller + ngdirective // creates an Angular directive + ngfactory // creates an Angular factory + ngmodule // creates an Angular module + ``` **[Back to top](#table-of-contents)** From 45f7009e1c0d6df0a129368ec67ac790412667fd Mon Sep 17 00:00:00 2001 From: Andrey Koleshko Date: Fri, 13 Feb 2015 20:46:20 +0300 Subject: [PATCH 182/567] An instead of a before identifiable word --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 2cf34ab9..d49228df 100644 --- a/README.md +++ b/README.md @@ -2010,7 +2010,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see *Why?*: Separates configuration from module definition, components, and active code. - *Why?*: Provides a identifiable place to set configuration for a module. + *Why?*: Provides an identifiable place to set configuration for a module. ### Routes ###### [Style [Y129](#style-y129)] From 4e612e63927a0170167f5836054d99b3b3970a26 Mon Sep 17 00:00:00 2001 From: John Papa Date: Sat, 14 Feb 2015 08:12:56 -0500 Subject: [PATCH 183/567] fixed Y112 comments and added some more depth to handling routing errors --- README.md | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 2cf34ab9..d3f4daa5 100644 --- a/README.md +++ b/README.md @@ -1773,6 +1773,8 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see ```javascript /* recommended */ + var handlingRouteChangeError = false; + function handleRoutingErrors() { /** * Route cancellation: @@ -1781,14 +1783,25 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see */ $rootScope.$on('$routeChangeError', function(event, current, previous, rejection) { - var destination = (current && (current.title || current.name || current.loadedTemplateUrl)) || + if (handlingRouteChangeError) { return; } + handlingRouteChangeError = true; + var destination = (current && (current.title || + current.name || current.loadedTemplateUrl)) || 'unknown target'; - var msg = 'Error routing to ' + destination + '. ' + (rejection.msg || ''); + var msg = 'Error routing to ' + destination + '. ' + + (rejection.msg || ''); + /** * Optionally log using a custom service or $log. * (Don't forget to inject custom service) */ logger.warning(msg, [current]); + + /** + * On routing error, go to another route/state. + */ + $location.path('/'); + } ); } From 023ec1fc4209058446dc98c167eacdfd72fcc43f Mon Sep 17 00:00:00 2001 From: Alberto Date: Mon, 16 Feb 2015 00:04:31 +0000 Subject: [PATCH 184/567] Adding some translations. --- i18n/es-ES.md | 200 +++++++++++++++++++++++++------------------------- 1 file changed, 100 insertions(+), 100 deletions(-) diff --git a/i18n/es-ES.md b/i18n/es-ES.md index cb11cbcc..e5db6786 100644 --- a/i18n/es-ES.md +++ b/i18n/es-ES.md @@ -59,9 +59,9 @@ Mientras que esta guía explica el *qué*, *por qué* y *cómo*, me resulta úti ### La regla del 1 ###### [Style [Y001](#style-y001)] - - Define 1 componente por fichero. + - Define 1 componente por archivo. - El siguiente ejemplo define el módulo `app` y sus dependencias, define un controller, y defines una factory todo en el mismo fichero. + El siguiente ejemplo define el módulo `app` y sus dependencias, define un controller, y defines una factory todo en el mismo archivo. ```javascript /* evitar */ @@ -75,7 +75,7 @@ Mientras que esta guía explica el *qué*, *por qué* y *cómo*, me resulta úti function someFactory() { } ``` - Los mismos componentes están separados en su propio fichero. + Los mismos componentes están separados en su propio archivo. ```javascript /* recomendado */ @@ -117,7 +117,7 @@ Mientras que esta guía explica el *qué*, *por qué* y *cómo*, me resulta úti *¿Por qué?*: Una IIFE elimina las variables del scope global. Esto ayuda a prevenir que las variables y las declaraciones de funciones vivan más de lo esperado en el scope global, evitando así colisión de variables. - *¿Por qué?*: Cuando tu código se minimiza y se empaqueta en un fichero único para desplegar al servidor de producción, podrías tener colisión de variables y muchas variables globales. Una IIFE te protege contra ambos, creando una scope por cada fichero. + *¿Por qué?*: Cuando tu código se minimiza y se empaqueta en un archivo único para desplegar al servidor de producción, podrías tener colisión de variables y muchas variables globales. Una IIFE te protege contra ambos, creando una scope por cada archivo. ```javascript /* evitar */ @@ -188,7 +188,7 @@ Mientras que esta guía explica el *qué*, *por qué* y *cómo*, me resulta úti - Declara los módulos sin usar la variable, usando la sintaxis de los setters. - *¿Por qué?*: Con un componente por fichero, es raro que necesitemos introducir una variable para el módulo. + *¿Por qué?*: Con un componente por archivo, es raro que necesitemos introducir una variable para el módulo. ```javascript /* evitar */ @@ -392,7 +392,7 @@ Mientras que esta guía explica el *qué*, *por qué* y *cómo*, me resulta úti - Coloca las asociaciones en la parte superior del controller, por orden alfabético y no separados a lo largo del código del controller. - *¿Por qué?*: Colocarlas en la parte superior lo hace más fácil de leer y te ayuda a identificar instantáneamente qué variable del controller pueden ser asociadas y usadas en la View. + *¿Por qué?*: Colocar las variables asignables arriba hace más fácil la lectura y te ayuda a identificar qué variables del controlador pueden ser asociadas y usadas en la View. *¿Por qué?*: Setear funciones anónimas puede ser fácil, pero cuando esas funciones tienen más de una línea de código se hace menos legible. Definiendo las funciones bajo a las variables, hace que los detalles de implementación estén abajo, deja las variables arriba y las funciones abajo. @@ -479,21 +479,21 @@ Mientras que esta guía explica el *qué*, *por qué* y *cómo*, me resulta úti ### Function Declarations to Hide Implementation Details ###### [Style [Y034](#style-y034)] - - Use function declarations to hide implementation details. Keep your bindable members up top. When you need to bind a function in a controller, point it to a function declaration that appears later in the file. This is tied directly to the section Bindable Members Up Top. For more details see [this post](http://www.johnpapa.net/angular-function-declarations-function-expressions-and-readable-code). + - Declara funciones para ocultar detalles de implementación. Mantén las variables asignables arriba. Cuando necesites asignar una función a un controlador referencia una función que aparezca después en el archivo. Esto está directamente relacionado con la sección: Bindable Members Up Top. Para más detalles mira [este post](http://www.johnpapa.net/angular-function-declarations-function-expressions-and-readable-code). - *¿Por qué?*: Placing bindable members at the top makes it easy to read and helps you instantly identify which members of the controller can be bound and used in the View. (Same as above.) + *¿Por qué?*: Colocar las variables asignables arriba hace más fácil la lectura y te ayuda a identificar qué variables del controlador pueden ser asociadas y usadas en la View. - *¿Por qué?*: Placing the implementation details of a function later in the file moves that complexity out of view so you can see the important stuff up top. + *¿Por qué?*: Colocar los detalles de implementación de una función al final del deja la complejidad fuera de la vista, con las cosas importantes arriba. - *¿Por qué?*: Function declaration are hoisted so there are no concerns over using a function before it is defined (as there would be with function expressions). + *¿Por qué?*: Evitamos problemas usando funciones antes de ser definidas. - *¿Por qué?*: You never have to worry with function declarations that moving `var a` before `var b` will break your code because `a` depends on `b`. + *¿Por qué?*: No tendrás que propcuparte de que si pones `var a` antes de `var b` se rompa el código porque `a` dependa de `b`. - *¿Por qué?*: Order is critical with function expressions + *¿Por qué?*: El orden es crítico para las funciones ```javascript /** - * avoid + * evitar * Using function expressions. */ function Avengers(dataservice, logger) { @@ -520,13 +520,13 @@ Mientras que esta guía explica el *qué*, *por qué* y *cómo*, me resulta úti } ``` - Notice that the important stuff is scattered in the preceding example. In the example below, notice that the important stuff is up top. For example, the members bound to the controller such as `vm.avengers` and `vm.title`. The implementation details are down below. This is just easier to read. + Nótese que lo importante está disperso en el ejemplo anterior. En el siguiente ejemplo, lo importante está arriba. Por ejemplo, las variables asociadas al controller como `vm.avengers` y `vm.title`. Los detalles de implementación están debajo. Así es más fácil de leer. ```javascript /* - * recommend - * Using function declarations - * and bindable members up top. + * recomendado + * Usando declaraciones de funciones y + * asignandola a las variables arriba. */ function Avengers(dataservice, logger) { var vm = this; @@ -554,17 +554,17 @@ Mientras que esta guía explica el *qué*, *por qué* y *cómo*, me resulta úti ### Defer Controller Logic ###### [Style [Y035](#style-y035)] - - Defer logic in a controller by delegating to services and factories. + - Difiera la lógica dentro de un controller delegándola en services y factories. - *¿Por qué?*: Logic may be reused by multiple controllers when placed within a service and exposed via a function. + *¿Por qué?*: La lógica podría ser reutilizada por varios controllers cuando la colocas en un service y la expones como una función. - *¿Por qué?*: Logic in a service can more easily be isolated in a unit test, while the calling logic in the controller can be easily mocked. + *¿Por qué?*: La lógica en un servicio puede ser aislada en un test unitario, mientras que la lógica de llamadas en un controller se puede mockear fácilmente. - *¿Por qué?*: Removes dependencies and hides implementation details from the controller. + *¿Por qué?*: Elimina dependencias y esconde detalles de implementación del controller. ```javascript - /* avoid */ + /* evitar */ function Order($http, $q, config, userInfo) { var vm = this; vm.checkCredit = checkCredit; @@ -594,7 +594,7 @@ Mientras que esta guía explica el *qué*, *por qué* y *cómo*, me resulta úti ``` ```javascript - /* recommended */ + /* recomendado */ function Order(creditService) { var vm = this; vm.checkCredit = checkCredit; @@ -612,21 +612,21 @@ Mientras que esta guía explica el *qué*, *por qué* y *cómo*, me resulta úti ### Keep Controllers Focused ###### [Style [Y037](#style-y037)] - - Define a controller for a view, and try not to reuse the controller for other views. Instead, move reusable logic to factories and keep the controller simple and focused on its view. + - Define un controller para una vista, no intentes reutilizar el controller para otras views. En lugar de eso, mueve la lógica que se pueda reutilizar en factories y deja el controller simple, enfocándose en su view. - *¿Por qué?*: Reusing controllers with several views is brittle and good end to end (e2e) test coverage is required to ensure stability across large applications. + *¿Por qué?*: Reutilizar controllers con varias views es arriesgado y necesitarías un buen end to end (e2e) test para asegurar que todo funciona bien en la aplicación. ### Assigning Controllers ###### [Style [Y038](#style-y038)] - - When a controller must be paired with a view and either component may be re-used by other controllers or views, define controllers along with their routes. + - Cuando un controller debe ser asociado a una view y cada componente puede ser reutilizado por otros controllers o views, define controllers con sus rutas. - Note: If a View is loaded via another means besides a route, then use the `ng-controller="Avengers as vm"` syntax. + Nota: Si una View es cargada por otra además de por la ruta, entonces usa la sintaxis `ng-controller="Avengers as vm"`. - *¿Por qué?*: Pairing the controller in the route allows different routes to invoke different pairs of controllers and views. When controllers are assigned in the view using [`ng-controller`](https://docs.angularjs.org/api/ng/directive/ngController), that view is always associated with the same controller. + *¿Por qué?*: Emparejar el controller en la ruta permite a diferentes rutas invocar diferentes pares de controllers y views. Cuando los controllers son asignados en la view usando [`ng-controller`](https://docs.angularjs.org/api/ng/directive/ngController), esa view siempre estará asociada al mismo controller. ```javascript - /* avoid - when using with a route and dynamic pairing is desired */ + /* evitar - cuando se use con una ruta y queramos asociarlo dinámicamente */ // route-config.js angular @@ -648,7 +648,7 @@ Mientras que esta guía explica el *qué*, *por qué* y *cómo*, me resulta úti ``` ```javascript - /* recommended */ + /* recomendado */ // route-config.js angular @@ -678,9 +678,9 @@ Mientras que esta guía explica el *qué*, *por qué* y *cómo*, me resulta úti ### Singletons ###### [Style [Y040](#style-y040)] - - Services are instantiated with the `new` keyword, use `this` for public methods and variables. Since these are so similar to factories, use a factory instead for consistency. + - Los Services son instanciados con un `new`, usan `this` para los métodos públicos y las variables. Ya que son muy similares a las factories, usa una factory en su lugar por consistencia. - Note: [All AngularJS services are singletons](https://docs.angularjs.org/guide/services). This means that there is only one instance of a given service per injector. + Nota: [Todos los servicios AngularJS son singletons](https://docs.angularjs.org/guide/services). Esto significa que sólo hay una instancia de un servicio por inyector. ```javascript // service @@ -717,28 +717,28 @@ Mientras que esta guía explica el *qué*, *por qué* y *cómo*, me resulta úti ### Single Responsibility ###### [Style [Y050](#style-y050)] - - Factories should have a [single responsibility](http://en.wikipedia.org/wiki/Single_responsibility_principle), that is encapsulated by its context. Once a factory begins to exceed that singular purpose, a new factory should be created. + - Las factories deben tener una [responsabilidad única](http://en.wikipedia.org/wiki/Single_responsibility_principle), que es encapsulada por su contexto. Cuando una factory empiece a exceder el principio de responsabilidad única, una nueva factory debe ser creada. ### Singletons ###### [Style [Y051](#style-y051)] - - Factories are singletons and return an object that contains the members of the service. + - Las Factories son singletos y devuelven un objeto que contiene las variables del servicio. - Note: [All AngularJS services are singletons](https://docs.angularjs.org/guide/services). + Nota: [Todos los servicios AngularJS son singletons](https://docs.angularjs.org/guide/services). ### Accessible Members Up Top ###### [Style [Y052](#style-y052)] - - Expose the callable members of the service (it's interface) at the top, using a technique derived from the [Revealing Module Pattern](http://addyosmani.com/resources/essentialjsdesignpatterns/book/#revealingmodulepatternjavascript). + - Expón las variables que se llaman del servicio (su interfaz) arriba, usando la técnica deribada de [Revealing Module Pattern](http://addyosmani.com/resources/essentialjsdesignpatterns/book/#revealingmodulepatternjavascript). - *¿Por qué?*: Placing the callable members at the top makes it easy to read and helps you instantly identify which members of the service can be called and must be unit tested (and/or mocked). + *¿Por qué?*: Colocar los elementos que se llamand arriba hace más fácil la lectura y te ayuda a identificar los elementos del servicio que se pueden llamar y se deben testear (y/o mockear). - *¿Por qué?*: This is especially helpful when the file gets longer as it helps avoid the need to scroll to see what is exposed. + *¿Por qué?*: Es especialmente útil cuando el archivo se hace más largo, ya que ayuda a evitar el scroll para ver qué se expone. - *¿Por qué?*: Setting functions as you go can be easy, but when those functions are more than 1 line of code they can reduce the readability and cause more scrolling. Defining the callable interface via the returned service moves the implementation details down, keeps the callable interface up top, and makes it easier to read. + *¿Por qué?*: Setear las funciones puede ser fácil, pero cuando tienen más de una línea ser reduce la legibilidad. Definiendo la interfaz mueve los detalles de implementación abajo, mantiene la interfaz que se llama arriba y lo hace más fácil de leer. ```javascript - /* avoid */ + /* evitar */ function dataService() { var someValue = ''; function save() { @@ -757,7 +757,7 @@ Mientras que esta guía explica el *qué*, *por qué* y *cómo*, me resulta úti ``` ```javascript - /* recommended */ + /* recomendado */ function dataService() { var someValue = ''; var service = { @@ -779,29 +779,29 @@ Mientras que esta guía explica el *qué*, *por qué* y *cómo*, me resulta úti } ``` - This way bindings are mirrored across the host object, primitive values cannot update alone using the revealing module pattern + De esta forma se asocian los enlaces desde el objeto que lo mantiene, los valores primitivos no se pueden modificar por si solos usando este patrón - ![Factories Using "Above the Fold"](https://raw.githubusercontent.com/johnpapa/angularjs-styleguide/master/assets/above-the-fold-2.png) + ![Factories Usando "Above the Fold"](https://raw.githubusercontent.com/johnpapa/angularjs-styleguide/master/assets/above-the-fold-2.png) ### Function Declarations to Hide Implementation Details ###### [Style [Y053](#style-y053)] - - Use function declarations to hide implementation details. Keep your accessible members of the factory up top. Point those to function declarations that appears later in the file. For more details see [this post](http://www.johnpapa.net/angular-function-declarations-function-expressions-and-readable-code). + - Declara funciones para esconder detalles de implementación. Manten los elementos accesibles en la parte superior de la factory. Referencia a los que aparezcan después en el archivo. Para más detalles visita [este post](http://www.johnpapa.net/angular-function-declarations-function-expressions-and-readable-code). - *¿Por qué?*: Placing accessible members at the top makes it easy to read and helps you instantly identify which functions of the factory you can access externally. + *¿Por qué?*: Coloca los elementos accesibles en la parte superior para hacerlo más fácil de leer y ayudarte instantáneamente a identificar qué funciones de la factory te pueden ayudar externamente. - *¿Por qué?*: Placing the implementation details of a function later in the file moves that complexity out of view so you can see the important stuff up top. + *¿Por qué?*: Colocar los detalles de implementación de una función al final del archivo mueve esa complegidad fuera de la vista, de esta forma puedes dejar lo importante arriba. - *¿Por qué?*: Function declaration are hoisted so there are no concerns over using a function before it is defined (as there would be with function expressions). + *¿Por qué?*: Las declaraciones de las funciones son "hoisted" de esta forma no hay problemas en usar una función antes de su definición (como la habría si fuera una expresión). - *¿Por qué?*: You never have to worry with function declarations that moving `var a` before `var b` will break your code because `a` depends on `b`. + *¿Por qué?*: No tendrás que propcuparte de que si pones `var a` antes de `var b` se rompa el código porque `a` dependa de `b`. - *¿Por qué?*: Order is critical with function expressions + *¿Por qué?*: El orden es crítico para las expresiones ```javascript /** - * avoid - * Using function expressions + * evitar + * Usar function expressions */ function dataservice($http, $location, $q, exception, logger) { var isPrimed = false; @@ -840,7 +840,7 @@ Mientras que esta guía explica el *qué*, *por qué* y *cómo*, me resulta úti ```javascript /** - * recommended + * recomendado * Using function declarations * and accessible members up top. */ @@ -888,16 +888,16 @@ Mientras que esta guía explica el *qué*, *por qué* y *cómo*, me resulta úti ### Separate Data Calls ###### [Style [Y060](#style-y060)] - - Refactor logic for making data operations and interacting with data to a factory. Make data services responsible for XHR calls, local storage, stashing in memory, or any other data operations. + - Refactoriza la lógica para hacer operaciones e interaciones con datos en una factory, que los servicios responsables de las peticiones XHR, local storage, memoria o cualquier otra operación con datos. - *¿Por qué?*: The controller's responsibility is for the presentation and gathering of information for the view. It should not care how it gets the data, just that it knows who to ask for it. Separating the data services moves the logic on how to get it to the data service, and lets the controller be simpler and more focused on the view. + *¿Por qué?*: La responsabilidad del controller es la presentación y recoger la información para la view. No debe importarle cómo se consiguen los datos, sólo saber cómo conseguirlos. Separando los servicios de datos movemos la lógica de cómo conseguirlos al servicio de datos, y deja el controller simple, enfocandose en la vista. - *¿Por qué?*: This makes it easier to test (mock or real) the data calls when testing a controller that uses a data service. + *¿Por qué?*: Lo hace más fácil de testear (mock o real) las llamadas de datos cuando testeamos un controller que usa un servicio de datos. - *¿Por qué?*: Data service implementation may have very specific code to handle the data repository. This may include headers, how to talk to the data, or other services such as $http. Separating the logic into a data service encapsulates this logic in a single place hiding the implementation from the outside consumers (perhaps a controller), also making it easier to change the implementation. + *¿Por qué?*: La implementación del servicio de datos puede tener código muy específico para usar el repositorio de datos. Podría incluir cabeceras, cómo hablar a los datos, u otros servicios como $http. Separando la lógica en servicios de datos encapsulamos la lógica en un único lugar, escondiendo la implementación de sus consumidores externos (quizá un controller), de esta forma es más fácil cambiar la implementación. ```javascript - /* recommended */ + /* recomendado */ // dataservice factory angular @@ -927,12 +927,12 @@ Mientras que esta guía explica el *qué*, *por qué* y *cómo*, me resulta úti } ``` - Note: The data service is called from consumers, such as a controller, hiding the implementation from the consumers, as shown below. + Nota: El servicio de datos es llamado desde los consumidores, como el controller, escondiendo la implementación del consumidor como se muestra a continuación. ```javascript - /* recommended */ + /* recomendado */ - // controller calling the dataservice factory + // controller llamando a la factory del servicio de datos angular .module('app.avengers') .controller('Avengers', Avengers); @@ -964,25 +964,25 @@ Mientras que esta guía explica el *qué*, *por qué* y *cómo*, me resulta úti ### Return a Promise from Data Calls ###### [Style [Y061](#style-y061)] - - When calling a data service that returns a promise such as $http, return a promise in your calling function too. + - Cuando llamamos a servicios de datos que devuelven una promesa como $http, devuelve una promesa en la llamada de tu función también. - *¿Por qué?*: You can chain the promises together and take further action after the data call completes and resolves or rejects the promise. + *¿Por qué?*: Puedes encadenar promesas y hacer algo cuando la llamada se complete y resuelva o rechaze la promesa. ```javascript - /* recommended */ + /* recomendado */ activate(); function activate() { /** * Step 1 - * Ask the getAvengers function for the - * avenger data and wait for the promise + * Pide a la función getAvengers por los datos + * de los vengadores y espera la promesa */ return getAvengers().then(function() { /** * Step 4 - * Perform an action on resolve of final promise + * Ejecuta una acción cuando se resuelva la promesa final */ logger.info('Activated Avengers View'); }); @@ -991,14 +991,14 @@ Mientras que esta guía explica el *qué*, *por qué* y *cómo*, me resulta úti function getAvengers() { /** * Step 2 - * Ask the data service for the data and wait - * for the promise + * Pide al servicio de datos los datos y espera + * por la promesa */ return dataservice.getAvengers() .then(function(data) { /** * Step 3 - * set the data and resolve the promise + * setea los datos y resuelva la promesa */ vm.avengers = data; return vm.avengers; @@ -1012,14 +1012,14 @@ Mientras que esta guía explica el *qué*, *por qué* y *cómo*, me resulta úti ### Limit 1 Per File ###### [Style [Y070](#style-y070)] - - Create one directive per file. Name the file for the directive. + - Crea una directiva por archivo. Llama al archivo como la directiva. - *¿Por qué?*: It is easy to mash all the directives in one file, but difficult to then break those out so some are shared across apps, some across modules, some just for one module. + *¿Por qué?*: Es muy fácil colocar todas las directivas en un archivo, pero será más difícil de partir para ser compartida entre aplicaciones, modulos o para un simple módulo. - *¿Por qué?*: One directive per file is easy to maintain. + *¿Por qué?*: Una directiva por archivo es fácil de mantener. ```javascript - /* avoid */ + /* evitar */ /* directives.js */ angular @@ -1048,7 +1048,7 @@ Mientras que esta guía explica el *qué*, *por qué* y *cómo*, me resulta úti ``` ```javascript - /* recommended */ + /* recomendado */ /* calendarRange.directive.js */ /** @@ -1065,7 +1065,7 @@ Mientras que esta guía explica el *qué*, *por qué* y *cómo*, me resulta úti ``` ```javascript - /* recommended */ + /* recomendado */ /* customerInfo.directive.js */ /** @@ -1082,7 +1082,7 @@ Mientras que esta guía explica el *qué*, *por qué* y *cómo*, me resulta úti ``` ```javascript - /* recommended */ + /* recomendado */ /* spinner.directive.js */ /** @@ -1098,42 +1098,42 @@ Mientras que esta guía explica el *qué*, *por qué* y *cómo*, me resulta úti } ``` - Note: There are many naming options for directives, especially since they can be used in narrow or wide scopes. Choose one that makes the directive and it's file name distinct and clear. Some examples are below, but see the naming section for more recommendations. + Nota: Hay muchas formas de llamar a las directivas, especialmente cuando pueden ser usadas en scopes específicas. Elige un nombre que tenga sentido para la directiva y que su archivo sea distintivo y claro. Hemos visto algunos ejemplos antes, pero veremos más en la sección de cómo nombrar. ### Manipulate DOM in a Directive ###### [Style [Y072](#style-y072)] - - When manipulating the DOM directly, use a directive. If alternative ways can be used such as using CSS to set styles or the [animation services](https://docs.angularjs.org/api/ngAnimate), Angular templating, [`ngShow`](https://docs.angularjs.org/api/ng/directive/ngShow) or [`ngHide`](https://docs.angularjs.org/api/ng/directive/ngHide), then use those instead. For example, if the directive simply hides and shows, use ngHide/ngShow. + - Cuando manipules DOM directamente, usa una directiva. Si hay alguna alternativa como usando un CSS para cambiar el estilo o el [animation services](https://docs.angularjs.org/api/ngAnimate), Angular templating, [`ngShow`](https://docs.angularjs.org/api/ng/directive/ngShow) o [`ngHide`](https://docs.angularjs.org/api/ng/directive/ngHide), Entonces úsalos en su lugar. Por ejemplo, si la directiva sólo muestra o esconde elementos, usa ngHide/ngShow. - *¿Por qué?*: DOM manipulation can be difficult to test, debug, and there are often better ways (e.g. CSS, animations, templates) + *¿Por qué?*: Manipular el DOM puede ser dificil de testear, debugear y normalmente hay mejores maneras (e.g. CSS, animations, templates) ### Provide a Unique Directive Prefix ###### [Style [Y073](#style-y073)] - - Provide a short, unique and descriptive directive prefix such as `acmeSalesCustomerInfo` which is declared in HTML as `acme-sales-customer-info`. + - Proporciona prefijo corto, único y descriptiovo como `acmeSalesCustomerInfo` que se declara en el HTML como `acme-sales-customer-info`. - *¿Por qué?*: The unique short prefix identifies the directive's context and origin. For example a prefix of `cc-` may indicate that the directive is part of a CodeCamper app while `acme-` may indicate a directive for the Acme company. + *¿Por qué?*: El prefijo corto y único identifica el contexto de la directiva y el origen. Por ejemplo el prefijo `cc-` puede indicar que la directiva en particular es parte de la aplicación CodeCamper, mientras que `acme-` pudiera indicar que la directiva es de la compañía Acme. - Note: Avoid `ng-` as these are reserved for AngularJS directives. Research widely used directives to avoid naming conflicts, such as `ion-` for the [Ionic Framework](http://ionicframework.com/). + Nota: Evita `ng-` ya que está reservado para las directivas AngularJS. Estudia sabiamente las directivas usadas para evitar conflictos de nombres, como `ion-` de [Ionic Framework](http://ionicframework.com/). ### Restrict to Elements and Attributes ###### [Style [Y074](#style-y074)] - - When creating a directive that makes sense as a stand-alone element, allow restrict `E` (custom element) and optionally restrict `A` (custom attribute). Generally, if it could be its own control, `E` is appropriate. General guideline is allow `EA` but lean towards implementing as an element when its stand-alone and as an attribute when it enhances its existing DOM element. + - Cuando crees directivas que tengan sentido como elemento, restringe `E` (elemento personalizado) y opcionalmente restringe `A` (atributo personalizado). Generalmente, si puede ser su control propio, `E` es apropiado, La guía genera es permitir `EA` pero intenta implementarlo como un elemento cuando sea un elemento único y como un atributo cuando añada elementos a su propio DOM. - *¿Por qué?*: It makes sense. + *¿Por qué?*: Tiene sentido. - *¿Por qué?*: While we can allow the directive to be used as a class, if the directive is truly acting as an element it makes more sense as an element or at least as an attribute. + *¿Por qué?*: Mientras permitamos que una directiva sea usada como una clase, si esa directiva realmente estáa actuando como un elemento, tiene sentido que sea un elemento, o al menos un atributo. - Note: EA is the default for AngularJS 1.3 + + Nota: En AngularJS 1.3 + EA es el valor por defecto ```html - +
``` ```javascript - /* avoid */ + /* evitar */ angular .module('app.widgets') .directive('myCalendarRange', myCalendarRange); @@ -1153,13 +1153,13 @@ Mientras que esta guía explica el *qué*, *por qué* y *cómo*, me resulta úti ``` ```html - +
``` ```javascript - /* recommended */ + /* recomendado */ angular .module('app.widgets') .directive('myCalendarRange', myCalendarRange); @@ -1308,7 +1308,7 @@ Mientras que esta guía explica el *qué*, *por qué* y *cómo*, me resulta úti Note: If you need to conditionally cancel the route before you start use the controller, use a [route resolve](#style-y081) instead. ```javascript - /* avoid */ + /* evitar */ function Avengers(dataservice) { var vm = this; vm.avengers = []; @@ -1322,7 +1322,7 @@ Mientras que esta guía explica el *qué*, *por qué* y *cómo*, me resulta úti ``` ```javascript - /* recommended */ + /* recomendado */ function Avengers(dataservice) { var vm = this; vm.avengers = []; @@ -1355,7 +1355,7 @@ Mientras que esta guía explica el *qué*, *por qué* y *cómo*, me resulta úti Note: The code executes before the route via a promise. Rejecting the promise cancels the route. Resolve makes the new view wait for the route to resolve. A “busy” animation can be shown before the resolve and through the view transition. If you want to get to the View faster and do not require a checkpoint to decide if you can get to the View, consider the [controller `activate` technique](#style-y080) instead. ```javascript - /* avoid */ + /* evitar */ angular .module('app') .controller('Avengers', Avengers); @@ -1484,7 +1484,7 @@ Mientras que esta guía explica el *qué*, *por qué* y *cómo*, me resulta úti *¿Por qué?*: Avoid creating in-line dependencies as long lists can be difficult to read in the array. Also it can be confusing that the array is a series of strings while the last item is the component's function. ```javascript - /* avoid */ + /* evitar */ angular .module('app') .controller('Dashboard', @@ -1494,7 +1494,7 @@ Mientras que esta guía explica el *qué*, *por qué* y *cómo*, me resulta úti ``` ```javascript - /* avoid */ + /* evitar */ angular .module('app') .controller('Dashboard', @@ -1505,7 +1505,7 @@ Mientras que esta guía explica el *qué*, *por qué* y *cómo*, me resulta úti ``` ```javascript - /* recommended */ + /* recomendado */ angular .module('app') .controller('Dashboard', Dashboard); @@ -1556,7 +1556,7 @@ Mientras que esta guía explica el *qué*, *por qué* y *cómo*, me resulta úti *¿Por qué?*: An `$inject` statement can easily precede the resolver to handle making any dependencies minification safe. ```javascript - /* recommended */ + /* recomendado */ function config($routeProvider) { $routeProvider .when('/avengers', { @@ -1700,7 +1700,7 @@ Mientras que esta guía explica el *qué*, *por qué* y *cómo*, me resulta úti Note: Another option is to override the service instead of using a decorator. This is a fine option, but if you want to keep the default behavior and extend it a decorator is recommended. ```javascript - /* recommended */ + /* recomendado */ angular .module('blocks.exception') .config(exceptionConfig); @@ -1741,7 +1741,7 @@ Mientras que esta guía explica el *qué*, *por qué* y *cómo*, me resulta úti Note: The exception catcher is good for catching and reacting to specific exceptions from calls that you know may throw one. For example, when making an XHR call to retrieve data from a remote web service and you want to catch any exceptions from that service and react uniquely. ```javascript - /* recommended */ + /* recomendado */ angular .module('blocks.exception') .factory('exception', exception); @@ -1772,7 +1772,7 @@ Mientras que esta guía explica el *qué*, *por qué* y *cómo*, me resulta úti *¿Por qué?*: Potentially provides a better user experience if a routing error occurs and you route them to a friendly screen with more details or recovery options. ```javascript - /* recommended */ + /* recomendado */ function handleRoutingErrors() { /** * Route cancellation: From cc8c03e488125f2ee1bda843da511493392ec3fa Mon Sep 17 00:00:00 2001 From: angelochiello Date: Mon, 16 Feb 2015 09:18:34 +0100 Subject: [PATCH 185/567] [it-IT] #280 Updated as PR #280 --- i18n/it-IT.md | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/i18n/it-IT.md b/i18n/it-IT.md index 64a532c1..ffc84f3d 100644 --- a/i18n/it-IT.md +++ b/i18n/it-IT.md @@ -1779,6 +1779,8 @@ Nonostante questa guida spieghi i *cosa*, *come* e *perché*, trovo che sia di a ```javascript /* consigliato */ + var handlingRouteChangeError = false; + function handleRoutingErrors() { /** * Annullamento del route: @@ -1787,18 +1789,24 @@ Nonostante questa guida spieghi i *cosa*, *come* e *perché*, trovo che sia di a */ $rootScope.$on('$routeChangeError', function(event, current, previous, rejection) { - var destination = (current && (current.title || current.name || current.loadedTemplateUrl)) || + if (handlingRouteChangeError) { return; } + handlingRouteChangeError = true; + var destination = (current && (current.title || + current.name || current.loadedTemplateUrl)) || 'unknown target'; - var msg = 'Error routing to ' + destination + '. ' + (rejection.msg || ''); - /** - * Optionally log using a custom service or $log. - * (Don't forget to inject custom service) - */ + var msg = 'Error routing to ' + destination + '. ' + + (rejection.msg || ''); + /** * A scelta fai il log usando un servizio ad hoc o $log. * (Non dimenticare di iniettare il servizio ad hoc) */ logger.warning(msg, [current]); + + /** + * Su un errore di routing, vai ad un'altra route/stato. + */ + $location.path('/'); } ); } From be04d16c2395d8e5e282829be132909c711dfb64 Mon Sep 17 00:00:00 2001 From: angelochiello Date: Mon, 16 Feb 2015 09:25:02 +0100 Subject: [PATCH 186/567] [it-IT] PR #276 Updated as PR #276 "added a reference to a snippets package for Atom" --- i18n/it-IT.md | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/i18n/it-IT.md b/i18n/it-IT.md index ffc84f3d..027c0eb2 100644 --- a/i18n/it-IT.md +++ b/i18n/it-IT.md @@ -2727,6 +2727,27 @@ Usa file template o snippet che ti aiutino a seguire stili e schemi consistentem ng-f // crea una factory Angular ng-m // crea un modulo Angular ``` + +### Atom +###### [Stile [Y253](#stile-y253)] + + - Snippet di Angular JS e file di template che seguono queste linee guida. + ``` + apm install angularjs-styleguide-snippets + ``` + oppure + - Apri Atom, poi apri il Package Manager (Packages -> Settings View -> Install Packages/Themes) + - Cerca il pacchetto 'angularjs-styleguide-snippets' + - Clicca 'Install' per installare il pacchetto + + - In un file di JavaScript digita i seguenti comandi seguiti da un `TAB` + + ```javascript + ngcontroller // crea un controller Angular + ngdirective // crea una directive Angular + ngfactory // crea una factory Angular + ngmodule // crea un module Angular + ``` **[Torna all'inizio](#tavola-dei-contenuti)** From 4a82ed39fb45f946066131a3bf4674e79f9f0d19 Mon Sep 17 00:00:00 2001 From: John Papa Date: Mon, 16 Feb 2015 11:13:43 -0500 Subject: [PATCH 187/567] removed develop branch --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 1cb007c8..42d996c1 100644 --- a/README.md +++ b/README.md @@ -2828,7 +2828,7 @@ Open an issue first to discuss potential changes/additions. If you have question ### Process 1. Discuss the changes in a GitHub issue. - 2. Open a Pull Request against the develop branch, reference the issue, and explain the change and why it adds value. + 2. Open a Pull Request, reference the issue, and explain the change and why it adds value. 3. The Pull Request will be evaluated and either merged or declined. ## License From 20d225c7b860edde97342cb4ef70b6e26de14ae1 Mon Sep 17 00:00:00 2001 From: Alberto Date: Tue, 17 Feb 2015 23:47:51 +0000 Subject: [PATCH 188/567] More translations --- i18n/es-ES.md | 94 +++++++++++++++++++++++++-------------------------- 1 file changed, 47 insertions(+), 47 deletions(-) diff --git a/i18n/es-ES.md b/i18n/es-ES.md index e5db6786..b24772c6 100644 --- a/i18n/es-ES.md +++ b/i18n/es-ES.md @@ -1125,7 +1125,7 @@ Mientras que esta guía explica el *qué*, *por qué* y *cómo*, me resulta úti *¿Por qué?*: Mientras permitamos que una directiva sea usada como una clase, si esa directiva realmente estáa actuando como un elemento, tiene sentido que sea un elemento, o al menos un atributo. - Nota: En AngularJS 1.3 + EA es el valor por defecto + Nota: En AngularJS 1.3+ EA es el valor por defecto ```html @@ -1181,15 +1181,15 @@ Mientras que esta guía explica el *qué*, *por qué* y *cómo*, me resulta úti ### Directives and ControllerAs ###### [Style [Y075](#style-y075)] - - Use `controller as` syntax with a directive to be consistent with using `controller as` with view and controller pairings. + - Usa la sintaxis `controller as` con una directiva para ser consistente con el uso de `controller as` con los pares de view y controller. - *¿Por qué?*: It makes sense and it's not difficult. + *¿Por qué?*: Tiene sentido y no es dificil. - Note: The directive below demonstrates some of the ways you can use scope inside of link and directive controllers, using controllerAs. I in-lined the template just to keep it all in one place. + Nota: La siguiente directiva demuestra algunas de las formas en las que puedes usar el scope dentro de un link y controllers de una directiva, usando controllerAs. He puesto la template para dejarlo todo en un lugar. - Note: Regarding dependency injection, see [Manually Identify Dependencies](#manual-annotating-for-dependency-injection). + Nota: En cuanto a la inyección de dependencias, mira [Identificar Dependencias Manualmente](#manual-annotating-for-dependency-injection). - Note: Note that the directive's controller is outside the directive's closure. This style eliminates issues where the injection gets created as unreachable code after a `return`. + Nota: Nótese que la directiva controller está fuera del closure de la directiva. Este estilo elimina los problemas que genera la inyección de dependencias donde la inyección es creada en un código no alcanzable después del `return`. ```html
@@ -1247,11 +1247,11 @@ Mientras que esta guía explica el *qué*, *por qué* y *cómo*, me resulta úti ###### [Style [Y076](#style-y076)] - - Use `bindToController = true` when using `controller as` syntax with a directive when you want to bind the outer scope to the directive's controller's scope. + - Usa `bindToController = true` cuando uses `controller as` con una directiva cuando quieras asociar el scope exterior al scope del controller de la directiva. - *¿Por qué?*: It makes it easy to bind outer scope to the directive's controller scope. + *¿Por qué?*: Lo hace más fácil a la hora de asociar el scope exterior al scope del controller de la directiva. - Note: `bindToController` was introduced in Angular 1.3.0. + Nota: `bindToController` fue introducido en Angular 1.3.0. ```html
@@ -1299,13 +1299,13 @@ Mientras que esta guía explica el *qué*, *por qué* y *cómo*, me resulta úti ### Controller Activation Promises ###### [Style [Y080](#style-y080)] - - Resolve start-up logic for a controller in an `activate` function. + - Resuelve la lógica de inicialización de un controller en una función `activate`. - *¿Por qué?*: Placing start-up logic in a consistent place in the controller makes it easier to locate, more consistent to test, and helps avoid spreading out the activation logic across the controller. + *¿Por qué?*: Colocar la lógica de inicialización en un lugar consistente del controller lo hace más fácil de localizar, más consistente de testear, y ayuda a evitar que la lógica de activación se propage a lo largo del controller. - *¿Por qué?*: The controller `activate` makes it convenient to re-use the logic for a refresh for the controller/View, keeps the logic together, gets the user to the View faster, makes animations easy on the `ng-view` or `ui-view`, and feels snappier to the user. + *¿Por qué?*: El controller `activate` hace que la lógica para refrescar el controller/View sea reutilizable, mantiene la lógica junta, proporciona al usuario la View más rápido, hace las animacines más fáciles en `ng-view` o `ui-view` y lo hace más rápido a la vista del usuario. - Note: If you need to conditionally cancel the route before you start use the controller, use a [route resolve](#style-y081) instead. + Nota: Si necesitas condicionalmente cancelar la ruta antes de empezar el controller, usa en su lugar [route resolve](#style-y081). ```javascript /* evitar */ @@ -1344,15 +1344,15 @@ Mientras que esta guía explica el *qué*, *por qué* y *cómo*, me resulta úti ### Route Resolve Promises ###### [Style [Y081](#style-y081)] - - When a controller depends on a promise to be resolved before the controller is activated, resolve those dependencies in the `$routeProvider` before the controller logic is executed. If you need to conditionally cancel a route before the controller is activated, use a route resolver. + - Cuando un controller depende en una promesa a ser resuelta antes de que el controller se active, resuelve esas dependencias en el `$routeProvider` antes de que la lógica del controller sea ejecutada. Si necesitas condicionalmente cancelar una ruta antes de que el controller sea activado, usa un route resolver. - - Use a route resolve when you want to decide to cancel the route before ever transitioning to the View. + - Usa un route resolver cuando decidas cancelar la ruta antes de transicionar la View. - *¿Por qué?*: A controller may require data before it loads. That data may come from a promise via a custom factory or [$http](https://docs.angularjs.org/api/ng/service/$http). Using a [route resolve](https://docs.angularjs.org/api/ngRoute/provider/$routeProvider) allows the promise to resolve before the controller logic executes, so it might take action based on that data from the promise. + *¿Por qué?*: Un controller puede requerir datos antes de que se cargue. Esos datos deben venir desde una promesa a través de una factory o de [$http](https://docs.angularjs.org/api/ng/service/$http). Using a [route resolve](https://docs.angularjs.org/api/ngRoute/provider/$routeProvider) permitiendo que la promesa se resuelva antes de que la lógica del controller se ejecute, así puedes tomar decisiones basándote en los datos de la promesa. - *¿Por qué?*: The code executes after the route and in the controller’s activate function. The View starts to load right away. Data binding kicks in when the activate promise resolves. A “busy” animation can be shown during the view transition (via ng-view or ui-view) + *¿Por qué?*: El código se ejecuta después de la ruta y la función activate del controller. La View empieza a cargar al instante. Los Data binding se ejecutan cuando la promesa del activate se resuelva. Una animación de "Cargando" se puede mostrar mientras la transición de la view (via ng-view o ui-view) - Note: The code executes before the route via a promise. Rejecting the promise cancels the route. Resolve makes the new view wait for the route to resolve. A “busy” animation can be shown before the resolve and through the view transition. If you want to get to the View faster and do not require a checkpoint to decide if you can get to the View, consider the [controller `activate` technique](#style-y080) instead. + Nota: El código se ejecuta antes que la ruta mediante una promesa. Rechazar la promesa cancela la ruta. Resolverla hace que la nueva view espere a que la ruta sea resuelta. Una animación de "Cargando" puede ser mostrada antes de que se resuelva. Si quieres que la View aparezca más rápido y no necesitas un checkpoint para decidir si puedes mostrar o no la view, considera la técnica [controller `activate`](#style-y080). ```javascript /* evitar */ @@ -1405,7 +1405,7 @@ Mientras que esta guía explica el *qué*, *por qué* y *cómo*, me resulta úti } ``` - Note: The example below shows the route resolve points to a named function, which is easier to debug and easier to handle dependency injection. + Nota: El siguiente ejemplo muestra una ruta que cuando se resuelve apunta a una función, haciéndolo más fácil de debugear y más fácil de manejar inyección de dependencias. ```javascript /* even better */ @@ -1442,7 +1442,7 @@ Mientras que esta guía explica el *qué*, *por qué* y *cómo*, me resulta úti vm.movies = moviesPrepService.movies; } ``` - Note: The code example's dependency on `movieService` is not minification safe on its own. For details on how to make this code minification safe, see the sections on [dependency injection](#manual-annotating-for-dependency-injection) and on [minification and annotation](#minification-and-annotation). + Nota: El código del ejemplo de dependencia en `movieService` no se puede minimizar tal cual. Para detalles en cómo hacer este código sea minimizable, mira la sección de [inyección de dependencias](#manual-annotating-for-dependency-injection) y en [minimización y anotación](#minification-and-annotation). **[Volver arriba](#table-of-contents)** @@ -1451,12 +1451,12 @@ Mientras que esta guía explica el *qué*, *por qué* y *cómo*, me resulta úti ### UnSafe from Minification ###### [Style [Y090](#style-y090)] - - Avoid using the shortcut syntax of declaring dependencies without using a minification-safe approach. + - Evita usar la sintaxis acortada para declarar dependencias sin usar algún método que permita minimifación. - *¿Por qué?*: The parameters to the component (e.g. controller, factory, etc) will be converted to mangled variables. For example, `common` and `dataservice` may become `a` or `b` and not be found by AngularJS. + *¿Por qué?*: Los parámetros al componente (e.g. controller, factory, etc) se convertirán en variables acortadas. Por ejemplo, `common` y `dataservice` se convertirán `a` o `b` y no serán encontradas por AngularJS. ```javascript - /* avoid - not minification-safe*/ + /* evitar - not minification-safe*/ angular .module('app') .controller('Dashboard', Dashboard); @@ -1465,23 +1465,23 @@ Mientras que esta guía explica el *qué*, *por qué* y *cómo*, me resulta úti } ``` - This code may produce mangled variables when minified and thus cause runtime errors. + Este código acortará las variables cuando se minimice y causará errores en tiempo de ejecución. ```javascript - /* avoid - not minification-safe*/ + /* evitar - not minification-safe*/ angular.module('app').controller('Dashboard', d);function d(a, b) { } ``` ### Manually Identify Dependencies ###### [Style [Y091](#style-y091)] - - Use `$inject` to manually identify your dependencies for AngularJS components. + - Usa `$inject` Para identificar manualmente las dependencias de tus componentes AngularJS. - *¿Por qué?*: This technique mirrors the technique used by [`ng-annotate`](https://github.com/olov/ng-annotate), which I recommend for automating the creation of minification safe dependencies. If `ng-annotate` detects injection has already been made, it will not duplicate it. + *¿Por qué?*: Esta técnica es la misma que se usa con [`ng-annotate`](https://github.com/olov/ng-annotate), la cuál recomiendo para automatizar la creación de dependencias minificadas de forma segura. Si `ng-annotate` detecta que la inyección ha sido hecha, no la duplicará. - *¿Por qué?*: This safeguards your dependencies from being vulnerable to minification issues when parameters may be mangled. For example, `common` and `dataservice` may become `a` or `b` and not be found by AngularJS. + *¿Por qué?*: Esto salvaguarda tus dependencias de ser vulnerables de problemas a la hora de minimizar cuando los parámetros se acorten. Por ejemplo, `common` y `dataservice` se convertirán `a` o `b` y no serán encontradas por AngularJS. - *¿Por qué?*: Avoid creating in-line dependencies as long lists can be difficult to read in the array. Also it can be confusing that the array is a series of strings while the last item is the component's function. + *¿Por qué?*: Evita crear dependencias en la línea, ya que las listas largas pueden ser dificil de leer en el array. También puede ser confuso que el array es una serie de cadenas mientras que el último componente e suna función. ```javascript /* evitar */ @@ -1516,27 +1516,27 @@ Mientras que esta guía explica el *qué*, *por qué* y *cómo*, me resulta úti } ``` - Note: When your function is below a return statement the $inject may be unreachable (this may happen in a directive). You can solve this by either moving the $inject above the return statement or by using the alternate array injection syntax. + Nota: Cuando tu función está debajo de un return, $inject puede ser inalcanzable (esto puede pasar en una directiva). Puedes solucionarlo moviendo el $inject encima del return o usando la sintaxis de array para inyectar.by either moving the $inject above the return statement or by using the alternate array injection syntax. - Note: [`ng-annotate 0.10.0`](https://github.com/olov/ng-annotate) introduced a feature where it moves the `$inject` to where it is reachable. + Nota: [`ng-annotate 0.10.0`](https://github.com/olov/ng-annotate) introduce una funcionalidad donde mueve `$inject` donde es alcanzable. ```javascript - // inside a directive definition + // dentro de la definición de una directiva function outer() { return { controller: DashboardPanel, }; - DashboardPanel.$inject = ['logger']; // Unreachable + DashboardPanel.$inject = ['logger']; // Inalcanzable function DashboardPanel(logger) { } } ``` ```javascript - // inside a directive definition + // dentro de la definición de una directiva function outer() { - DashboardPanel.$inject = ['logger']; // reachable + DashboardPanel.$inject = ['logger']; // alcanzable return { controller: DashboardPanel, }; @@ -1632,9 +1632,9 @@ Mientras que esta guía explica el *qué*, *por qué* y *cómo*, me resulta úti Avengers.$inject = ['storageService', 'avengerService']; ``` - Note: If `ng-annotate` detects injection has already been made (e.g. `@ngInject` was detected), it will not duplicate the `$inject` code. + Nota: If `ng-annotate` detects injection has already been made (e.g. `@ngInject` was detected), it will not duplicate the `$inject` code. - Note: When using a route resolver you can prefix the resolver's function with `/* @ngInject */` and it will produce properly annotated code, keeping any injected dependencies minification safe. + Nota: When using a route resolver you can prefix the resolver's function with `/* @ngInject */` and it will produce properly annotated code, keeping any injected dependencies minification safe. ```javascript // Using @ngInject annotations @@ -1653,7 +1653,7 @@ Mientras que esta guía explica el *qué*, *por qué* y *cómo*, me resulta úti } ``` - > Note: Starting from AngularJS 1.3 use the [`ngApp`](https://docs.angularjs.org/api/ng/directive/ngApp) directive's `ngStrictDi` parameter. When present the injector will be created in "strict-di" mode causing the application to fail to invoke functions which do not use explicit function annotation (these may not be minification safe). Debugging info will be logged to the console to help track down the offending code. + > Nota: Starting from AngularJS 1.3 use the [`ngApp`](https://docs.angularjs.org/api/ng/directive/ngApp) directive's `ngStrictDi` parameter. When present the injector will be created in "strict-di" mode causing the application to fail to invoke functions which do not use explicit function annotation (these may not be minification safe). Debugging info will be logged to the console to help track down the offending code. `` ### Use Gulp or Grunt for ng-annotate @@ -1697,7 +1697,7 @@ Mientras que esta guía explica el *qué*, *por qué* y *cómo*, me resulta úti *¿Por qué?*: Provides a consistent way to handle uncaught AngularJS exceptions for development-time or run-time. - Note: Another option is to override the service instead of using a decorator. This is a fine option, but if you want to keep the default behavior and extend it a decorator is recommended. + Nota: Another option is to override the service instead of using a decorator. This is a fine option, but if you want to keep the default behavior and extend it a decorator is recommended. ```javascript /* recomendado */ @@ -1738,7 +1738,7 @@ Mientras que esta guía explica el *qué*, *por qué* y *cómo*, me resulta úti *¿Por qué?*: Provides a consistent way to catch exceptions that may be thrown in your code (e.g. during XHR calls or promise failures). - Note: The exception catcher is good for catching and reacting to specific exceptions from calls that you know may throw one. For example, when making an XHR call to retrieve data from a remote web service and you want to catch any exceptions from that service and react uniquely. + Nota: The exception catcher is good for catching and reacting to specific exceptions from calls that you know may throw one. For example, when making an XHR call to retrieve data from a remote web service and you want to catch any exceptions from that service and react uniquely. ```javascript /* recomendado */ @@ -1865,7 +1865,7 @@ Mientras que esta guía explica el *qué*, *por qué* y *cómo*, me resulta úti avenger-profile.directive.spec.js ``` - Note: Another common convention is naming controller files without the word `controller` in the file name such as `avengers.js` instead of `avengers.controller.js`. All other conventions still hold using a suffix of the type. Controllers are the most common type of component so this just saves typing and is still easily identifiable. I recommend you choose 1 convention and be consistent for your team. + Nota: Another common convention is naming controller files without the word `controller` in the file name such as `avengers.js` instead of `avengers.controller.js`. All other conventions still hold using a suffix of the type. Controllers are the most common type of component so this just saves typing and is still easily identifiable. I recommend you choose 1 convention and be consistent for your team. ```javascript /** @@ -2089,7 +2089,7 @@ Mientras que esta guía explica el *qué*, *por qué* y *cómo*, me resulta úti - Have a near term view of implementation and a long term vision. In other words, start small and but keep in mind on where the app is heading down the road. All of the app's code goes in a root folder named `app`. All content is 1 feature per file. Each controller, service, module, view is in its own file. All 3rd party vendor scripts are stored in another root folder and not in the `app` folder. I didn't write them and I don't want them cluttering my app (`bower_components`, `scripts`, `lib`). - Note: Find more details and reasoning behind the structure at [this original post on application structure](http://www.johnpapa.net/angular-app-structuring-guidelines/). + Nota: Find more details and reasoning behind the structure at [this original post on application structure](http://www.johnpapa.net/angular-app-structuring-guidelines/). ### Layout ###### [Style [Y151](#style-y151)] @@ -2151,7 +2151,7 @@ Mientras que esta guía explica el *qué*, *por qué* y *cómo*, me resulta úti ![Sample App Structure](https://raw.githubusercontent.com/johnpapa/angularjs-styleguide/master/assets/modularity-2.png) - Note: Do not use structuring using folders-by-type. This requires moving to multiple folders when working on a feature and gets unwieldy quickly as the app grows to 5, 10 or 25+ views and controllers (and other features), which makes it more difficult than folder-by-feature to locate files. + Nota: Do not use structuring using folders-by-type. This requires moving to multiple folders when working on a feature and gets unwieldy quickly as the app grows to 5, 10 or 25+ views and controllers (and other features), which makes it more difficult than folder-by-feature to locate files. ```javascript /* @@ -2250,7 +2250,7 @@ Mientras que esta guía explica el *qué*, *por qué* y *cómo*, me resulta úti *¿Por qué?*: Intra-App features such as shared data services become easy to locate and share from within `app.core` (choose your favorite name for this module). - Note: This is a strategy for consistency. There are many good options here. Choose one that is consistent, follows AngularJS's dependency rules, and is easy to maintain and scale. + Nota: This is a strategy for consistency. There are many good options here. Choose one that is consistent, follows AngularJS's dependency rules, and is easy to maintain and scale. > My structures vary slightly between projects but they all follow these guidelines for structure and modularity. The implementation may vary depending on the features and the team. In other words, don't get hung up on an exact like-for-like structure but do justify your structure using consistency, maintainability, and efficiency in mind. @@ -2369,7 +2369,7 @@ Unit testing helps maintain clean code, as such I included some of my recommenda *¿Por qué?*: Both Jasmine and Mocha are widely used in the AngularJS community. Both are stable, well maintained, and provide robust testing features. - Note: When using Mocha, also consider choosing an assert library such as [Chai](http://chaijs.com). + Nota: When using Mocha, also consider choosing an assert library such as [Chai](http://chaijs.com). ### Test Runner ###### [Style [Y192](#style-y192)] @@ -2400,7 +2400,7 @@ Unit testing helps maintain clean code, as such I included some of my recommenda *¿Por qué?*: PhantomJS is a headless browser that helps run your tests without needing a "visual" browser. So you do not have to install Chrome, Safari, IE, or other browsers on your server. - Note: You should still test on all browsers in your environment, as appropriate for your target audience. + Nota: You should still test on all browsers in your environment, as appropriate for your target audience. ### Code Analysis ###### [Style [Y195](#style-y195)] @@ -2480,7 +2480,7 @@ Unit testing helps maintain clean code, as such I included some of my recommenda *¿Por qué?*: animate.css is widely used and tested. - Note: See this [great post by Matias Niemelä on AngularJS animations](http://www.yearofmoo.com/2013/08/remastered-animation-in-angularjs-1-2.html) + Nota: See this [great post by Matias Niemelä on AngularJS animations](http://www.yearofmoo.com/2013/08/remastered-animation-in-angularjs-1-2.html) **[Volver arriba](#table-of-contents)** From a8af5bfb53316416e87ba5d678ea703b0d3a0ad8 Mon Sep 17 00:00:00 2001 From: Andrew Smith Date: Wed, 18 Feb 2015 17:34:43 -0800 Subject: [PATCH 189/567] Grammar fix Add missing word "to" for clarity. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 42d996c1..d4b508f0 100644 --- a/README.md +++ b/README.md @@ -1767,7 +1767,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see - Handle and log all routing errors using [`$routeChangeError`](https://docs.angularjs.org/api/ngRoute/service/$route#$routeChangeError). - *Why?*: Provides a consistent way handle all routing errors. + *Why?*: Provides a consistent way to handle all routing errors. *Why?*: Potentially provides a better user experience if a routing error occurs and you route them to a friendly screen with more details or recovery options. From 010b9b4a467642a5f7b5a34ff653f9f1fa0e7b43 Mon Sep 17 00:00:00 2001 From: Vasiliy Mazhekin Date: Sat, 21 Feb 2015 12:36:54 +0200 Subject: [PATCH 190/567] small link fix (to webstorm snippets) --- i18n/ru-RU.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/i18n/ru-RU.md b/i18n/ru-RU.md index 4a779654..e2d068b8 100644 --- a/i18n/ru-RU.md +++ b/i18n/ru-RU.md @@ -2647,7 +2647,7 @@ - AngularJS сниппеты и шаблоны файлов, которые соблюдают приведенные здесь стили и руководства. Вы можете импортировать их в свои настройки WebStorm: - - Скачайте [WebStorm AngularJS шаблоны файлов и сниппетов](assets/webstorm-angular-file-template.settings.jar?raw=true) + - Скачайте [WebStorm AngularJS шаблоны файлов и сниппетов](../assets/webstorm-angular-file-template.settings.jar?raw=true) - Откройте WebStorm и перейдите в меню `File` - Выберите пункт меню `Import Settings` - Выберите файл и нажмите `OK` From c5de451bbf00b5978f20768135df6b42ff19646c Mon Sep 17 00:00:00 2001 From: noritamago Date: Fri, 30 Jan 2015 22:11:10 +0900 Subject: [PATCH 191/567] add i18n/ja-JP.md --- i18n/ja-JP.md | 2826 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 2826 insertions(+) create mode 100644 i18n/ja-JP.md diff --git a/i18n/ja-JP.md b/i18n/ja-JP.md new file mode 100644 index 00000000..647ddd6a --- /dev/null +++ b/i18n/ja-JP.md @@ -0,0 +1,2826 @@ +# AngularJS スタイルガイド + +*[@john_papa](//twitter.com/john_papa)によるチームのための頑固なAngularJSスタイルガイド* + +もしあなたがAngularJSのシンタックス、規約、そしてアプリケーション構成のための頑固なスタイルガイドを探しているなら、どうぞいらっしゃい!本スタイルは、[AngularJS](//angularjs.org)を用いた私の開発経験やプレゼンテーション、[Pluralsight training courses](http://pluralsight.com/training/Authors/Details/john-papa) 、そしてチームでの作業に基づいたものです。 + +このスタイルガイドの目的は、私が実践している規約だけでなく、私がそれを行う理由を示すことによって、AngularJSアプリケーションを構築する手引きとなることです。 + +>もしあなたがこのガイドを気に入ったのなら、Pluralsightにある [AngularJS Patterns: Clean Code](http://jpapa.me/ngclean) の私のコースもチェックして下さい。 + +## Community Awesomeness and Credit +あなたは決して1人でありません!AngularJSのコミュニティは、自身の経験を共有することに情熱的な素晴らしい集団です。実際、友人でありAngularJSのエキスパートでもある Todd Motto と私は、共同で多くのスタイルや規約をまとめました。一部意見が分かれましたが、概ね合意できるものでした。彼のアプローチと本スタイルとの比較のため、是非 [Todd's guidelines](https://github.com/toddmotto/angularjs-styleguide) をチェックすることをお勧めします。 + +ここで紹介する多くのスタイルは、数多くのペアプログラミングのセッション [Ward Bell](http://twitter.com/wardbell) および私自身が既に持っていたアイデアによるものです。いつも意見が一致した訳ではないですが、友人のWardはこのガイドの最終的な発展に大きく貢献してくれました。 + +## See the Styles in a Sample App +このガイドは"何を"、"なぜ"、"どのように"行えば良いかという説明をしますが、合わせて実践的に見ていくことが理解に役立つはずです。本ガイドは、スタイルやパターンに沿ったサンプルアプリケーションを [`modular`のディレクトリ](https://github.com/johnpapa/ng-demos) に用意しています。ここから自由に取得しcloneやforkをしてもらって構いません。また [readmeに実行のためのインストラクション](https://github.com/johnpapa/ng-demos/tree/master/modular) もあります。 + +## Translations +[Translations of this Angular style guide](https://github.com/johnpapa/angularjs-styleguide/tree/master/i18n) がコミュニティによってメンテナンスされており、そこで翻訳を参照することができます。 + +## Table of Contents + + 1. [Single Responsibility](#single-responsibility) + 1. [IIFE](#iife) + 1. [Modules](#modules) + 1. [Controllers](#controllers) + 1. [Services](#services) + 1. [Factories](#factories) + 1. [Data Services](#data-services) + 1. [Directives](#directives) + 1. [Resolving Promises for a Controller](#resolving-promises-for-a-controller) + 1. [Manual Annotating for Dependency Injection](#manual-annotating-for-dependency-injection) + 1. [Minification and Annotation](#minification-and-annotation) + 1. [Exception Handling](#exception-handling) + 1. [Naming](#naming) + 1. [Application Structure LIFT Principle](#application-structure-lift-principle) + 1. [Application Structure](#application-structure) + 1. [Modularity](#modularity) + 1. [Startup Logic](#startup-logic) + 1. [Angular $ Wrapper Services](#angular--wrapper-services) + 1. [Testing](#testing) + 1. [Animations](#animations) + 1. [Comments](#comments) + 1. [JSHint](#js-hint) + 1. [Constants](#constants) + 1. [File Templates and Snippets](#file-templates-and-snippets) + 1. [Yeoman Generator](#yeoman-generator) + 1. [Routing](#routing) + 1. [Task Automation](#task-automation) + 1. [AngularJS Docs](#angularjs-docs) + 1. [Contributing](#contributing) + 1. [License](#license) + +## Single Responsibility + +### Rule of 1 +###### [Style [Y001](#style-y001)] + + - ファイル毎に一つのコンポーネントを定義して下さい。 + + 次の例は`app`モジュールとその依存、コントローラの定義とファクトリーの定義の全てが同じファイルに定義されています。 + + ```javascript + /* avoid */ + angular + .module('app', ['ngRoute']) + .controller('SomeController', SomeController) + .factory('someFactory', someFactory); + + function SomeController() { } + + function someFactory() { } + ``` + + コンポーネント単位でファイルに分割します。 + + ```javascript + /* recommended */ + + // app.module.js + angular + .module('app', ['ngRoute']); + ``` + + ```javascript + /* recommended */ + + // someController.js + angular + .module('app') + .controller('SomeController', SomeController); + + function SomeController() { } + ``` + + ```javascript + /* recommended */ + + // someFactory.js + angular + .module('app') + .factory('someFactory', someFactory); + + function someFactory() { } + ``` + +**[Back to top](#table-of-contents)** + +## IIFE +### JavaScript Closures +###### [Style [Y010](#style-y010)] + + - AngularJSのコンポーネントを即時関数式(Immediately Invoked Function Expression:IIFE)で包んで下さい。 + + *なぜ ?*: IIFEを用いると変数はグローバルスコープになりません。それにより、変数がグローバルスコープの中で期待以上に長く生存してしまうことを防ぐことがでます。また変数同士の衝突も避けることができます。 + + *なぜ ?*: コードをMinifyして一つのファイルにしてプロダクションのサーバーにデプロイするときに、変数の衝突や多数のグローバル変数の存在が問題を起こすかもしれません。IIFEはファイル毎にスコープを持つため、これらの問題を防ぐことができます。 + + ```javascript + /* avoid */ + // logger.js + angular + .module('app') + .factory('logger', logger); + + // logger function is added as a global variable + function logger() { } + + // storage.js + angular + .module('app') + .factory('storage', storage); + + // storage function is added as a global variable + function storage() { } + ``` + + ```javascript + /** + * recommended + * + * no globals are left behind + */ + + // logger.js + (function() { + 'use strict'; + + angular + .module('app') + .factory('logger', logger); + + function logger() { } + })(); + + // storage.js + (function() { + 'use strict'; + + angular + .module('app') + .factory('storage', storage); + + function storage() { } + })(); + ``` + + - Note: 簡潔にするため, 以下に続くコードの例ではIIFEのシンタックスを省略させて下さい。 + + - Note: テストコードは正規表現や単体テスト向けに有効なヘルバー関数のようになプライベートなメンバにしばしばアクセスしますが、IIFEはそのアクセスへの妨げとなります。しかしながら、アクセス可能なメンバを通してテストをすることや独立したコンポーネント経由でこれらを公開してしまうことでテストが可能になります。例えば、ヘルバー関数、正規表現、もしくは定数をAngularJSのファクトリや定数として用意してしまう方法があります。 + +**[Back to top](#table-of-contents)** + +## Modules + +### Avoid Naming Collisions +###### [Style [Y020](#style-y020)] + + - サブモジュールにセパレータを用いたユニークな命名規則を用いて下さい。 + + *なぜ ?*: ユニークな名前は衝突を防ぐことができます。セパレータはモジュールやそのサブモジュールの階層を定義するのに役立ちます。例えば、`app` はルートとなるモジュールであり、`app.dashboard` または `app.users` は `app` と依存のあるモジュールかもしれません。 + +### Definitions (aka Setters) +###### [Style [Y021](#style-y021)] + + - セッターを用いて変数を使うことなくモジュールを定義して下さい。 + + *なぜ ?*: 1ファイル1コンポーネントの原則下では、モジュールの宣言で変数が必要となるケースは非常に稀です。 + + ```javascript + /* avoid */ + var app = angular.module('app', [ + 'ngAnimate', + 'ngRoute', + 'app.shared', + 'app.dashboard' + ]); + ``` + + 代わりに下記のようなシンプルなセッターのシンタックスを用いて下さい。 + + ```javascript + /* recommended */ + angular + .module('app', [ + 'ngAnimate', + 'ngRoute', + 'app.shared', + 'app.dashboard' + ]); + ``` + +### Getters +###### [Style [Y022](#style-y022)] + + - モジュールを用いるときは変数を使うことを避け、代わりにゲッターを使ったチェーンを用いて下さい。 + + *なぜ ?*: 可読性の高いコードとなり変数の衝突やリークを防ぐことができます。 + + ```javascript + /* avoid */ + var app = angular.module('app'); + app.controller('SomeController', SomeController); + + function SomeController() { } + ``` + + ```javascript + /* recommended */ + angular + .module('app') + .controller('SomeController', SomeController); + + function SomeController() { } + ``` + +### Setting vs Getting +###### [Style [Y023](#style-y023)] + + - 一度だけsetして、その他のインスタンスでは全てgetして下さい。 + + *なぜ ?*: モジュールは一度だけ生成され、それ以降は取得のみが行われるべきです。 + + - モジュールのsetには`angular.module('app', []);` を用いる。 + - モジュールのgetには `angular.module('app');` を用いる。 + +### Named vs Anonymous Functions +###### [Style [Y024](#style-y024)] + + - コールバックとして、無名関数ではなく有名関数を渡して下さい。 + + *なぜ ?*: 可読性の高いコードとなりデバッグが容易となります。またネスト化されたコールバックの量を減らせます。 + + ```javascript + /* avoid */ + angular + .module('app') + .controller('Dashboard', function() { }) + .factory('logger', function() { }); + ``` + + ```javascript + /* recommended */ + + // dashboard.js + angular + .module('app') + .controller('Dashboard', Dashboard); + + function Dashboard() { } + ``` + + ```javascript + // logger.js + angular + .module('app') + .factory('logger', logger); + + function logger() { } + ``` + +**[Back to top](#table-of-contents)** + +## Controllers + +### controllerAs View Syntax +###### [Style [Y030](#style-y030)] + + - `典型的な$scopeを使ったcontroller`のシンタックスよりも、[`controllerAs`](http://www.johnpapa.net/do-you-like-your-angular-controllers-with-or-without-sugar/) を用いて下さい。 + + *なぜ ?*: 全く新規にControllersが生成されると、 単一の新しいインスタンスが生成されます。`controllerAs` のシンタックスは、`典型的な$scopeを使ったcontroller`のシンタックスよりも、JavaScriptのコンストラクタにより近いものとなります。 + + *なぜ ?*: ビューの中で"ドット."によるバインディングが容易となり、(例えば、`name` の代わりに `customer.name` となることで)様々な状況に対応可能となり可読性が高まります。また、"ドット."を使わない場合に起こりうる参照の問題を避けることができます。 + + *なぜ ?*: ネスト化されたコントローラを使ったビューの中で`$parent` の呼び出しを避けるのに役立ちます。 + + ```html + +
+ {{ name }} +
+ ``` + + ```html + +
+ {{ customer.name }} +
+ ``` + +### controllerAs Controller Syntax +###### [Style [Y031](#style-y031)] + + - `典型的な$scopeを用いたコントローラ`のシンタックスよりも、`controllerAs`のシンタックスを用いて下さい。 + + - `controllerAs`のシンタックスを用い、$scopeにバインドされるコントローラの内部で`this`を用いて下さい。 + + *なぜ ?*: `controllerAs`は、`$scope`の糖衣構文(シンタックスシュガー)となるので、`$scope`が引き続きビューにバインドされます。そのため`$scope`のメソッドも利用することができます。 + + *なぜ ?*: コントローラ内部で`$scope`のメソッドを利用したいときに、それを自体を避けた方が良いかもしくはファクトリに移動した方が良いことがあります。そのようなときに、コントローラの中に押し込めてしまいたい誘惑を遠ざけるのに役立ちます。ファクトリの中で$scopeを使うことや必要なときに限ってコントローラの中で`$scope`を用いることを検討して下さい。 例えば、[`$emit`](https://docs.angularjs.org/api/ng/type/$rootScope.Scope#$emit) や [`$broadcast`](https://docs.angularjs.org/api/ng/type/$rootScope.Scope#$broadcast) もしくは [`$on`](https://docs.angularjs.org/api/ng/type/$rootScope.Scope#$on) を使ってイベントのpublishとsubscribeを行うときは、その実装をファクトリに移動するかまたはコントローラから呼び出すといった形を検討して下さい。 + + ```javascript + /* avoid */ + function Customer($scope) { + $scope.name = {}; + $scope.sendMessage = function() { }; + } + ``` + + ```javascript + /* recommended - but see next section */ + function Customer() { + this.name = {}; + this.sendMessage = function() { }; + } + ``` + +### controllerAs with vm +###### [Style [Y032](#style-y032)] + + - `controllerAs` シンタックスを用いるときは、`this`をキャプチャした変数を用いて下さい。ビューモデルを表す`vm`のような一貫性のある名前を選んで下さい。 + + *なぜ ?*: `this` キーワードはコンテキストに応じて変化するので、コントローラの関数の中で使われるときにはコンテキストが変更されるかもしれません。`this`のコンテクストをキャプチャすることで、このような問題を避けることができます。 + + ```javascript + /* avoid */ + function Customer() { + this.name = {}; + this.sendMessage = function() { }; + } + ``` + + ```javascript + /* recommended */ + function Customer() { + var vm = this; + vm.name = {}; + vm.sendMessage = function() { }; + } + ``` + + Note: 下記のコメントをコードの上部に入れることで [jshint](http://www.jshint.com/) のwarningsを避けることができます。 しかし関数がアッパーケースの場合には不要です。規約的にはそれはコンストラクタであり、Angularではコントローラに当たります。 + + ```javascript + /* jshint validthis: true */ + var vm = this; + ``` + + Note: `controller as`を用いたコントローラの中で watch を作成したときは、次のシンタックスで `vm.*` のメンバを watch することができます。(digestのサイクルに追加の負荷がかかることに注意してwatchを作成します。) + + ```html + + ``` + + ```javascript + function SomeController($scope, $log) { + var vm = this; + vm.title = 'Some Title'; + + $scope.$watch('vm.title', function(current, original) { + $log.info('vm.title was %s', original); + $log.info('vm.title is now %s', current); + }); + } + ``` + +### Bindable Members Up Top +###### [Style [Y033](#style-y033)] + + - バインドするメンバをコントローラの先頭でアルファベット順に配置し、コントローラのコードの中に分散させないで下さい。 + + *なぜ ?*: バインドするメンバを先頭に書くことで可読性が上がり、コントローラのどのメンバがバインドされ、ビューの中で使われるのかが即座に特定できます。 + + *なぜ ?*: インラインで無名関数をセットするのは容易ですが、一行以上の関数の場合は可読性が下がります。バインドするメンバの下に関数を定義し(関数は巻き上げられます)、実装の詳細は下へ移動します。そうすることで、バインドするメンバを先頭に置いたまま可読性を上げることができるでしょう。 + + ```javascript + /* avoid */ + function Sessions() { + var vm = this; + + vm.gotoSession = function() { + /* ... */ + }; + vm.refresh = function() { + /* ... */ + }; + vm.search = function() { + /* ... */ + }; + vm.sessions = []; + vm.title = 'Sessions'; + ``` + + ```javascript + /* recommended */ + function Sessions() { + var vm = this; + + vm.gotoSession = gotoSession; + vm.refresh = refresh; + vm.search = search; + vm.sessions = []; + vm.title = 'Sessions'; + + //////////// + + function gotoSession() { + /* */ + } + + function refresh() { + /* */ + } + + function search() { + /* */ + } + ``` + + ![Controller Using "Above the Fold"](https://raw.githubusercontent.com/johnpapa/angularjs-styleguide/master/assets/above-the-fold-1.png) + + Note: もし関数がワンライナーであれば、可読性に影響が無い限り上に置いたままにすることを検討して下さい。 + + ```javascript + /* avoid */ + function Sessions(data) { + var vm = this; + + vm.gotoSession = gotoSession; + vm.refresh = function() { + /** + * lines + * of + * code + * affects + * readability + */ + }; + vm.search = search; + vm.sessions = []; + vm.title = 'Sessions'; + ``` + + ```javascript + /* recommended */ + function Sessions(dataservice) { + var vm = this; + + vm.gotoSession = gotoSession; + vm.refresh = dataservice.refresh; // 1 liner is OK + vm.search = search; + vm.sessions = []; + vm.title = 'Sessions'; + ``` + +### Function Declarations to Hide Implementation Details +###### [Style [Y034](#style-y034)] + + - 実装の詳細を隠すために関数宣言を用いて下さい。またバインドされるメンバを先頭に置いて下さい。コントローラの中で関数をバインドするときは、その関数がファイルの後方に現れる関数宣言を指すようにします。これは、「Bindable Members Up Top」のセクションと直接対応しています。 詳細は[このポスト](http://www.johnpapa.net/angular-function-declarations-function-expressions-and-readable-code) を参照して下さい。 + + *なぜ ?*: バインドするメンバを先頭に書くことで可読性が上がり、コントローラのどのメンバがバインドされ、ビューの中で使われるのかが即座に特定できます(上記と同じ)。 + + *なぜ ?*: 関数の実装の詳細をファイルの後方に置くことでviewから複雑さを排除し、重要なものがファイルの先頭で見えるようになります。 + + *なぜ ?*: 関数宣言が巻き上げられるので(関数式でありがちな)関数を宣言する前に利用してしまう懸念がありません。 + + *なぜ ?*: `var b` の前に`var a` を移動するという関数宣言が`a` が `b` に依存しているからといってコードが壊れてしまう心配する必要は決してありません。 + + *なぜ ?*: 関数式では順番がクリティカルです。 + + ```javascript + /** + * avoid + * Using function expressions. + */ + function Avengers(dataservice, logger) { + var vm = this; + vm.avengers = []; + vm.title = 'Avengers'; + + var activate = function() { + return getAvengers().then(function() { + logger.info('Activated Avengers View'); + }); + } + + var getAvengers = function() { + return dataservice.getAvengers().then(function(data) { + vm.avengers = data; + return vm.avengers; + }); + } + + vm.getAvengers = getAvengers; + + activate(); + } + ``` + + 重要な事が続く例に散りばめられていることに着目して下さい。下記の例では、重要な物が先頭にあるのが分かります。例えば、`vm.avengers` や `vm.title` がコントローラにバインドされています。そして実装の詳細がその下にあります。これにより可読性が上がっています。 + + ```javascript + /* + * recommend + * Using function declarations + * and bindable members up top. + */ + function Avengers(dataservice, logger) { + var vm = this; + vm.avengers = []; + vm.getAvengers = getAvengers; + vm.title = 'Avengers'; + + activate(); + + function activate() { + return getAvengers().then(function() { + logger.info('Activated Avengers View'); + }); + } + + function getAvengers() { + return dataservice.getAvengers().then(function(data) { + vm.avengers = data; + return vm.avengers; + }); + } + } + ``` + +### Defer Controller Logic +###### [Style [Y035](#style-y035)] + + - サービスやファクトリに委譲することで、コントローラの中のロジックを遅延させて下さい。 + + *なぜ ?*: ロジックがサービス内に配置されて関数経由で利用可能になれば、複数のコントローラによって再利用されるかもしれません。 + + *なぜ ?*: 単体テスト上でサービス内のロジックは簡単に分離できます。そのためコントローラの呼び出しロジックを容易にモック化がすることができます。 + + *なぜ ?*: 依存性を取り除きコントローラから実装の詳細を隠すことができます。 + + ```javascript + + /* avoid */ + function Order($http, $q, config, userInfo) { + var vm = this; + vm.checkCredit = checkCredit; + vm.isCreditOk; + vm.total = 0; + + function checkCredit() { + var settings = {}; + // Get the credit service base URL from config + // Set credit service required headers + // Prepare URL query string or data object with request data + // Add user-identifying info so service gets the right credit limit for this user. + // Use JSONP for this browser if it doesn't support CORS + return $http.get(settings) + .then(function(data) { + // Unpack JSON data in the response object + // to find maxRemainingAmount + vm.isCreditOk = vm.total <= maxRemainingAmount + }) + .catch(function(error) { + // Interpret error + // Cope w/ timeout? retry? try alternate service? + // Re-reject with appropriate error for a user to see + }); + }; + } + ``` + + ```javascript + /* recommended */ + function Order(creditService) { + var vm = this; + vm.checkCredit = checkCredit; + vm.isCreditOk; + vm.total = 0; + + function checkCredit() { + return creditService.isOrderTotalOk(vm.total) + .then(function(isOk) { vm.isCreditOk = isOk; }) + .catch(showServiceError); + }; + } + ``` + +### Keep Controllers Focused +###### [Style [Y037](#style-y037)] + + - 一つのビューに一つのコントローラを定義し、他のビューで再利用を試みないで下さい。代わりに再利用可能なロジックをファクトリに移動し、コントローラをシンプルにビューにフォーカスさせて下さい。 + + *なぜ ?*: 複数のビューを持つコントローラを再利用することは脆く、大規模なアプリケーション上で安定性を確保するためには、高いカバレッジのエンドツーエンドテストが必須となります。 + +### Assigning Controllers +###### [Style [Y038](#style-y038)] + + - コントローラは必ずビューとペアとなる必要があります。どちらかのコンポーネントが他のコントローラやビューによって最利用可能であるときは、ルーティングに沿ってコントローラを定義して下さい。 + + Note: もしビューがルーティング以外の別の方法でロードされているなら、`ng-controller="Avengers as vm"` のシンタックスを利用して下さい。 + + *なぜ ?*: ルーティングによりコントローラのペアリングを行うことで、ルーティングによって異なるコントローラとビューのペアを呼び出すことが出来ます。コントローラが[`ng-controller`](https://docs.angularjs.org/api/ng/directive/ngController)を使ってビューにアサインされたときには、そのビューはいつも同じコントローラにアサインされます。 + + ```javascript + /* avoid - when using with a route and dynamic pairing is desired */ + + // route-config.js + angular + .module('app') + .config(config); + + function config($routeProvider) { + $routeProvider + .when('/avengers', { + templateUrl: 'avengers.html' + }); + } + ``` + + ```html + +
+
+ ``` + + ```javascript + /* recommended */ + + // route-config.js + angular + .module('app') + .config(config); + + function config($routeProvider) { + $routeProvider + .when('/avengers', { + templateUrl: 'avengers.html', + controller: 'Avengers', + controllerAs: 'vm' + }); + } + ``` + + ```html + +
+
+ ``` + +**[Back to top](#table-of-contents)** + +## Services + +### Singletons +###### [Style [Y040](#style-y040)] + + - サービスは`new`キーワードでインスタンス化されます。パブリックメソッドや変数には`this`を使って下さい。これらはファクトリも同様ですが、一貫性のためにはサービスの代わりにファクトリを用いて下さい。 + + Note: [全てのAngularJSのサービスはシングルトンです](https://docs.angularjs.org/guide/services)。 これはつまり、作成されたサービスはインジェクター毎に単一インスタンスしか存在しないことを意味しています。 + + ```javascript + // service + angular + .module('app') + .service('logger', logger); + + function logger() { + this.logError = function(msg) { + /* */ + }; + } + ``` + + ```javascript + // factory + angular + .module('app') + .factory('logger', logger); + + function logger() { + return { + logError: function(msg) { + /* */ + } + }; + } + ``` + +**[Back to top](#table-of-contents)** + +## Factories + +### Single Responsibility +###### [Style [Y050](#style-y050)] + + - ファクトリは[単一責任](http://en.wikipedia.org/wiki/Single_responsibility_principle)であるべきであり、そのコンテキストに応じてカプセル化されます。ファクトリが一つの目的を超えて利用され始めた場合は、新しいファクトリが作成されるべきです。 + +### Singletons +###### [Style [Y051](#style-y051)] + + - ファクトリはシングルトンであり、そのサービスのメンバを含むオブジェクトを返して下さい。 + + Note: [全てのAngularJSのサービスはシングルトンです](https://docs.angularjs.org/guide/services)。 + +### Accessible Members Up Top +###### [Style [Y052](#style-y052)] + + - 呼び出し可能なサービスのメンバ(そのインターフェイス)を先頭に公開します。このテクニックは [Revealing Module Pattern](http://addyosmani.com/resources/essentialjsdesignpatterns/book/#revealingmodulepatternjavascript) に由来しています。 + + *なぜ ?*: 呼び出し可能なメンバを先頭に置くことは可読性に優れ、どのサービスのメンバが呼び出し可能で単体テストされる(モックされる)べきなのかを即座に特定するのに役立ちます。 + + *なぜ ?*: これは何が公開されているかを見るためにスクロールが必要なるほどファイルが長い場合に特に有効です。 + + *なぜ ?*: セッターの関数では簡単ですが、関数宣言が一行以上のコードからなる場合には可読性が下がりスクロールが必要となります。サービスからの戻り値を用いて呼び出し可能なインターフェイスの定義をすることで、実装の詳細を下に移動できます。また、インターフェイスの定義が先頭に置かれることで、可読性を上げることができます。 + ```javascript + /* avoid */ + function dataService() { + var someValue = ''; + function save() { + /* */ + }; + function validate() { + /* */ + }; + + return { + save: save, + someValue: someValue, + validate: validate + }; + } + ``` + + ```javascript + /* recommended */ + function dataService() { + var someValue = ''; + var service = { + save: save, + someValue: someValue, + validate: validate + }; + return service; + + //////////// + + function save() { + /* */ + }; + + function validate() { + /* */ + }; + } + ``` + + このバインディングの方法はホストオブジェクト全体で反映されます。このrevealing module パターンを使うことで単独でプリミティブの値を更新することは出来なくなります。 + ![Factories Using "Above the Fold"](https://raw.githubusercontent.com/johnpapa/angularjs-styleguide/master/assets/above-the-fold-2.png) + +### Function Declarations to Hide Implementation Details +###### [Style [Y053](#style-y053)] + + - 実装の詳細を隠すために関数宣言を用いて下さい。ファクトリのアクセス可能なメンバを先頭に置いて下さい。それらのメンバがファイルの後方に現れる関数宣言を指すようにします。詳細は[このポスト](http://www.johnpapa.net/angular-function-declarations-function-expressions-and-readable-code) を参照して下さい。 + + *なぜ ?*: アクセス可能なメンバを先頭に書くことで可読性が上がり、ファクトリの中でどの関数が外部からアクセス可能なのか即座に特定できます。 + + *なぜ ?*: 実装の詳細をファイルの後方に置くことでviewから複雑さを排除し、重要なものがファイルの先頭で見えるようになります。 + + *なぜ ?*: 関数宣言が巻き上げられるので、(関数式であるような)関数を宣言する前に利用してしまう懸念がありません。 + + *なぜ ?*: `var b` の前に`var a` を移動するという関数宣言が、`a` が `b` に依存しているからといってコードが壊れてしまう心配する必要は決してありません。 + + *なぜ ?*: 関数式では順番がクリティカルです。 + + ```javascript + /** + * avoid + * Using function expressions + */ + function dataservice($http, $location, $q, exception, logger) { + var isPrimed = false; + var primePromise; + + var getAvengers = function() { + // implementation details go here + }; + + var getAvengerCount = function() { + // implementation details go here + }; + + var getAvengersCast = function() { + // implementation details go here + }; + + var prime = function() { + // implementation details go here + }; + + var ready = function(nextPromises) { + // implementation details go here + }; + + var service = { + getAvengersCast: getAvengersCast, + getAvengerCount: getAvengerCount, + getAvengers: getAvengers, + ready: ready + }; + + return service; + } + ``` + + ```javascript + /** + * recommended + * Using function declarations + * and accessible members up top. + */ + function dataservice($http, $location, $q, exception, logger) { + var isPrimed = false; + var primePromise; + + var service = { + getAvengersCast: getAvengersCast, + getAvengerCount: getAvengerCount, + getAvengers: getAvengers, + ready: ready + }; + + return service; + + //////////// + + function getAvengers() { + // implementation details go here + } + + function getAvengerCount() { + // implementation details go here + } + + function getAvengersCast() { + // implementation details go here + } + + function prime() { + // implementation details go here + } + + function ready(nextPromises) { + // implementation details go here + } + } + ``` + +**[Back to top](#table-of-contents)** + +## Data Services + +### Separate Data Calls +###### [Style [Y060](#style-y060)] + + - データオペレーションやファクトリとのデータのインタラクションのようなロジックをリファクタリングして下さい。XHRの呼び出し、ローカルストレージ、メモリへの退避などのデータオペレーションを担うデータサービスを作成して下さい。 + + *なぜ ?*: コントローラの責任は、プレゼンテーションとビューのために必要な情報を集めることです。どのようにデータを取得するかは気にせず、ただ単に誰に問い合わせれば良いかを知っているだけです。 データサービスの分割によってどのようにデータを取得するかというロジックをデータサービスに移動し、コントローラをよりシンプルにビューにフォーカスさせて下さい。 + + *なぜ ?*: データサービスを用いるコントローラをテストする際に、(モックまたは本物の)データの呼び出しを容易にテストできます。 + + *なぜ ?*: データサービスの実装は、データリポジトリを取り扱う非常にスペシフィックなコードとなります。 このコードには、ヘッダ、データリポジトリの利用方法、もしくは$httpのような他のサービスを含むでしょう。そのようなロジックをデータサービスへ分割し、他のconsumers (おそらくコントローラ) から実装の詳細を隠すように一つの場所へカプセル化します。そうすることで、実装の変更も容易になります + + ```javascript + /* recommended */ + + // dataservice factory + angular + .module('app.core') + .factory('dataservice', dataservice); + + dataservice.$inject = ['$http', 'logger']; + + function dataservice($http, logger) { + return { + getAvengers: getAvengers + }; + + function getAvengers() { + return $http.get('/api/maa') + .then(getAvengersComplete) + .catch(getAvengersFailed); + + function getAvengersComplete(response) { + return response.data.results; + } + + function getAvengersFailed(error) { + logger.error('XHR Failed for getAvengers.' + error.data); + } + } + } + ``` + + Note: データサービスがコントローラのような consumers から呼び出されますが、下記で示されるように実装はconsumersから隠されます。 + + ```javascript + /* recommended */ + + // controller calling the dataservice factory + angular + .module('app.avengers') + .controller('Avengers', Avengers); + + Avengers.$inject = ['dataservice', 'logger']; + + function Avengers(dataservice, logger) { + var vm = this; + vm.avengers = []; + + activate(); + + function activate() { + return getAvengers().then(function() { + logger.info('Activated Avengers View'); + }); + } + + function getAvengers() { + return dataservice.getAvengers() + .then(function(data) { + vm.avengers = data; + return vm.avengers; + }); + } + } + ``` + +### Return a Promise from Data Calls +###### [Style [Y061](#style-y061)] + + - $httpのようなpromiseを返すデータサービスを呼び出すときは、それを呼び出す関数も同様にpromiseを返して下さい。 + + *なぜ ?*: promiseを一緒にチェーンすることで、データの呼び出しが完了した後にさらなるアクションを行い、そのpromiseをresolveもしくはrejectすることができます。 + + ```javascript + /* recommended */ + + activate(); + + function activate() { + /** + * Step 1 + * Ask the getAvengers function for the + * avenger data and wait for the promise + */ + return getAvengers().then(function() { + /** + * Step 4 + * Perform an action on resolve of final promise + */ + logger.info('Activated Avengers View'); + }); + } + + function getAvengers() { + /** + * Step 2 + * Ask the data service for the data and wait + * for the promise + */ + return dataservice.getAvengers() + .then(function(data) { + /** + * Step 3 + * set the data and resolve the promise + */ + vm.avengers = data; + return vm.avengers; + }); + } + ``` + + **[Back to top](#table-of-contents)** + +## Directives +### Limit 1 Per File +###### [Style [Y070](#style-y070)] + + - ファイル毎に一つのディレクティブを作って下さい。ディレクティブ名でファイル名を付けて下さい。 + + *なぜ ?*: 全てのディレクティブを一つのファイルに押し込めるのは容易ですが、アプリ間、モジュール間、たった一つのモジュールと共有する場合でも抜き出すのは難しくなります。 + + *なぜ ?*: ファイル毎に一つのディレクティブにすることで、メンテナンスが容易になります。 + + ```javascript + /* avoid */ + /* directives.js */ + + angular + .module('app.widgets') + + /* order directive that is specific to the order module */ + .directive('orderCalendarRange', orderCalendarRange) + + /* sales directive that can be used anywhere across the sales app */ + .directive('salesCustomerInfo', salesCustomerInfo) + + /* spinner directive that can be used anywhere across apps */ + .directive('sharedSpinner', sharedSpinner); + + function orderCalendarRange() { + /* implementation details */ + } + + function salesCustomerInfo() { + /* implementation details */ + } + + function sharedSpinner() { + /* implementation details */ + } + ``` + + ```javascript + /* recommended */ + /* calendarRange.directive.js */ + + /** + * @desc order directive that is specific to the order module at a company named Acme + * @example
+ */ + angular + .module('sales.order') + .directive('acmeOrderCalendarRange', orderCalendarRange); + + function orderCalendarRange() { + /* implementation details */ + } + ``` + + ```javascript + /* recommended */ + /* customerInfo.directive.js */ + + /** + * @desc spinner directive that can be used anywhere across the sales app at a company named Acme + * @example
+ */ + angular + .module('sales.widgets') + .directive('acmeSalesCustomerInfo', salesCustomerInfo); + + function salesCustomerInfo() { + /* implementation details */ + } + ``` + + ```javascript + /* recommended */ + /* spinner.directive.js */ + + /** + * @desc spinner directive that can be used anywhere across apps at a company named Acme + * @example
+ */ + angular + .module('shared.widgets') + .directive('acmeSharedSpinner', sharedSpinner); + + function sharedSpinner() { + /* implementation details */ + } + ``` + + Note: スコープが狭いか広いかに応じて、ディレクティブには多くの命名オプションがあります。ディレクティブだと理解され、そのファイル名の区別がつきやすく内容が明解であるような名前を一つ選んで下さい。いくつかの例が下記に登場しますが、より推奨される名前に関しては命名のセクションを参照して下さい。 + +### Manipulate DOM in a Directive +###### [Style [Y072](#style-y072)] + + - DOMを直接操作する場合にはディレクティブを使って下さい。もしもスタイルをセットするためのCSSや [animation services](https://docs.angularjs.org/api/ngAnimate)、Angularテンプレート、 [`ngShow`](https://docs.angularjs.org/api/ng/directive/ngShow) や [`ngHide`](https://docs.angularjs.org/api/ng/directive/ngHide) といった代替の方法があれば、代わりにそれを用いるのでも良いです。例えば、ディレクティブが単純に表示と非表示を行うものであれば、ngHide/ngShowを使って下さい。 + + *なぜ ?*: DOM操作はテストやデバッグが難しいため、しばしば良いアプローチ(例えば、CSS、アニメーション、テンプレート)があります。 + +### Provide a Unique Directive Prefix +###### [Style [Y073](#style-y073)] + + - 簡潔でユニークで内容をよく表すディレクティブのプリフィックスを付けて下さい。例えば、HTMLで`acme-sales-customer-info`のように宣言されれば、`acmeSalesCustomerInfo`のようになります。 + + *なぜ ?*: ユニークで簡潔なプリフィックスは、ディレクティブのコンテキストと由来を特定します。例えば、`cc-` というプリフィックスは、CodeCamperアプリを示し、`acme-` は Acme companyのためのディレクティブであることを示します。 + + Note: `ng-` のようなAngularJSのdirectivesのためにリザーブされているものは避けて下さい。 名前の衝突を避けるため、[Ionic Framework](http://ionicframework.com/)の`ion-`のように、幅広く利用されているディレクティブを調査して下さい。 + +### Restrict to Elements and Attributes +###### [Style [Y074](#style-y074)] + + - スタンドアロンで成り立つ要素のようなディレクティブを作るときは、restrictプロパティに`E` (カスタム要素) を指定し、必要に応じて `A` (カスタム属性)を指定して下さい。一般的に、スタンドアロンでコントロールできるものであれば `E` が適しています. 一般的なガイドラインとして `EA` は許されますが、スタンドアロンのときは要素として実装される方が好ましく、既存のDOM操作の拡張のためには属性として実装される方が好ましいです。 + + *なぜ ?*: 理にかなっているからです。 + + *なぜ ?*: 私たちはディレクティブをクラスとして使うことを許していますが、もしディレクティブが要素として働いているのであれば、要素の方がより理にかなっていますし、また少なくとも属性としても理にかなうはずです。 + + Note: AngularJS 1.3 +では、EAがデフォルトです。 + + ```html + +
+ ``` + + ```javascript + /* avoid */ + angular + .module('app.widgets') + .directive('myCalendarRange', myCalendarRange); + + function myCalendarRange() { + var directive = { + link: link, + templateUrl: '/template/is/located/here.html', + restrict: 'C' + }; + return directive; + + function link(scope, element, attrs) { + /* */ + } + } + ``` + + ```html + + +
+ ``` + + ```javascript + /* recommended */ + angular + .module('app.widgets') + .directive('myCalendarRange', myCalendarRange); + + function myCalendarRange() { + var directive = { + link: link, + templateUrl: '/template/is/located/here.html', + restrict: 'EA' + }; + return directive; + + function link(scope, element, attrs) { + /* */ + } + } + ``` + +### Directives and ControllerAs +###### [Style [Y075](#style-y075)] + + - ディレクティブが一貫性を保てるように、ビューとコントローラのペアリングで用いられる`controller as`を用いて下さい。 + + *なぜ ?*: 理にかなっていますし、難しくありません。 + + Note: 下記のディレクティブは、controllerAsを用いてlinkやディレクティブのコントローラの中でscopeを使う方法を示しています。全てが一箇所に収まるようにテンプレートをインラインで入れています。 + + Note: 依存性の注入(dependency injection)に関しては、[Manually Identify Dependencies](#manual-annotating-for-dependency-injection)を参照して下さい。 + + Note: ディレクティブのコントローラがディレクティブのクロージャーの外にあることに注意して下さい。この書き方によって注入が`return`の後で到達不能なコードを生成してしまう問題を回避することができます。 + + ```html +
+ ``` + + ```javascript + angular + .module('app') + .directive('myExample', myExample); + + function myExample() { + var directive = { + restrict: 'EA', + templateUrl: 'app/feature/example.directive.html', + scope: { + max: '=' + }, + link: linkFunc, + controller: ExampleController, + controllerAs: 'vm', + bindToController: true // because the scope is isolated + }; + + return directive; + + function linkFunc(scope, el, attr, ctrl) { + console.log('LINK: scope.min = %s *** should be undefined', scope.min); + console.log('LINK: scope.max = %s *** should be undefined', scope.max); + console.log('LINK: scope.vm.min = %s', scope.vm.min); + console.log('LINK: scope.vm.max = %s', scope.vm.max); + } + } + + ExampleController.$inject = ['$scope']; + + function ExampleController($scope) { + // Injecting $scope just for comparison + var vm = this; + + vm.min = 3; + + console.log('CTRL: $scope.vm.min = %s', $scope.vm.min); + console.log('CTRL: $scope.vm.max = %s', $scope.vm.max); + console.log('CTRL: vm.min = %s', vm.min); + console.log('CTRL: vm.max = %s', vm.max); + } + ``` + + ```html + +
hello world
+
max={{vm.max}}
+
min={{vm.min}}
+ ``` + +###### [Style [Y076](#style-y076)] + + - `controller as`シンタックスをディレクティブで用い、外側のscopeをディレクティブのコントローラのscopeにバインドしたいときは `bindToController = true` を使って下さい。 + + *なぜ ?*: 外側のscopeをディレクティブのコントローラのscopeにバインドした方が容易です。 + + Note: `bindToController`はAngular 1.3.0で導入されました。 + + ```html +
+ ``` + + ```javascript + angular + .module('app') + .directive('myExample', myExample); + + function myExample() { + var directive = { + restrict: 'EA', + templateUrl: 'app/feature/example.directive.html', + scope: { + max: '=' + }, + controller: ExampleController, + controllerAs: 'vm', + bindToController: true + }; + + return directive; + } + + function ExampleController() { + var vm = this; + vm.min = 3; + console.log('CTRL: vm.min = %s', vm.min); + console.log('CTRL: vm.max = %s', vm.max); + } + ``` + + ```html + +
hello world
+
max={{vm.max}}
+
min={{vm.min}}
+ ``` + +**[Back to top](#table-of-contents)** + +## Resolving Promises for a Controller + +### Controller Activation Promises +###### [Style [Y080](#style-y080)] + + - `activate`関数でコントローラのスタートアップロジックを解決して下さい。 + + *なぜ ?*: スタートアップロジックをコントローラの中の一貫性の取れた場所へと置くことでテストの場所を特定し、より一貫性のとれたテストを行うことを容易にします。またコントローラ全体にアクティベーションのロジックが分散してしまうのを避けるのにも役立ちます。 + + *なぜ ?*: コントローラの`activate`は、コントローラ/ビューのリフレッシュするためのロジックを再利用するのに便利です。またロジックを一緒にまとめることで、ユーザがビューに早くたどり着けます。`ng-view` や `ui-view`へアニメーションを入れるのも容易となるので、ユーザはキビキビとした動作だと感じます。 + + Note: もしコントローラを使い始める前に条件的にルーティングをキャンセルする必要があるなら、代わりに [route resolve](#style-y081) を用いて下さい。 + + ```javascript + /* avoid */ + function Avengers(dataservice) { + var vm = this; + vm.avengers = []; + vm.title = 'Avengers'; + + dataservice.getAvengers().then(function(data) { + vm.avengers = data; + return vm.avengers; + }); + } + ``` + + ```javascript + /* recommended */ + function Avengers(dataservice) { + var vm = this; + vm.avengers = []; + vm.title = 'Avengers'; + + activate(); + + //////////// + + function activate() { + return dataservice.getAvengers().then(function(data) { + vm.avengers = data; + return vm.avengers; + }); + } + } + ``` + +### Route Resolve Promises +###### [Style [Y081](#style-y081)] + + - コントローラがアクティベイトされる前にpromiseが解決されることに依存しているときは、コントローラのロジックが実行される前に`$routeProvider`の中でそれらの依存が解決されます。もしコントローラがアクティベイトされる前に条件的にルーティングをキャンセルしたい場合は、route resolveを用いて下さい。 + + - ビューへ遷移する前にルーティングのキャンセルを判断したいときは、route resolveを用いて下さい。 + + *なぜ ?*: コントローラが読み込まれる前にデータが必要となるかもしれません。そのデータはカスタムのファクトリや[$http](https://docs.angularjs.org/api/ng/service/$http)から返るpromiseから取得するかもしれません。[route resolve](https://docs.angularjs.org/api/ngRoute/provider/$routeProvider) を使うと、コントローラがロジックを実行する前にpromiseを解決することができるため、 promiseから取得したデータに基づいてアクションを取ることができます。 + + *なぜ ?*: ルーティングとコントローラのactivate関数の後にコードが実行されて、ビューが直ちにロードされます。アクティベイトされたpromiseがresolveされるとデータバインディングがキックされます。ビューが遷移している間(ng-viewやui-viewで)"busy"なアニメーションが表示されます。 + + Note: promiseの後に、ルーティングが行われる前にコードが実行されます。もしそのpromiseがrejectされるとルーティングはキャンセルされます。resolveによって新しいビューはルーティングが解決されるのを待ちます。resolve及びビューの遷移が終わるまで"busy" なアニメーションが表示されます。より早くビューを表示したい場合で、かつビューを表示するかどうかのチェックポイントが不要な場合は、代わりに [controller `activate` technique](#style-y080) を用いることを検討して下さい。 + + ```javascript + /* avoid */ + angular + .module('app') + .controller('Avengers', Avengers); + + function Avengers(movieService) { + var vm = this; + // unresolved + vm.movies; + // resolved asynchronously + movieService.getMovies().then(function(response) { + vm.movies = response.movies; + }); + } + ``` + + ```javascript + /* better */ + + // route-config.js + angular + .module('app') + .config(config); + + function config($routeProvider) { + $routeProvider + .when('/avengers', { + templateUrl: 'avengers.html', + controller: 'Avengers', + controllerAs: 'vm', + resolve: { + moviesPrepService: function(movieService) { + return movieService.getMovies(); + } + } + }); + } + + // avengers.js + angular + .module('app') + .controller('Avengers', Avengers); + + Avengers.$inject = ['moviesPrepService']; + function Avengers(moviesPrepService) { + var vm = this; + vm.movies = moviesPrepService.movies; + } + ``` + + Note: 下記の例はルーティングのresolveが有名関数を指し示しています。そのためデバッグが容易になり依存性の注入が扱いやすくなっています。 + + + ```javascript + /* even better */ + + // route-config.js + angular + .module('app') + .config(config); + + function config($routeProvider) { + $routeProvider + .when('/avengers', { + templateUrl: 'avengers.html', + controller: 'Avengers', + controllerAs: 'vm', + resolve: { + moviesPrepService: moviesPrepService + } + }); + } + + function moviePrepService(movieService) { + return movieService.getMovies(); + } + + // avengers.js + angular + .module('app') + .controller('Avengers', Avengers); + + Avengers.$inject = ['moviesPrepService']; + function Avengers(moviesPrepService) { + var vm = this; + vm.movies = moviesPrepService.movies; + } + ``` + Note: このコード例にある`movieService`への依存は、minificationセーフではありません。どのようにコードをminificationセーフにするかの詳細は[dependency injection](#manual-annotating-for-dependency-injection) と [minification and annotation](#minification-and-annotation)を参照して下さい。 + +**[Back to top](#table-of-contents)** + +## Manual Annotating for Dependency Injection + +### UnSafe from Minification +###### [Style [Y090](#style-y090)] + + - minificationセーフなアプローチを用いずにショートカットで依存を宣言するシンタックスは避けて下さい。 + + *なぜ ?*: コンポーネント(つまり、コントローラやファクトリなど)に対するパラメータはマングル化された変数に変換されます。例えば、`common` や `dataservice`は、`a` もしくは `b` になるかもしれず、AngularJSが見つけられないかもしれません。 + + ```javascript + /* avoid - not minification-safe*/ + angular + .module('app') + .controller('Dashboard', Dashboard); + + function Dashboard(common, dataservice) { + } + ``` + + このコードはMinifyされたときにマングルされた変数が生成され実行エラーになるかもしれません。 + + ```javascript + /* avoid - not minification-safe*/ + angular.module('app').controller('Dashboard', d);function d(a, b) { } + ``` + +### Manually Identify Dependencies +###### [Style [Y091](#style-y091)] + + - AngularJSコンポーネントの依存を手動で特定するために`$inject`を使って下さい。 + + *なぜ ?*: このテクニックは[`ng-annotate`](https://github.com/olov/ng-annotate)で用いられており、そしてそれは自動でminificationセーフな依存を生成することを勧めています。もし`ng-annotate` が注入がすでに行われたことを検出すると再生成をスキップします。 + + *なぜ ?*: このテクニックは、パラメータがマングルされたときにminificationの問題に対して脆弱であることから依存性を守ります。例えば、`common` や `dataservice` が `a` や `b` になるかもしれず、AngularJSが見つけられないかもしれません。 + + *なぜ ?*: 配列で読むのが難しいほと長いリストになる場合には、インラインで依存性を生成することを避けて下さい。さらに依存のリストは配列が文字列の連続からなる一方で、最後の要素がコンポーネントの関数となり紛らわしいです。 + + ```javascript + /* avoid */ + angular + .module('app') + .controller('Dashboard', + ['$location', '$routeParams', 'common', 'dataservice', + function Dashboard($location, $routeParams, common, dataservice) {} + ]); + ``` + + ```javascript + /* avoid */ + angular + .module('app') + .controller('Dashboard', + ['$location', '$routeParams', 'common', 'dataservice', Dashboard]); + + function Dashboard($location, $routeParams, common, dataservice) { + } + ``` + + ```javascript + /* recommended */ + angular + .module('app') + .controller('Dashboard', Dashboard); + + Dashboard.$inject = ['$location', '$routeParams', 'common', 'dataservice']; + + function Dashboard($location, $routeParams, common, dataservice) { + } + ``` + + Note: 関数がreturn文の下にあるとき、$injectが到達可能になるかもしれません(これはディレクティブで起こるかもしれません)。$injectをreturn文の上に移動するか、もしくは交互の配列によって注入するシンタックスを使うことで回避することができます。 + + Note: [`ng-annotate 0.10.0`](https://github.com/olov/ng-annotate) は'$inject'を到達可能なところに移動する機能を導入しました。 + + ```javascript + // inside a directive definition + function outer() { + return { + controller: DashboardPanel, + }; + + DashboardPanel.$inject = ['logger']; // Unreachable + function DashboardPanel(logger) { + } + } + ``` + + ```javascript + // inside a directive definition + function outer() { + DashboardPanel.$inject = ['logger']; // reachable + return { + controller: DashboardPanel, + }; + + function DashboardPanel(logger) { + } + } + ``` + +### Manually Identify Route Resolver Dependencies +###### [Style [Y092](#style-y092)] + + - AngularJSのコンポーネントのroute resolverの依存性を手動で特定するために$injectを使って下さい。 + + *なぜ ?*: このテクニックは、route resolverを無名関数として外に出すことで可読性を上げることができます。 + + *なぜ ?*: `$inject`の文をただ前に置くことによって、resolverがいかなる依存性もminificationセーフにします。 + + ```javascript + /* recommended */ + function config($routeProvider) { + $routeProvider + .when('/avengers', { + templateUrl: 'avengers.html', + controller: 'Avengers', + controllerAs: 'vm', + resolve: { + moviesPrepService: moviePrepService + } + }); + } + + moviePrepService.$inject = ['movieService']; + function moviePrepService(movieService) { + return movieService.getMovies(); + } + ``` + +**[Back to top](#table-of-contents)** + +## Minification and Annotation + +### ng-annotate +###### [Style [Y100](#style-y100)] + + - [Gulp](http://gulpjs.com)や[Grunt](http://gruntjs.com)のために[ng-annotate](//github.com/olov/ng-annotate)を使って下さい。自動の依存性の注入が必要となる関数に`/** @ngInject */`というコメントをいれて下さい。 + + *なぜ ?*: このことはminificationセーフなプラクティスを利用していない依存性からコードを守ります。 + + *なぜ ?*: [`ng-min`](https://github.com/btford/ngmin)は非推奨です。 + + >私は読み書きとデバッグが容易なためGulpの方を好みます。 + + 次のコードはminificationセーフな依存性注入を使っていません。 + + ```javascript + angular + .module('app') + .controller('Avengers', Avengers); + + /* @ngInject */ + function Avengers(storageService, avengerService) { + var vm = this; + vm.heroSearch = ''; + vm.storeHero = storeHero; + + function storeHero() { + var hero = avengerService.find(vm.heroSearch); + storageService.save(hero.name, hero); + } + } + ``` + + 上記のコードにng-annotateを実行すると、次の`$inject`が付与された出力が生成され、その出力はminificationセーフになります。 + + ```javascript + angular + .module('app') + .controller('Avengers', Avengers); + + /* @ngInject */ + function Avengers(storageService, avengerService) { + var vm = this; + vm.heroSearch = ''; + vm.storeHero = storeHero; + + function storeHero() { + var hero = avengerService.find(vm.heroSearch); + storageService.save(hero.name, hero); + } + } + + Avengers.$inject = ['storageService', 'avengerService']; + ``` + + Note: もし`ng-annotate`が注入がすでに行われていることを検出すると(例えば、`@ngInject` が検出されると)、 `$inject`が入ったコ−ドを重複して生成しません。 + + Note: route resolverを用いるときは、resolverの関数の先頭に `/* @ngInject */` に付けることができます。注入された依存性がminificationセーフになるような適切にアノテーションのついたコードを生成します。 + + ```javascript + // Using @ngInject annotations + function config($routeProvider) { + $routeProvider + .when('/avengers', { + templateUrl: 'avengers.html', + controller: 'Avengers', + controllerAs: 'vm', + resolve: { /* @ngInject */ + moviesPrepService: function(movieService) { + return movieService.getMovies(); + } + } + }); + } + ``` + + > Note: AngularJS 1.3から導入された、[`ngApp`](https://docs.angularjs.org/api/ng/directive/ngApp)のディレクティブの`ngStrictDi`パラメータを使って下さい。 現在のinjectorが"strict-di"モードで生成されたとき、アプリケーションが明示的にアノテーションの付いていない関数(これらはminificationセーフではありません)の呼び出しは失敗します。デバッグ情報がログとしてconsoleに出力されるので、問題のあるコードを見つけ出すのに役立ちます。 + `` + +### Use Gulp or Grunt for ng-annotate +###### [Style [Y101](#style-y101)] + + - 自動ビルドのタスクの中で[gulp-ng-annotate](https://www.npmjs.org/package/gulp-ng-annotate) もしくは [grunt-ng-annotate](https://www.npmjs.org/package/grunt-ng-annotate) を使って下さい。依存性を持つどの関数よりも前に`/* @ngInject */` を注入して下さい。 + + *なぜ ?*: ng-annotate は大半の依存性を捕捉しますが、`/* @ngInject */`のシンタックスを使ったヒントが時々必要となリます。 + + 次のコードは、ngAnnotateを使ったgulpタスクの例です。 + + ```javascript + gulp.task('js', ['jshint'], function() { + var source = pkg.paths.js; + return gulp.src(source) + .pipe(sourcemaps.init()) + .pipe(concat('all.min.js', {newLine: ';'})) + // Annotate before uglify so the code get's min'd properly. + .pipe(ngAnnotate({ + // true helps add where @ngInject is not used. It infers. + // Doesn't work with resolve, so we must be explicit there + add: true + })) + .pipe(bytediff.start()) + .pipe(uglify({mangle: true})) + .pipe(bytediff.stop()) + .pipe(sourcemaps.write('./')) + .pipe(gulp.dest(pkg.paths.dev)); + }); + + ``` + +**[Back to top](#table-of-contents)** + +## Exception Handling + +### decorators +###### [Style [Y110](#style-y110)] + + - 例外が発生したときに[`$exceptionHandler`](https://docs.angularjs.org/api/ng/service/$exceptionHandler)サービスを上書きし、カスタムのアクションを実行するために、configの呼び出し時に[`$provide`](https://docs.angularjs.org/api/auto/service/$provide) サービスの[decorator](https://docs.angularjs.org/api/auto/service/$provide#decorator)を使って下さい。 + + *なぜ ?*: 開発時や実行時に捕捉されていないAngularJSの例外をハンドルする一貫した方法を与えます。 + + Note: もう一つのオプションは、decoratorを使う代わりにサービスをオーバーライドすることです。これも有効なオプションですが、もしデフォルトの動作をキープしたい場合または拡張したい場合はdecoratorがお勧めです。 + + ```javascript + /* recommended */ + angular + .module('blocks.exception') + .config(exceptionConfig); + + exceptionConfig.$inject = ['$provide']; + + function exceptionConfig($provide) { + $provide.decorator('$exceptionHandler', extendExceptionHandler); + } + + extendExceptionHandler.$inject = ['$delegate', 'toastr']; + + function extendExceptionHandler($delegate, toastr) { + return function(exception, cause) { + $delegate(exception, cause); + var errorData = { + exception: exception, + cause: cause + }; + /** + * Could add the error to a service's collection, + * add errors to $rootScope, log errors to remote web server, + * or log locally. Or throw hard. It is entirely up to you. + * throw exception; + */ + toastr.error(exception.msg, errorData); + }; + } + ``` + +### Exception Catchers +###### [Style [Y111](#style-y111)] + + - 例外を捕捉し丁寧にハンドルするインターフェイスを公開するファクトリを作って下さい。 + + *なぜ ?*: コードが投げられる可能性のある例外(例えば、XHR呼び出しやpromiseのfailuresなど)を捕捉するため一貫した方法を与えます。 + + Note: 例外のキャッチャーは、例外が発生するかもしれない呼び出しに対して、特定の例外を捕捉しそれに応じて処理をする際に有効です。例えば、リモートのWebサービスからデータを取得するXHRを呼び出すときに、それらのサービスから発生するいかなる例外も捕捉し一意に対応したい場合です。 + + ```javascript + /* recommended */ + angular + .module('blocks.exception') + .factory('exception', exception); + + exception.$inject = ['logger']; + + function exception(logger) { + var service = { + catcher: catcher + }; + return service; + + function catcher(message) { + return function(reason) { + logger.error(message, reason); + }; + } + } + ``` + +### Route Errors +###### [Style [Y112](#style-y112)] + + - [`$routeChangeError`](https://docs.angularjs.org/api/ngRoute/service/$route#$routeChangeError)を使って全てのルーティングのエラーをハンドルしてログにして下さい。 + + *なぜ ?*: 全てのルーティングのエラーをハンドルする一貫した方法を与えます。 + + *なぜ ?*: もしルーティングエラーが発生した際に、詳細な情報もしくはリカバリーのオプションが備わったユーザフレンドリーな画面にルーティングできれば、より良いユーザエクスペリエンスになる可能性があります。 + + ```javascript + /* recommended */ + function handleRoutingErrors() { + /** + * Route cancellation: + * On routing error, go to the dashboard. + * Provide an exit clause if it tries to do it twice. + */ + $rootScope.$on('$routeChangeError', + function(event, current, previous, rejection) { + var destination = (current && (current.title || current.name || current.loadedTemplateUrl)) || + 'unknown target'; + var msg = 'Error routing to ' + destination + '. ' + (rejection.msg || ''); + /** + * Optionally log using a custom service or $log. + * (Don't forget to inject custom service) + */ + logger.warning(msg, [current]); + } + ); + } + ``` + +**[Back to top](#table-of-contents)** + +## Naming + +### Naming Guidelines +###### [Style [Y120](#style-y120)] + + - 全てのコンポーネントに対して、特徴や(オプションで)その型を表すパターンに沿った一貫性のある名前を使って下さい。私のお勧めは、`feature.type.js`です。大半のアセットに対して二つの命名箇所があります。 + * ファイル名 (`avengers.controller.js`) + * Angularに登録するコンポーネント名 (`AvengersController`) + + *なぜ ?*: 命名規則は一目見ただけでコンテンツが見つかるような一貫した方法を与えます。一貫性はプロジェクトにとって極めて重要なことでありチームにとって大切なことです。また会社全体でとても大きな効率性に繋がります。 + + *なぜ ?*: 命名規則はコードをより早く発見し、そしてより簡単に理解する助けになります。 + +### Feature File Names +###### [Style [Y121](#style-y121)] + + - 全てのコンポーネントに対して、特徴や(オプションで)その型を表すパターンに沿った一貫性のある名前を使って下さい。私のお勧めは、`feature.type.js`です。 + + *なぜ ?*: 素早くコンポーネントを特定できる一貫した方法を与えます。 + + *なぜ ?*: 自動タスクためのパターンマッチングが可能となります。 + + ```javascript + /** + * common options + */ + + // Controllers + avengers.js + avengers.controller.js + avengersController.js + + // Services/Factories + logger.js + logger.service.js + loggerService.js + ``` + + ```javascript + /** + * recommended + */ + + // controllers + avengers.controller.js + avengers.controller.spec.js + + // services/factories + logger.service.js + logger.service.spec.js + + // constants + constants.js + + // module definition + avengers.module.js + + // routes + avengers.routes.js + avengers.routes.spec.js + + // configuration + avengers.config.js + + // directives + avenger-profile.directive.js + avenger-profile.directive.spec.js + ``` + + Note: 別の命名規則は `avengers.controller.js` というファイル名から`controller`を取り除いて命名することです。 その他の全ての規則はサフィックスを使い続けるものです。コントローラは最も共通なコンポーネントであり、タイピングの量を減らしながらも依然として特定しやすいままになります。どれか一つを選びチーム内で一つの命名規則に統一することを勧めます。 + + ```javascript + /** + * recommended + */ + // Controllers + avengers.js + avengers.spec.js + ``` + +### Test File Names +###### [Style [Y122](#style-y122)] + + - コンポーネントと同様、テストするコンポーネントにサフィックスとして`spec`を付与した形でテストのスペックを命名して下さい + + *なぜ ?*: コンポーネントを素早く特定する一貫した方法を与えます。 + + *なぜ ?*: [karma](http://karma-runner.github.io/)やその他のテストランナーでパターンマッチングが可能となります。 + + ```javascript + /** + * recommended + */ + avengers.controller.spec.js + logger.service.spec.js + avengers.routes.spec.js + avenger-profile.directive.spec.js + ``` + +### Controller Names +###### [Style [Y123](#style-y123)] + + - 全てのコントローラにそれらの機能から取った一貫した名前を付けて下さい。コントローラのコンストラクタには、アッパーキャメルケースを使って下さい。 + + *なぜ ?*: 素早くコントラーを特定し参照できる一貫した方法を与えます。 + + *なぜ ?*: アッパーキャメルケースはコンストラクタを使ってインスタンスを生成されたオブジェクトを特定する規約的な方法です。 + + ```javascript + /** + * recommended + */ + + // avengers.controller.js + angular + .module + .controller('HeroAvengers', HeroAvengers); + + function HeroAvengers() { } + ``` + +### Controller Name Suffix +###### [Style [Y124](#style-y124)] + + - コントローラに`Controller`という名前を挿入するか、もしくはしないかどちらか一つを選択せよ。 両方を混ぜてはいけません。 + + *なぜ ?*: `Controller`のサフィックスは、広く使われており明らかに直接内容を説明している。 + + *なぜ ?*: サフィックスを省略することは効率的であり、コントローラはサフィックスが無くても簡単に特定が可能です。 + + ```javascript + /** + * recommended: Option 1 + */ + + // avengers.controller.js + angular + .module + .controller('Avengers', Avengers); + + function Avengers() { } + ``` + + ```javascript + /** + * recommended: Option 2 + */ + + // avengers.controller.js + angular + .module + .controller('AvengersController', AvengersController); + + function AvengersController() { } + ``` + +### Factory Names +###### [Style [Y125](#style-y125)] + + - 全てのファクトリに対して、機能に沿った一貫性の取れた名前を用いて下さい。サービスやファクトリ名にはキャメルケースを用いて下さい。 + + *なぜ ?*: 参照するべきファクトリを素早く特定する一貫性の取れた方法を与えます。 + + ```javascript + /** + * recommended + */ + + // logger.service.js + angular + .module + .factory('logger', logger); + + function logger() { } + ``` + +### Directive Component Names +###### [Style [Y126](#style-y126)] + + - 全てのディレクトリにキャメルケースで一貫性を取れた名前を用いて下さい。そのディレクティブが属する範囲を表す短いプリフィックス(例としては会社やプロジェクトのプリフィックス)を用いて下さい。 + + *なぜ ?*: 参照するべきコンポーネントと素早く特定する一貫性の取れた方法を与えます。 + + ```javascript + /** + * recommended + */ + + // avenger-profile.directive.js + angular + .module + .directive('xxAvengerProfile', xxAvengerProfile); + + // usage is + + function xxAvengerProfile() { } + ``` + +### Modules +###### [Style [Y127](#style-y127)] + + - 複数のモジュールがあるとき、メインとなるモジュールのファイルは`app.module.js`と命名し、他に依存のあるモジュールはそれが表す内容に応じて命名して下さい。 例えば、adminのモジュールは`admin.module.js`と命名します。registerされるモジュール名はそれぞれ`app`と`admin`になります。 + + *なぜ ?*: 複数のモジュールからなるアプリまたは大規模なアプリケーションへ拡張される際に一貫性を与えます。 + + *なぜ ?*: 自動化タスクを用いることで、定義されている全てのモジュールを最初にロードし、それから他のAngularのファイルを(bundlingのため)ロードするための簡単な方法を与えます。 + +### Configuration +###### [Style [Y128](#style-y128)] + + - モジュールのコンフィギュレーションをそれぞれのモジュールに沿って命名されたファイルに分離して下さい。メインの`app`のモジュールのコンフィグレーションは`app.config.js`と命名して下さい。(もしくは単純に`config.js`)。 モジュールの名前が`admin.module.js`であれば、そのコンフィグレーションは`admin.config.js`と命名します。 + + *なぜ ?*: モジュールの定義やコンポーネント、アクティブなコードからコンフィグレーションを分離できます。 + + *なぜ ?*: モジュールのコンフィグレーションを設定するための場所を特定できます。 + +### Routes +###### [Style [Y129](#style-y129)] + + - ルーティングのコンフィグレーションをそれぞれのファイルに分離して下さい。例えば、メインのモジュールが`app.route.js`であれば、`admin`のモジュールは、`admin.route.js`になります。例え小さいアプリであっても、私は他コンフィグレーションからルーティングを分離することを好みます。 + +**[Back to top](#table-of-contents)** + +## Application Structure LIFT Principle +### LIFT +###### [Style [Y140](#style-y140)] + + - コードを素早く`L`ocate(配置する)するため、一目見ただけでそのコードを`I`dentify(特定する)ため、できる限り`F`lattestに保ち`、なるべくDRYになるように(`T`ry)アプリケーションを構造化して下さい。アプリケーションの構造はこれらの4つのガイドラインに従うべきです。 + + *なぜ LIFT?*: 一貫性のとれた構造によって十分にスケールしモジュール化され、コードの所在を素早く見つけられることで開発の効率性も上がります。アプリの構造をチェックするもう一つ方法は、次のことを自身に聞いてみることです:ある機能に対して、どのくらい素早く全ての関連ファイルを開き、そして変更できるでしょうか。 + + もし自分の構造が良いと思えなかったら、立ち戻ってこれらのLIFTのガイドラインを見直して下さい。 + + 1. コードを容易に`L`ocatingできること + 2. 一目見ただけでコードを`I`dentifyできること + 3. できる限りコードを`F`latな構造にすること + 4. DRY(Don’t Repeat Yourself)のままになるように(`T`ry) or T-DRY + +### Locate +###### [Style [Y141](#style-y141)] + + - コードの配置を直感的に単純に素早く行えるようにして下さい。 + + *Why?*: これはプロジェクトにとって極めて重要なことです。もしチームが彼らが変更するべきファイルを素早く見つけることができなければ、最大限効率的に働くことができなくなってしまいます。そのようなときは構造を変更する必要があります。ファイル名が分からない、もしくは関連のファイルがわからないようであれば、ファイルを最も直感的で相互に近い位置に置くことができれば、大幅な時間の削減となります。理解しやすいフォルダ構成はそのようなにときに役立ちます。 + + ``` + /bower_components + /client + /app + /avengers + /blocks + /exception + /logger + /core + /dashboard + /data + /layout + /widgets + /content + index.html + .bower.json + ``` + +### Identify +###### [Style [Y142](#style-y142)] + + - ファイルを参照したときに、そのファイルが何を含み何をしようとしているか即座に理解できるべきです。 + + *なぜ ?*: コードを探し中身をかいつまんで見ている際に費やす時間が少なくなることでより効率的になります。 これはより長いファイル名を求めているのであれば、そうするべきということです。内容をよく表すファイル名を付けて、ファイルの中のコンテンツはたった一つのコンポーネントのみにします。複数のコントローラやサービス、またはそれらが一つのファイルの中で混在することを避けて下さい。 さもなければ、これらはファイル毎に一つのコンポーネントであるというルールを逸脱してしまいます。ルールを守ることで、全てが相互に関係しているような非常に小さい機能の集まりがあったときも、依然としてファイルを簡単に特定することができます。 + +### Flat +###### [Style [Y143](#style-y143)] + + - できる限りフォルダ構成をフラットに保って下さい。7個以上のファイルがある場合は、分割を検討し始めて下さい。 + + *なぜ ?*: ファイルを見つけるために7階層以上のファイルを探したい人はいません。 Webサイトのメニューについて考えると、2つ以上に深い階層には再考の余地があります。 1つのフォルダの構成では、厳格な数のルールは無いですが、フォルダが7-10のファイルから成るときには、サブフォルダを作るときかもしれません。自分が快適であるレベルに基づいて決めれば良いです。 新しいフォルダを作成する明らかな(残りのLIFTに役立つための)レベルまではフラットな構造を使って下さい。 + +### T-DRY (Try to Stick to DRY) +###### [Style [Y144](#style-y144)] + + - DRYにして下さい。だがそれに捉われすぎて可読性を犠牲にしてはいけません。 + + *なぜ ?*: DRYであることは大切ですが、決定的に重要なことではありません。もしLIFTの中の何か一方を犠牲にするのであれば、それを私はT-DRYと呼んでいます。一つのビューをsession-view.htmlとタイプしたくはありません。なぜならそれは明らかにビューだからです。 明らかにではない場合もしくは規則による場合、そのように命名します。 + +**[Back to top](#table-of-contents)** + +## Application Structure + +### Overall Guidelines +###### [Style [Y150](#style-y150)] + + - 実装に関する短期的な視点と長期的なビジョンを持って下さい。言い換えると、小さく始めるが、アプリがどの方向に向かっているかををしっかりと把握することです。 全てのアプリケーションのコードは`app`という名前のルートのディレクトリ配下に置いて下さい。どのコンテンツもファイル毎に一機能として下さい。コントローラ、サービス、モジュール、ビューのそれぞれを独立したファイルにして下さい。全てのサードパーティのベンダーのスクリプトは別のルートのディレクトリの下に置き、`app`ディレクトリ配下には置かないで下さい。私はそのスクリプトを書いていないですし、それが自分のアプリを散らかしてしまうことも望んでいません(`bower_components`, `scripts`, `lib`)。 + + Note: この構造の詳細や理由などは[this original post on application structure](http://www.johnpapa.net/angular-app-structuring-guidelines/)を参照して下さい。 + +### Layout +###### [Style [Y151](#style-y151)] + + - アプリケーションの全体のレイアウトを定義するコンポーネントは、`layout`というフォルダの中に置いて下さい。このディレクトリにはビューのテンプレートやナビゲーション、メニュー、コンテンツエリア、その他の場所でコンテナとして振舞うコントローラを含むかもしれません。 + + *なぜ ?*: 全てのレイアウトを一箇所に配置することで、アプリケーション全体で再利用可能になります。 + +### Folders-by-Feature Structure +###### [Style [Y152](#style-y152)] + + - 特徴を表す名前でフォルダを作成して下さい。フォルダが7つ以上のファイルを含むように肥大化してきた時、それらのためにフォルダを作ることを検討して下さい。人により閾値は違うかもしれないので必要に応じて調整して下さい。 + + *なぜ ?*: ディベロッパーがコードを配置し、一目見ただけでそれぞれのファイルが何をしているかが理解できます。またできる限りフラットな構造を保つことで、重複も無駄の無い名前にすることができます。 + + *なぜ ?*: LIFTのガイドラインが全てカバーされます。 + + *なぜ ?*: コンテンツを整理しLIFTのガイドラインに沿って維持し続けることで、アプリが散らかってしまうことを避けることができます。 + + *なぜ ?*: 大量のファイル(10個以上)があるときに、それらを一貫性の取れたフォルダに配置することは簡単ですが、フラットな構造で配置するのは難しいでしょう。 + + ```javascript + /** + * recommended + */ + + app/ + app.module.js + app.config.js + app.routes.js + components/ + calendar.directive.js + calendar.directive.html + user-profile.directive.js + user-profile.directive.html + layout/ + shell.html + shell.controller.js + topnav.html + topnav.controller.js + people/ + attendees.html + attendees.controller.js + speakers.html + speakers.controller.js + speaker-detail.html + speaker-detail.controller.js + services/ + data.service.js + localstorage.service.js + logger.service.js + spinner.service.js + sessions/ + sessions.html + sessions.controller.js + session-detail.html + session-detail.controller.js + ``` + + ![Sample App Structure](https://raw.githubusercontent.com/johnpapa/angularjs-styleguide/master/assets/modularity-2.png) + + Note: folders-by-typeを使って構造化をしてはいけません。一つの機能が、5、10、25以上のビューやコントローラ(また他の機能)からなるときにアプリが肥大化してきます。そのとき複数のフォルダに移動する必要がありますが、ファイルを配置するのはfolder-by-featureよりも難しいでしょう。 + + ```javascript + /* + * avoid + * Alternative folders-by-type. + * I recommend "folders-by-feature", instead. + */ + + app/ + app.module.js + app.config.js + app.routes.js + controllers/ + attendees.js + session-detail.js + sessions.js + shell.js + speakers.js + speaker-detail.js + topnav.js + directives/ + calendar.directive.js + calendar.directive.html + user-profile.directive.js + user-profile.directive.html + services/ + dataservice.j + localstorage.js + logger.js + spinner.js + views/ + attendees.html + session-detail.html + sessions.html + shell.html + speakers.html + speaker-detail.html + topnav.html + ``` + +**[Back to top](#table-of-contents)** + +## Modularity + +### Many Small, Self Contained Modules +###### [Style [Y160](#style-y160)] + + - 一つの責任をカプセル化した小さいモジュールを作って下さい。 + + *なぜ ?*: モジュール化されたアプリケーションは、開発チームがアプリケーションの垂直なスライスを簡単に組み立てインクリメンタルにロールアウトすることができます。 つまり開発した新しい機能をプラグイン化することができます。 + +### Create an App Module +###### [Style [Y161](#style-y161)] + + - 全てのモジュールと機能を統合することを担うアプリケーションのルートなるモジュールを作って下さい。これにアプリケーション名をつけて下さい。 + + *なぜ ?*: AngularJSはモジュール化と分割のパターンを推奨しています。他のモジュールを結びつけるアプリケーションのルートモジュールを作ることは、 モジュールの追加や削除を行う簡単な方法を与えます。 + +### Keep the App Module Thin +###### [Style [Y162](#style-y162)] + + - アプリケーションのモジュールの中でロジックは統合する箇所にのみに置いて下さい。それぞれのモジュールの中の機能はそのままにして下さい。 + + *なぜ ?*: アプリケーションのルートにリモートのデータ取得、ビューの表示、もしくはアプリケーションに統合と関係のない他のロジックなどの役割を加えることは、アプリをより混沌とさせ、機能のセットを再利用もしくは無効にすることをより難しくします。 + + *なぜ ?*: ルートのモジュールは、どのモジュールがアプリケーションを構成するかを記述するマニュフェストになります。 + +### Feature Areas are Modules +###### [Style [Y163](#style-y163)] + + - 再利用可能で共有される機能エリアでモジュールを作成して下さい。レイアウトのように、サービスやダッシュボード、アプリケーションスペシフィックな機能(例えば、カスタマー、アドミン、セールス)がそれに該当します。 + + *なぜ ?*: 自己完結型のモジュールは衝突が少ないか全く無い形でアプリケーションに追加することができます。 + + *なぜ ?*: スプリントやイテレーション中は機能エリアにフォーカスし、スプリントやイテレーションの終わりでは、それらの機能をオンにできます。 + + *なぜ ?*:機能エリアでモジュールに分割することで、コードの分離と再利用が可能となり、モジュールのテストが容易になります。 + +### Reusable Blocks are Modules +###### [Style [Y164](#style-y164)] + + - 再利用可能なアプリケーションのブロックでモジュールを作成して下さい。例外のハンドリング、ログ、ダイアグ、セキュリティ、ローカルデータの退避のような共通のサービスがそれに該当します。 + + *なぜ ?*: これらの機能は多くのアプリケーションで必要となり、それぞれモジュールとして分離し続けることによって、ジェネリックになりアプリケーション間で再利用可能となります。 + +### Module Dependencies +###### [Style [Y165](#style-y165)] + + - ルートのモジュールは、アプリケーションスペシフィックなモジュールや共有または再利用されるモジュールに依存します。 + + ![Modularity and Dependencies](https://raw.githubusercontent.com/johnpapa/angularjs-styleguide/master/assets/modularity-1.png) + + *なぜ ?*: メインのアプリケーションのモジュールは、アプリケーションの機能を素早く特定可能なマニュフェストを含みます。 + + *なぜ ?*: それぞれの機能エリアはそれが何と依存しているかを示したマニフェストを含んでいます。そのお陰で機能エリアは依存性を取得することができ、例え他のアプリケーションの中であっても動作します。 + + *なぜ ?*: データを共有するサービスのようなアプリ内の機能は、`app.core`(このモジュールは好きな名前を選んで下さい)のようにまとめることで、簡単に位置を特定または共有することが可能です。 + + Note: これは一貫性のためのストラテジーです。ここには多くの良いオプションがあります。AngularJSの依存のルールに沿って一貫性をとるためにその一つを選ぶことで メンテナンスしスケールさせることが容易になります。 + + >  私のストラクチャはプロジェクト間で少しだけ変わっていますが、ストラクチャやモジュール化に関してはこのガイドラインに沿っています。実装は、機能やチームに依存して変わるかもしれません。言い換えれば、同等のストラクチャにこだわってるのではなく、一貫性やメンテナンス性、効率性を念頭に置いて正しいことを行うということです。 + + > 小さいアプリでは、共有される全ての依存を機能的なモジュールと直接的な依存を持たないモジュールの中に入れてしまうことも検討して下さい。この方法は、小さいアプリケーションのメンテナンスをより容易にしますが、アプリの外からそのモジュールを再利用することは難しくなります。 + +**[Back to top](#table-of-contents)** + +## Startup Logic + +### Configuration +###### [Style [Y170](#style-y170)] + + - angularのアプリが走る前にコンフィグが設定される[module configuration](https://docs.angularjs.org/guide/module#module-loading-dependencies)のコードを注入して下さい。 providerやconstantsが含まれるのが理想的です。 + + *なぜ ?*: コンフィグレーションをする箇所がより少なくなります。 + + ```javascript + angular + .module('app') + .config(configure); + + configure.$inject = + ['routerHelperProvider', 'exceptionHandlerProvider', 'toastr']; + + function configure (routerHelperProvider, exceptionHandlerProvider, toastr) { + exceptionHandlerProvider.configure(config.appErrorPrefix); + configureStateHelper(); + + toastr.options.timeOut = 4000; + toastr.options.positionClass = 'toast-bottom-right'; + + //////////////// + + function configureStateHelper() { + routerHelperProvider.configure({ + docTitle: 'NG-Modular: ' + }); + } + } + ``` + +### Run Blocks +###### [Style [Y171](#style-y171)] + + - アプリケーションが起動されるときに実行されるどのコードもファクトリで宣言され、関数経由で公開され、[run block](https://docs.angularjs.org/guide/module#module-loading-dependencies)として注入されるべきです。 + + *なぜ ?*: コードをrunのブロックに直接いれてしまうとテストするのが難しくなります。ファクトリに置くことで抽象化しモック化することが容易になります。 + + ```javascript + angular + .module('app') + .run(runBlock); + + runBlock.$inject = ['authenticator', 'translator']; + + function runBlock(authenticator, translator) { + authenticator.initialize(); + translator.initialize(); + } + ``` + +**[Back to top](#table-of-contents)** + +## Angular $ Wrapper Services + +### $document and $window +###### [Style [Y180](#style-y180)] + + - `document`と`window`の代わりに[`$document`](https://docs.angularjs.org/api/ng/service/$document)と[`$window`](https://docs.angularjs.org/api/ng/service/$window)を使って下さい。 + + *なぜ ?*: これらのサービスはAngularによってラップされているので、直接documentやwindowを使うよりはテスタブルになります。これにより自分自身でdocumentやwindowをモックすることを避けることができます。 + +### $timeout and $interval +###### [Style [Y181](#style-y181)] + + - `setTimeout` と `setInterval`の代わりに[`$timeout`](https://docs.angularjs.org/api/ng/service/$timeout)と[`$interval`](https://docs.angularjs.org/api/ng/service/$interval)を使って下さい。 + + *なぜ ?*: これらのサービスはAngularによってラップされているのでよりテスタブルになります。またAngularJSのdigestのサイクルでハンドルされるので、データバインディングが同期され続けます。 + +**[Back to top](#table-of-contents)** + +## Testing +単体テストはクリーンなコードを維持するのに役立ちます。より詳細な情報は、私のお薦めするいくつかの単体テストの基礎をリンク付きで紹介しています。 + +### Write Tests with Stories +###### [Style [Y190](#style-y190)] + + - 全てのストーリーのテストを書いて下さい。 空のテストから始めてストーリ毎にコードを書き中身を埋めて下さい。 + + *なぜ ?*: テストのデスクリプションを書くことは、ストーリが何をして、何をしないのか、何をもって成功とみなすのかを明確に定義するのに役立ちます。 + + ```javascript + it('should have Avengers controller', function() { + // TODO + }); + + it('should find 1 Avenger when filtered by name', function() { + // TODO + }); + + it('should have 10 Avengers', function() { + // TODO (mock data?) + }); + + it('should return Avengers via XHR', function() { + // TODO ($httpBackend?) + }); + + // and so on + ``` + +### Testing Library +###### [Style [Y191](#style-y191)] + + - 単体テストには [Jasmine](http://jasmine.github.io/) もしくは [Mocha](http://mochajs.org) を使って下さい。 + + *なぜ ?*: Jasmine と Mocha はAngularJSのコミュニティで幅広く使われています。双方とも安定しており、十分メンテされており、ロバストなテスト機能が与えられます。 + + Note: Mochaを用いるときは、合わせて[Chai](http://chaijs.com)といったアサートのライブラリを選ぶことを検討して下さい。 + +### Test Runner +###### [Style [Y192](#style-y192)] + + - テストランナーとしては[Karma](http://karma-runner.github.io)を使って下さい。 + + *なぜ ?*: Karmaは一度だけ実行するか、コードが変更されたときに自動的に実行するかを簡単に設定することができます。 + + *なぜ ?*: Karmaは自前のテストランナーもしくはGruntやGulpを用いた継続的なインテグレーションのプロセスに容易に接続することができます。 + + *なぜ ?*: [WebStorm](http://www.jetbrains.com/webstorm/) や [Visual Studio](http://visualstudiogallery.msdn.microsoft.com/02f47876-0e7a-4f6c-93f8-1af5d5189225)などのいくつかのIDEはKarmaを統合し始めています。 + + *なぜ ?*: Karmaは[Grunt](http://www.gruntjs.com) (と [grunt-karma](https://github.com/karma-runner/grunt-karma)) and [Gulp](http://www.gulpjs.com) (と [gulp-karma](https://github.com/lazd/gulp-karma))といった自動化のタスク上で正しく動作します。 + +### Stubbing and Spying +###### [Style [Y193](#style-y193)] + + - スタブやスパイのために [Sinon](http://sinonjs.org/) を使って下さい。 + + *なぜ ?*: SinonはJasminとMochaと一緒に正しく動作し、スタブやスパイの機能を拡張します。 + + *Why?*: もしJasmineとMochaの両方を試したければ、Sinonはそれらを簡単に切り替えることができます。 + +### Headless Browser +###### [Style [Y194](#style-y194)] + + - サーバ上でテストを実行するときは [PhantomJS](http://phantomjs.org/) を使って下さい。 + + *なぜ ?*: PhantomJSはヘッドレスブラウザであり、"visual"なブラウザを必要とすることなくテストを実行するのに役立ちます。 ChromeやSafari、IEや他のブラウザをサーバにインストールする必要はありません。 + + Note: それでも尚、ターゲットとなるユーザの環境で全てのブラウザ上でテストをするべきです。 + +### Code Analysis +###### [Style [Y195](#style-y195)] + + - テスト上でJSHintを実行して下さい。 + + *なぜ ?*: テストもコードです。JSHintはテストが正しく動作しないかもしれないコードの品質の問題を特定するのに役立ちます。 + +### Alleviate Globals for JSHint Rules on Tests +###### [Style [Y196](#style-y196)] + + -  テストコードでは、`describe`や`expect`といった共通のグローバルな変数を許すようにルールを緩めて下さい。 + + *なぜ ?*: テストもコードであり、プロダクションのコードと同様に注意が払われ、コードの品質のルールが必要となります。しかしながら、テストのフレームワークで用いられるグローバル変数は、例えば、テストのスペックに以下を含むことによって緩められます。 + + ```javascript + /* global sinon, describe, it, afterEach, beforeEach, expect, inject */ + ``` + + ![Testing Tools](https://raw.githubusercontent.com/johnpapa/angularjs-styleguide/master/assets/testing-tools.png) + +### Organizing Tests +###### [Style [Y197](#style-y197)] + + - 単体テストのファイル(スペック)はクライアントコードと横並びで置いて下さい。サーバのインテグレーションや複数のコンポーネントのテストをカバーするスペックは`tests`のフォルダに置いて下さい。 + + *なぜ ?*: 単体テストは特定のコンポーネントとソースファイルに直接の相関があります。 + + *なぜ ?*: いつも見えるところにそれらを置いて最新にしておく方がより簡単です。 TDDか開発中にテストをするか開発後にテストするに関わらず、コーディングをするときは、スペックが横に並びにあり、見えなくなることも気にならなくなることもないようにして下さい。こうすることで、よりメンテナンスされるようになり、コードのカバレッジも上がるでしょう。 + + *なぜ ?*: ソースコードをアップデートするとき、同時にテストもアップデートした方が簡単です。 + + *なぜ ?*: 横並びに置くことは見つけることを簡単にしソースを移動するときに合わせて動かすことができます。 + + *なぜ ?*: 近くにスペックファイルを置くことは、ソースコードのリーダーがそのコンポーネントがどのように使われるかを学ぶことや既知の制限が簡単に知ることが容易となります。 + + *なぜ ?*: gruntやgulpを使えば配布用のビルドに含まれないようにスペックを分割することは簡単です。 + + ``` + /src/client/app/customers/customer-detail.controller.js + /customer-detail.controller.spec.js + /customers.controller.spec.js + /customers.controller-detail.spec.js + /customers.module.js + /customers.route.js + /customers.route.spec.js + ``` + +**[Back to top](#table-of-contents)** + +## Animations + +### Usage +###### [Style [Y210](#style-y210)] + + - ビューや主要なビュジアルの要素で、ステート間を遷移するために、さりげない[animations with AngularJS](https://docs.angularjs.org/guide/animations)を使って下さい。[ngAnimate module](https://docs.angularjs.org/api/ngAnimate)を含めて下さい。三つの鍵はさりげなさ、スムーズさ、そしてシームレスです。 + + *なぜ ?*: さりげないアニメーションは、適切に使われることでユーザエクスペリエンスを改善します。 + + *なぜ ?*: さりげないアニメーションは、ビューの遷移の際に感じるパフォーマンスを改善します。 + +### Sub Second +###### [Style [Y211](#style-y211)] + + - デュレーションの短いアニメーションを使って下さい。私は大体300ミリ秒からはじめて適切なところまで調整します。 + + *なぜ ?*: 長いアニメーションはアプリケーションが遅い印象を与え、ユーザエクスペリエンスや体感のパフォーマンス上では逆効果になります、 + +### animate.css +###### [Style [Y212](#style-y212)] + + - 慣習的なアニメーションには[animate.css](http://daneden.github.io/animate.css/)を使って下さい。 + + *なぜ ?*: animation.cssが提供するアニメーションは速く、スムーズで、アプリケーションへの追加が容易です。 + + *なぜ ?*: アニメーションに一貫性を持たせます。 + + *なぜ ?*: animate.cssは広く利用されておりテストされています。 + + Note: この[Matias NiemeläによるAngularJSのアニメーションの素晴らしいポスト](http://www.yearofmoo.com/2013/08/remastered-animation-in-angularjs-1-2.html)を見て下さい。 + +**[Back to top](#table-of-contents)** + +## Comments + +### jsDoc +###### [Style [Y220](#style-y220)] + + - もしドキュメントの作成を計画しているのなら、関数名、説明、引数、そして戻り値を記述するために[`jsDoc`](http://usejsdoc.org/)のシンタックスを使って下さい。アプリケーションの構造に合わせて`@namespace`や`@memberOf`を使って下さい。 + + *なぜ ?*: フルスクラッチでドキュメントを書く代わりに、コードからドキュメントを生成(再生成)できます。 + + *なぜ ?*: 共通の生産性の高いツールを使うことで一貫性を保てます。 + + ```javascript + /** + * Logger Factory + * @namespace Factories + */ + (function() { + angular + .module('app') + .factory('logger', logger); + + /** + * @namespace Logger + * @desc Application wide logger + * @memberOf Factories + */ + function logger($log) { + var service = { + logError: logError + }; + return service; + + //////////// + + /** + * @name logError + * @desc Logs errors + * @param {String} msg Message to log + * @returns {String} + * @memberOf Factories.Logger + */ + function logError(msg) { + var loggedMsg = 'Error: ' + msg; + $log.error(loggedMsg); + return loggedMsg; + }; + } + })(); + ``` + +**[Back to top](#table-of-contents)** + +## JS Hint + +### Use an Options File +###### [Style [Y230](#style-y230)] + + - JavaScriptのコードにlintをかけるためにJS Hintを使って下さい。JS Hintのオプションを必ずカスタマイズしてソースコード管理に含めて下さい。詳細なオプションは[JS Hint docs](http://www.jshint.com/docs/)を参照して下さい。 + + *なぜ ?*: ソース管理にコードをコミットする前に最初にアラートが上がります。 + + *なぜ ?*: チームに一貫性が生まれます。 + + ```javascript + { + "bitwise": true, + "camelcase": true, + "curly": true, + "eqeqeq": true, + "es3": false, + "forin": true, + "freeze": true, + "immed": true, + "indent": 4, + "latedef": "nofunc", + "newcap": true, + "noarg": true, + "noempty": true, + "nonbsp": true, + "nonew": true, + "plusplus": false, + "quotmark": "single", + "undef": true, + "unused": false, + "strict": false, + "maxparams": 10, + "maxdepth": 5, + "maxstatements": 40, + "maxcomplexity": 8, + "maxlen": 120, + + "asi": false, + "boss": false, + "debug": false, + "eqnull": true, + "esnext": false, + "evil": false, + "expr": false, + "funcscope": false, + "globalstrict": false, + "iterator": false, + "lastsemic": false, + "laxbreak": false, + "laxcomma": false, + "loopfunc": true, + "maxerr": false, + "moz": false, + "multistr": false, + "notypeof": false, + "proto": false, + "scripturl": false, + "shadow": false, + "sub": true, + "supernew": false, + "validthis": false, + "noyield": false, + + "browser": true, + "node": true, + + "globals": { + "angular": false, + "$": false + } + } + ``` + +**[Back to top](#table-of-contents)** + +## Constants + +### Vendor Globals +###### [Style [Y240](#style-y240)] + + - vendorのライブラリのグローバル変数のためにAngularJSの定数を作って下さい。 + + *なぜ ?*: グローバルになってしまうvendorのライブラリを注入するための方法を与えます。 これによりコンポーネントが持っている依存性をより簡単に把握することで(抽象性の破綻を避け)、コードのテスタビリティが改善されます。さらに理にかなうように、これらのコンポーネントをモックでテストできるようになります。 + + ```javascript + // constants.js + + /* global toastr:false, moment:false */ + (function() { + 'use strict'; + + angular + .module('app.core') + .constant('toastr', toastr) + .constant('moment', moment); + })(); + ``` + +###### [Style [Y241](#style-y241)] + + - 変更されず他のサービスに依存しない値のために定数を使って下さい。定数が複数のアプリケーションで再利用されるモジュールだけに使われるときは、モジュールの後ろに定数とわかるファイル名でモジュール毎にファイル定数を置いて下さい。これが必要となるまでは、メインモジュールの`constants.js`のファイルに定数を置いて下さい。 + + *なぜ ?*: 変更されるかもしれない値は、たとえ頻繁でなかったとしてもサービスから取得されるべきです。そうすることでソースコードを変更する必要がなくなります。例えば、データサービスのためのURLを定数で置くときは、Webサービスからロードする方がより良い場所になるでしょう。 + + *なぜ ?*: 定数はプロバイダーを含めたAngularのコンポーネントの中に注入可能です。 + + *なぜ ?*: アプリケーションが他のアプリケーションからも再利用される可能性のあるモジュールに分割されるときに、依存のある定数をそれぞれのモジュール上で保持することで、モジュールが単独で定数を運用できるようにするべきです。 + + ```javascript + // Constants used by the entire app + angular + .module('app.core') + .constant('moment', moment); + + // Constants used only by the sales module + angular + .module('app.sales') + .constant('events', { + ORDER_CREATED: 'event_order_created', + INVENTORY_DEPLETED: 'event_inventory_depleted' + }); + ``` + +**[Back to top](#table-of-contents)** + +## File Templates and Snippets + +一貫性のあるスタイルやパターンに従うため、ファイルテンプレートもしくはスニペットを使って下さい。ここにいくつかのWeb開発のエディターやIDEsのためのテンプレート、もしくはスニペットがあります。 + +### Sublime Text +###### [Style [Y250](#style-y250)] + + - 本スタイルやガイドラインに沿ったAngularJSのスニペット + + - [Sublime Angular snippets](assets/sublime-angular-snippets.zip?raw=true)をダウンロード + - Packagesフォルダに置く + - Sublimeを再起動 + - JavaScriptのファイルのタイプで`TAB`に続いて下記のコマンドを打ちます。 + + ```javascript + ngcontroller // creates an Angular controller + ngdirective // creates an Angular directive + ngfactory // creates an Angular factory + ngmodule // creates an Angular module + ``` + +### Visual Studio +###### [Style [Y251](#style-y251)] + + - 本スタイルやガイドラインに沿ったAngularJSのファイルのテンプレートが[SideWaffle](http://www.sidewaffle.com)で公開されています。 + + - [SideWaffle](http://www.sidewaffle.com) で Visual Studio extension (vsixファイル) をダウンロード + - vsixファイルを実行 + - Visual Studioの再起動 + +### WebStorm +###### [Style [Y252](#style-y252)] + + - 本スタイルやガイドラインに沿ったAngularJSスニペットとファイルテンプレート。WebStormのsettingsへインポートできます。 + + - [WebStorm AngularJS file templates and snippets](assets/webstorm-angular-file-template.settings.jar?raw=true)をダウンロード + - WebStormを開き、 `File`メニューを開く + - メニューオプションから`Import Settings`を選ぶ + - ファイルを選択し、`OK`をクリック + - JavaScriptのファイルタイプで`TAB`に続いて下記のコマンドを打ちます。 + + ```javascript + ng-c // creates an Angular controller + ng-f // creates an Angular factory + ng-m // creates an Angular module + ``` + +**[Back to top](#table-of-contents)** + +## Yeoman Generator +###### [Style [Y260](#style-y260)] + +このスタイルガイドに沿ったAngularのアプリケーションを作る良いスタートポイントとして、[HotTowel yeoman generator](http://jpapa.me/yohottowel)を使うことができます。 + +1. generator-hottowelをインストール + + ``` + npm install -g generator-hottowel + ``` + +2. 新規フォルダを作成し、そのディレクトリに移動 + + ``` + mkdir myapp + cd myapp + ``` + +3. ジェネレータの実行 + + ``` + yo hottowel helloWorld + ``` + +**[Back to top](#table-of-contents)** + +## Routing +ビューと数多くの小さいテンプレートおよびディレクティブを持つビューの組み合わせからなるビューの間のナビゲーションのフローを作るために、クライアントサイドのルーティングは重要です。 + +###### [Style [Y270](#style-y270)] + + - クライアントサイドのルーティングには[AngularUI Router](http://angular-ui.github.io/ui-router/) を使って下さい。 + + *なぜ ?*: UI RouterはAngularのルーターが持つ全ての機能プラス、ネスト化されたルーティングやステートなどいくつかの追加機能があります。 + + *なぜ ?*: シンタックスはAngularのルータと非常に似ており、UI Routerへ容易に移行できます。 + +###### [Style [Y271](#style-y271)] + + - ビューが存在するモジュールの中でビューのためのルーティングを定義して下さい。それぞれのモジュールはモジュール内のビューのためのルーティングを含むべきです。 + + *なぜ ?*: それぞれのモジュールが独立して成り立つべきである。 + + *なぜ ?*: モジュールの削除と追加が行われるときに、アプリケーションは存在するビューを示すルーティングだけを含むでしょう。 + + *なぜ ?*: このことは親のないルーティングが出来てしまう懸念を持たずに、アプリケーションの一部分を有効にしたり無効にしたりするのを簡単にします。 + +**[Back to top](#table-of-contents)** + +## Task Automation + +自動タスクの生成に[Gulp](http://gulpjs.com)または[Grunt](http://gruntjs.com)を使って下さい。Gulpはコンフィグレーションをコーディングでリーンに行えます。一方で、Gruntはコードをコンフィグレーションでリーンに行うことができます。個人的には読みやすくまた書きやすいGulpを好みますが両者とも素晴らしいです。 + +###### [Style [Y400](#style-y400)] + + - その他全てのアプリケーションのJavaScriptファイルに先立って、モジュール定義ファイルの`*.module.js`をリスト化する自動化タスクを使って下さい。 + + *なぜ ?*: Angularはそれらが使用される前にモジュール定義を登録する必要があります。 + + *なぜ ?*: `*.module.js`のように特定のパターンで命名されたモジュールは、容易にグラブしさらにリストの先頭で列挙することができます。 + + ```javascript + var clientApp = './src/client/app/'; + + // Always grab module files first + var files = [ + clientApp + '**/*.module.js', + clientApp + '**/*.js' + ]; + ``` + +**[Back to top](#table-of-contents)** + +## AngularJS docs +その他の情報、APIリファレンス、については、[Angular documentation](//docs.angularjs.org/api)をチェックして下さい。 + +## Contributing + +Open an issue first to discuss potential changes/additions. If you have questions with the guide, feel free to leave them as issues in the repository. If you find a typo, create a pull request. The idea is to keep the content up to date and use github’s native feature to help tell the story with issues and PR’s, which are all searchable via google. Why? Because odds are if you have a question, someone else does too! You can learn more here at about how to contribute. + +*By contributing to this repository you are agreeing to make your content available subject to the license of this repository.* + +### Process + 1. Discuss the changes in a GitHub issue. + 2. Open a Pull Request against the develop branch, reference the issue, and explain the change and why it adds value. + 3. The Pull Request will be evaluated and either merged or declined. + +## License + +_tldr; Use this guide. Attributions are appreciated._ + +### (The MIT License) + +Copyright (c) 2014 [John Papa](http://johnpapa.net) + +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. + +**[Back to top](#table-of-contents)** From 00b6b6a633a543c149ecd024c01905022105d1be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=B5=B5=E5=8F=AF?= Date: Sun, 22 Feb 2015 15:40:15 +0800 Subject: [PATCH 192/567] update to #285 --- i18n/zh-CN.md | 132 +++++++++++++++++++++++++++++++------------------- 1 file changed, 83 insertions(+), 49 deletions(-) diff --git a/i18n/zh-CN.md b/i18n/zh-CN.md index e3316014..f4ba4ac2 100644 --- a/i18n/zh-CN.md +++ b/i18n/zh-CN.md @@ -1763,6 +1763,8 @@ ```javascript /* recommended */ + var handlingRouteChangeError = false; + function handleRoutingErrors() { /** * Route cancellation: @@ -1771,14 +1773,25 @@ */ $rootScope.$on('$routeChangeError', function(event, current, previous, rejection) { - var destination = (current && (current.title || current.name || current.loadedTemplateUrl)) || - 'unknown target'; - var msg = 'Error routing to ' + destination + '. ' + (rejection.msg || ''); + if (handlingRouteChangeError) { return; } + handlingRouteChangeError = true; + var destination = (current && (current.title || + current.name || current.loadedTemplateUrl)) || + 'unknown target'; + var msg = 'Error routing to ' + destination + '. ' + + (rejection.msg || ''); + /** * Optionally log using a custom service or $log. * (Don't forget to inject custom service) */ logger.warning(msg, [current]); + + /** + * On routing error, go to another route/state. + */ + $location.path('/'); + } ); } @@ -2652,6 +2665,72 @@ **[返回顶部](#目录)** +## 文件模板和片段 +使用文件模板和片段帮助保持一致性的风格,这里有针对一些web开发的编辑器和IDE的模板和(或)片段。 + +###Sublime Text +###### [Style [Y250](#style-y250)] + + - AngularJS片段遵循这些风格指南。 + + - 下载[Sublime Angular snippets](assets/sublime-angular-snippets.zip?raw=true) + - 把它放到Packages文件夹中 + - 重启Sublime + - 在JavaScript文件中输入下面的命令然后按下`TAB`键即可: + + ```javascript + ngcontroller // creates an Angular controller + ngdirective // creates an Angular directive + ngfactory // creates an Angular factory + ngmodule // creates an Angular module + ``` + +###Visual Studio +###### [Style [Y251](#style-y251)] + + - 下载Visual Studio扩展文件[SideWaffle](http://www.sidewaffle.com) + - 运行下载的vsix文件 + - 重启Visual Studio + +###WebStorm +###### [Style [Y252](#style-y252)] + + - 你可以把它们导入到WebStorm设置中: + + - 下载[WebStorm AngularJS file templates and snippets](assets/webstorm-angular-file-template.settings.jar?raw=true) + - 打开WebStorm点击`File`菜单 + - 选择`Import Settings`菜单选项 + - 选择文件点击`OK` + - 在JavaScript文件中输入下面的命令然后按下`TAB`键即可: + + ```javascript + ng-c // creates an Angular controller + ng-f // creates an Angular factory + ng-m // creates an Angular module + ``` + +### Atom +###### [Style [Y253](#style-y253)] + + - AngularJS snippets that follow these styles and guidelines. + ``` + apm install angularjs-styleguide-snippets + ``` + or + - Open Atom, then open the Package Manager (Packages -> Settings View -> Install Packages/Themes) + - Search for the package 'angularjs-styleguide-snippets' + - Click 'Install' to install the package + + - In a JavaScript file type these commands followed by a `TAB` + + ```javascript + ngcontroller // creates an Angular controller + ngdirective // creates an Angular directive + ngfactory // creates an Angular factory + ngmodule // creates an Angular module + ``` +**[返回顶部](#目录)** + ## Yeoman Generator ###### [Style [Y260](#style-y260)] @@ -2726,51 +2805,6 @@ ## AngularJS文档 [Angular文档](//docs.angularjs.org/api)。 -## 文件模板和片段 -使用文件模板和片段帮助保持一致性的风格,这里有针对一些web开发的编辑器和IDE的模板和(或)片段。 - -###Sublime Text -###### [Style [Y250](#style-y250)] - - - AngularJS片段遵循这些风格指南。 - - - 下载[Sublime Angular snippets](assets/sublime-angular-snippets.zip?raw=true) - - 把它放到Packages文件夹中 - - 重启Sublime - - 在JavaScript文件中输入下面的命令然后按下`TAB`键即可: - - ```javascript - ngcontroller // creates an Angular controller - ngdirective // creates an Angular directive - ngfactory // creates an Angular factory - ngmodule // creates an Angular module - ``` - -###Visual Studio -###### [Style [Y251](#style-y251)] - - - 下载Visual Studio扩展文件[SideWaffle](http://www.sidewaffle.com) - - 运行下载的vsix文件 - - 重启Visual Studio - -###WebStorm -###### [Style [Y252](#style-y252)] - - - 你可以把它们导入到WebStorm设置中: - - - 下载[WebStorm AngularJS file templates and snippets](assets/webstorm-angular-file-template.settings.jar?raw=true) - - 打开WebStorm点击`File`菜单 - - 选择`Import Settings`菜单选项 - - 选择文件点击`OK` - - 在JavaScript文件中输入下面的命令然后按下`TAB`键即可: - - ```javascript - ng-c // creates an Angular controller - ng-f // creates an Angular factory - ng-m // creates an Angular module - ``` -**[返回顶部](#目录)** - ## 贡献 先打开一个问题讨论潜在的变化和增加。如果你对这篇指南有问题,随时在仓库中提出问题。如果你发现了一个错字,创建一个pull request。这样做是为了保持内容的更新,使用github的原生功能通过问题和PR来帮助讲述这个故事,具体做法可以google一下。为什么?因为如果你有问题,其他人可能有同样的问题,你在这里可以学到如何贡献。 @@ -2780,7 +2814,7 @@ ###过程 1. 在Github Issue中讨论这个问题。 - 2. 在develop分支中开一个pull request,引用这个问题,解释你做的修改和为什么要这样做。 + 2. 拉取一个pull request,引用这个问题,解释你做的修改和为什么要这样做。 3. pull request将会被进行评估,结果就是合并或是拒绝。 ## 许可证 From 020ebfad30ac24d82554d310b2a4267d869cb3fd Mon Sep 17 00:00:00 2001 From: noritamago Date: Sun, 22 Feb 2015 21:05:53 +0900 Subject: [PATCH 193/567] merge for Atom and removing develop branch --- i18n/ja-JP.md | 39 +++++++++++++++++++++++++++++++++++++-- 1 file changed, 37 insertions(+), 2 deletions(-) diff --git a/i18n/ja-JP.md b/i18n/ja-JP.md index 647ddd6a..cd0c0608 100644 --- a/i18n/ja-JP.md +++ b/i18n/ja-JP.md @@ -1770,6 +1770,8 @@ ```javascript /* recommended */ + var handlingRouteChangeError = false; + function handleRoutingErrors() { /** * Route cancellation: @@ -1778,14 +1780,26 @@ */ $rootScope.$on('$routeChangeError', function(event, current, previous, rejection) { - var destination = (current && (current.title || current.name || current.loadedTemplateUrl)) || + if (handlingRouteChangeError) { return; } + handlingRouteChangeError = true; + var destination = (current && (current.title || + current.name || current.loadedTemplateUrl)) || 'unknown target'; var msg = 'Error routing to ' + destination + '. ' + (rejection.msg || ''); + var msg = 'Error routing to ' + destination + '. ' + + (rejection.msg || ''); + /** * Optionally log using a custom service or $log. * (Don't forget to inject custom service) */ logger.warning(msg, [current]); + + /** + * On routing error, go to another route/state. + */ + $location.path('/'); + } ); } @@ -2707,6 +2721,27 @@ ng-m // creates an Angular module ``` +### Atom +###### [Style [Y253](#style-y253)] + + - 本スタイルとガイドラインに沿ったAngularJSスニペット that follow these styles and guidelines. + ``` + apm install angularjs-styleguide-snippets + ``` + or + - Atomを開き、Package Managerを開く (Packages -> Settings View -> Install Packages/Themes) + - 'angularjs-styleguide-snippets'のパッケージを検索 + - パッケージをインストールするために'Install'をクリック + + - JavaScriptのファイルタイプで、`TAB`に続いて下記のコマンドを打ちます。 + + ```javascript + ngcontroller // creates an Angular controller + ngdirective // creates an Angular directive + ngfactory // creates an Angular factory + ngmodule // creates an Angular module + ``` + **[Back to top](#table-of-contents)** ## Yeoman Generator @@ -2793,7 +2828,7 @@ Open an issue first to discuss potential changes/additions. If you have question ### Process 1. Discuss the changes in a GitHub issue. - 2. Open a Pull Request against the develop branch, reference the issue, and explain the change and why it adds value. + 2. Open a Pull Request, reference the issue, and explain the change and why it adds value. 3. The Pull Request will be evaluated and either merged or declined. ## License From deb57add4d469e9cbb52e9f607f4a25652772cee Mon Sep 17 00:00:00 2001 From: John Papa Date: Sun, 22 Feb 2015 08:41:47 -0500 Subject: [PATCH 194/567] Update README.md --- i18n/README.md | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/i18n/README.md b/i18n/README.md index 92b61ced..20dd3f7e 100644 --- a/i18n/README.md +++ b/i18n/README.md @@ -6,10 +6,11 @@ The [original English version](http://jpapa.me/ngstyles) is the source of truth, 1. [French](fr-FR.md) 2. [Italian](it-IT.md) -3. [Macedonian](mk-MK.md) -4. [Portuguese-Brazil](PT-BR.md) -5. [Russian](ru-RU.md) -6. [Simplified Chinese](zh-CN.md) +3. [Japanese](ja-JP.md) +4. [Macedonian](mk-MK.md) +5. [Portuguese-Brazil](PT-BR.md) +6. [Russian](ru-RU.md) +7. [Simplified Chinese](zh-CN.md) ## Contributing Language translations are welcomed and encouraged. The succcess of these translations depends on the community. I highly encourage new translation contributions and help to keep them up to date. From c6edbca0823fa38c821a33394f149e1616ed67a4 Mon Sep 17 00:00:00 2001 From: John Papa Date: Sun, 22 Feb 2015 08:45:04 -0500 Subject: [PATCH 195/567] Update ja-JP.md --- i18n/ja-JP.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/i18n/ja-JP.md b/i18n/ja-JP.md index cd0c0608..ef025912 100644 --- a/i18n/ja-JP.md +++ b/i18n/ja-JP.md @@ -2,6 +2,8 @@ *[@john_papa](//twitter.com/john_papa)によるチームのための頑固なAngularJSスタイルガイド* +*Translation by [@noritamago](https://github.com/noritamago)* + もしあなたがAngularJSのシンタックス、規約、そしてアプリケーション構成のための頑固なスタイルガイドを探しているなら、どうぞいらっしゃい!本スタイルは、[AngularJS](//angularjs.org)を用いた私の開発経験やプレゼンテーション、[Pluralsight training courses](http://pluralsight.com/training/Authors/Details/john-papa) 、そしてチームでの作業に基づいたものです。 このスタイルガイドの目的は、私が実践している規約だけでなく、私がそれを行う理由を示すことによって、AngularJSアプリケーションを構築する手引きとなることです。 From 1208d7afc5adf8647389c2cf09838622655051e6 Mon Sep 17 00:00:00 2001 From: John Papa Date: Sun, 22 Feb 2015 08:45:45 -0500 Subject: [PATCH 196/567] Update ja-JP.md --- i18n/ja-JP.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/i18n/ja-JP.md b/i18n/ja-JP.md index ef025912..48856048 100644 --- a/i18n/ja-JP.md +++ b/i18n/ja-JP.md @@ -4,6 +4,8 @@ *Translation by [@noritamago](https://github.com/noritamago)* +>The [original English version](http://jpapa.me/ngstyles) is the source of truth, as it is maintained and updated first. + もしあなたがAngularJSのシンタックス、規約、そしてアプリケーション構成のための頑固なスタイルガイドを探しているなら、どうぞいらっしゃい!本スタイルは、[AngularJS](//angularjs.org)を用いた私の開発経験やプレゼンテーション、[Pluralsight training courses](http://pluralsight.com/training/Authors/Details/john-papa) 、そしてチームでの作業に基づいたものです。 このスタイルガイドの目的は、私が実践している規約だけでなく、私がそれを行う理由を示すことによって、AngularJSアプリケーションを構築する手引きとなることです。 From f04ac6db3769638e99b5447943632971dd358d69 Mon Sep 17 00:00:00 2001 From: Gilberto Villa Date: Mon, 23 Feb 2015 13:56:32 -0600 Subject: [PATCH 197/567] Fix some typos and update translations according to the context --- i18n/es-ES.md | 448 +++++++++++++++++++++++++------------------------- 1 file changed, 226 insertions(+), 222 deletions(-) diff --git a/i18n/es-ES.md b/i18n/es-ES.md index b24772c6..a144c997 100644 --- a/i18n/es-ES.md +++ b/i18n/es-ES.md @@ -2,16 +2,16 @@ *Guía de estilos colaborativa de AngularJS para equipos por [@john_papa](//twitter.com/john_papa)* -Si estás buscando una guía colaborativa sobre sintaxis, convenciones y estructura de aplicaciones con AngulRJS, este es el sitio. Estos estilos están basados en mi experiencia desarrollando con [AngularJS](//angularjs.org), persentaciones, [Cursos en Pluralsight](http://pluralsight.com/training/Authors/Details/john-papa) y trabajando en equipo. +Si estás buscando una guía colaborativa sobre sintaxis, convenciones y estructura de aplicaciones con AngulRJS, este es el sitio. Estos estilos están basados en mi experiencia desarrollando con [AngularJS](//angularjs.org), persentaciones, [Cursos en Pluralsight](http://pluralsight.com/training/Authors/Details/john-papa) y trabajando en equipos. -El propósito de esta guía de estilos es proporcionar una guía de cómo construir aplicaciones con AngularJS enseñando convenciones que uso y, lo más importante, el porqué. +El propósito de esta guía de estilos es proporcionar una guía de cómo construir aplicaciones con AngularJS enseñando convenciones que uso y, lo más importante, el porqué. >Si te gusta esta guía, écha un vistazo al curso de Pluralsight [AngularJS Patterns: Clean Code](http://jpapa.me/ngclean). [![AngularJs Patterns: Clean Code](https://raw.githubusercontent.com/johnpapa/angularjs-styleguide/master/assets/ng-clean-code-banner.png)](http://jpapa.me/ngclean) - + ## Asombrosa comunidad y créditos -Nunca trabajes solo. Personalmente, la comunidad de AngularJS es un increíble grupo que apasionado por compartir experiencias. Como por ejemplo, mi amigo y experto AngularJS Todd Motto, con el que he colaborado en muchas de los estilos y convenciones. Estamos de acuerdo en la mayoría, y en otras no. Te recomiendo que le eches un vistazo a [Todd's guidelines](https://github.com/toddmotto/angularjs-styleguide) para que le des sentido a ésta guía y la compares. +Nunca trabajes solo. Personalmente, la comunidad de AngularJS es un increíble grupo apasionado por compartir experiencias. Como por ejemplo, mi amigo y experto en AngularJS Todd Motto, con el que he colaborado en muchos de los estilos y convenciones. Estamos de acuerdo en la mayoría, y en otras no. Te recomiendo que le eches un vistazo a [Todd's guidelines](https://github.com/toddmotto/angularjs-styleguide) para que le des sentido a ésta guía y la compares. Muchos de los estilos han salido de las muchas sesiones de pair programming que [Ward Bell](http://twitter.com/wardbell) y yo hemos tenido. Aunque no siempre coincidimos, mi amigo Ward me ha ayudado con la última evolución de ésta guía. @@ -23,14 +23,14 @@ Mientras que esta guía explica el *qué*, *por qué* y *cómo*, me resulta úti ## Tabla de contenidos - 1. [Single Responsibility](#single-responsibility) + 1. [Responsabilidad Única](#single-responsibility) 1. [IIFE](#iife) - 1. [Modules](#modules) - 1. [Controllers](#controllers) - 1. [Services](#services) + 1. [Módulos](#modules) + 1. [Controladores](#controllers) + 1. [Servicios](#services) 1. [Factories](#factories) 1. [Data Services](#data-services) - 1. [Directives](#directives) + 1. [Directivas](#directives) 1. [Resolving Promises for a Controller](#resolving-promises-for-a-controller) 1. [Manual Annotating for Dependency Injection](#manual-annotating-for-dependency-injection) 1. [Minification and Annotation](#minification-and-annotation) @@ -42,7 +42,7 @@ Mientras que esta guía explica el *qué*, *por qué* y *cómo*, me resulta úti 1. [Startup Logic](#startup-logic) 1. [Angular $ Wrapper Services](#angular--wrapper-services) 1. [Testing](#testing) - 1. [Animations](#animations) + 1. [Animations](#animations) 1. [Comments](#comments) 1. [JSHint](#js-hint) 1. [Constants](#constants) @@ -61,7 +61,7 @@ Mientras que esta guía explica el *qué*, *por qué* y *cómo*, me resulta úti - Define 1 componente por archivo. - El siguiente ejemplo define el módulo `app` y sus dependencias, define un controller, y defines una factory todo en el mismo archivo. + El siguiente ejemplo define el módulo `app` y sus dependencias, define un controlador, y defines una factory todo en el mismo archivo. ```javascript /* evitar */ @@ -69,7 +69,7 @@ Mientras que esta guía explica el *qué*, *por qué* y *cómo*, me resulta úti .module('app', ['ngRoute']) .controller('SomeController', SomeController) .factory('someFactory', someFactory); - + function SomeController() { } function someFactory() { } @@ -103,17 +103,17 @@ Mientras que esta guía explica el *qué*, *por qué* y *cómo*, me resulta úti angular .module('app') .factory('someFactory', someFactory); - + function someFactory() { } ``` **[Volver arriba](#table-of-contents)** ## IIFE -### JavaScript Closures +### Closures de JavaScript ###### [Style [Y010](#style-y010)] - - Envuelve los componentes AngularJS en una expersiónb de función que se invoca inmediatamente Immediately Invoked Function Expression (IIFE). + - Envuelve los componentes AngularJS en una expresión de función que se invoca inmediatamente Immediately Invoked Function Expression (IIFE). *¿Por qué?*: Una IIFE elimina las variables del scope global. Esto ayuda a prevenir que las variables y las declaraciones de funciones vivan más de lo esperado en el scope global, evitando así colisión de variables. @@ -140,7 +140,7 @@ Mientras que esta guía explica el *qué*, *por qué* y *cómo*, me resulta úti ```javascript /** - * recomendado + * recomendado * * así no dejamos ninguna variable global */ @@ -168,28 +168,28 @@ Mientras que esta guía explica el *qué*, *por qué* y *cómo*, me resulta úti })(); ``` - - Nota: Para acortar únicamente, el resto de ejemplo de esta guía podrían omitir la sintaxis IIFE. + - Nota: Para acortar únicamente, el resto de los ejemplos de esta guía podrían omitir la sintaxis IIFE. - Nota: IIFE previente que el código de los tests llegue a sus variables privadas, como expresiones regulares o funciones de ayuda que normalmente vienen bien para hacer pruebas por sí solas. Sin embargo, puedes acceder a ellas creando accesorios o accediendo a través de sus componentes. Por ejemplo, poniendo las funciones de ayuda, expresiones regulares o constantes en su propia factory. **[Volver arriba](#table-of-contents)** -## Modules +## Módulos ### Evitando la colisión de nombres ###### [Style [Y020](#style-y020)] - - Use una convención de nombres única con separadores para los sub-módulos. + - Use una convención de nombres única con separadores para los sub-módulos. - *¿Por qué?*: Nombres únicos ayudan a evitar colisiones en los nombres de módulos. Los separadores ayudan a definir los módulos y la jerarquía de sus sub-módulos. Por ejemplo `app` puede ser tu módulo raiz y `app.dashboard` y `app.users` pueden ser módulos que dependen de `app`. + *¿Por qué?*: Nombres únicos ayudan a evitar colisiones en los nombres de módulos. Los separadores ayudan a definir los módulos y la jerarquía de sus sub-módulos. Por ejemplo `app` puede ser tu módulo raíz y `app.dashboard` y `app.users` pueden ser módulos que dependen de `app`. -### Definitions (aka Setters) +### Definiciones (aka Setters) ###### [Style [Y021](#style-y021)] - - Declara los módulos sin usar la variable, usando la sintaxis de los setters. + - Declara los módulos sin usar una variable, usando la sintaxis de los setters. *¿Por qué?*: Con un componente por archivo, es raro que necesitemos introducir una variable para el módulo. - + ```javascript /* evitar */ var app = angular.module('app', [ @@ -216,9 +216,9 @@ Mientras que esta guía explica el *qué*, *por qué* y *cómo*, me resulta úti ### Getters ###### [Style [Y022](#style-y022)] - - Cuando usemos un módulo, evita usar la variable y usando su getter en su lugar. + - Al usar un módulo, evita usar una variable y en su lugar usa encadenamiento con la sintaxis de los getter. - *¿Por quñe?*: Esto hace más legible el código y evita que las variables colisionen. + *¿Por qué?*: Esto hace más legible el código y evita que las variables colisionen. ```javascript /* evitar */ @@ -245,12 +245,12 @@ Mientras que esta guía explica el *qué*, *por qué* y *cómo*, me resulta úti *¿Por qué?*: Un módulo debe ser creado sólo una vez y recuperado desde ese punto. - Usa `angular.module('app', []);` para setear un módulo. - - Usa `angular.module('app');` para recuperar un módulo. + - Usa `angular.module('app');` para recuperar un módulo. ### Funciones anónimas vs funciones con nombre ###### [Style [Y024](#style-y024)] - - Usa funciones con nombre en lugar de pasar una función anónima en el callback. + - Usa funciones con nombre en lugar de pasar una función anónima en el callback. *¿Por qué?*: Así el código es más legible, es más fácil de debugear, y reduce la cantidad de código anidado en los callbacks. @@ -284,18 +284,18 @@ Mientras que esta guía explica el *qué*, *por qué* y *cómo*, me resulta úti **[Volver arriba](#table-of-contents)** -## Controllers +## Controladores -### controllerAs View Syntax +### controllerAs Sintaxis en la Vista ###### [Style [Y030](#style-y030)] - - Usa la sintaxis [`controllerAs`](http://www.johnpapa.net/do-you-like-your-angular-controllers-with-or-without-sugar/) en lugar del `clásico controller con $scope`. + - Usa la sintaxis [`controllerAs`](http://www.johnpapa.net/do-you-like-your-angular-controllers-with-or-without-sugar/) en lugar del `clásico controlador con $scope`. - *¿Por qué?*: Los Controllers se construyen, renuevan y proporcionan una nueva única instancia, y la sintaxis `controllerAs` se acerca más a eso que con la `sintaxis clásico de $scope`. + *¿Por qué?*: Los Controladores se construyen, renuevan y proporcionan una nueva instancia única, y la sintaxis `controllerAs` se acerca más a eso que la `sintaxis clásica de $scope`. - *¿Por qué?*: Enlazas el uso del objeto con el "punto" a la View (ej. `customer.name` en lugar de `name`), así es más contextual, fácil de leer y evitas problemas de referencia que pueden aparecer con el "punto". + *¿Por qué?*: Promueves el uso de binding usando el "." en el objeto dentro de la Vista (ej. `customer.name` en lugar de `name`), así es más contextual, fácil de leer y evitas problemas de referencia que pueden aparecer con el "punto". - *¿Por qué?*: Ayuda a evitar usar `$parent` en las Views con controllers anidados. + *¿Por qué?*: Ayuda a evitar usar `$parent` en las Vistas con controladores anidados. ```html @@ -311,16 +311,16 @@ Mientras que esta guía explica el *qué*, *por qué* y *cómo*, me resulta úti ``` -### controllerAs Controller Syntax +### controllerAs Sintaxis en el Controlador ###### [Style [Y031](#style-y031)] - - Usa la sintaxis `controllerAs` en lugar del `cláxico controller con $scope`. + - Usa la sintaxis `controllerAs` en lugar del `clásico controlador con $scope`. - - La sintaxis `controllerAs` usa `this` dentro de los controllers que se asocian al `$scope` + - La sintaxis `controllerAs` usa `this` dentro de los controladores que se asocian al `$scope` - *¿Por qué?*: `controllerAs` es azucar sintáctico sobre el `$scope`. Puedes enlazar a la vista y acceder a los métodos del `$scope`. + *¿Por qué?*: `controllerAs` es azúcar sintáctico sobre el `$scope`. Puedes enlazar a la vista y acceder a los métodos del `$scope`. - *¿Por qué?*: Ayuda a evitar la tentación de usar los métodos del `$scope` dentro de un controller cuando debería ser mejor evitar usarlos o moverlos a una factory. Considera usar `$scope` en una factory, o en un controlador sólo cuando sea necesario. Por ejemplo cuando publicas y te suscribes a eventos usando [`$emit`](https://docs.angularjs.org/api/ng/type/$rootScope.Scope#$emit), [`$broadcast`](https://docs.angularjs.org/api/ng/type/$rootScope.Scope#$broadcast), o [`$on`](https://docs.angularjs.org/api/ng/type/$rootScope.Scope#$on) considera mover estos usos a una factory e invocarlos desde el controller. + *¿Por qué?*: Ayuda a evitar la tentación de usar los métodos del `$scope` dentro de un controller cuando debería ser mejor evitar usarlos o moverlos a una factory. Considera usar `$scope` en una factory, o en un controlador sólo cuando sea necesario. Por ejemplo cuando publicas y te suscribes a eventos usando [`$emit`](https://docs.angularjs.org/api/ng/type/$rootScope.Scope#$emit), [`$broadcast`](https://docs.angularjs.org/api/ng/type/$rootScope.Scope#$broadcast), o [`$on`](https://docs.angularjs.org/api/ng/type/$rootScope.Scope#$on) considera mover estos usos a una factory e invocarlos desde el controller. ```javascript /* evitar */ @@ -338,12 +338,12 @@ Mientras que esta guía explica el *qué*, *por qué* y *cómo*, me resulta úti } ``` -### controllerAs with vm +### controllerAs con vm ###### [Style [Y032](#style-y032)] - Usa una variable para capturar `this` cuando uses la sintaxis `controllerAs`. Elige un nombre de variable consistente como `vm`, de ViewModel. - - *¿Por qué?*: La palabra `this` es contextual y cuando es usada dentro de una función en un controller puede cambiar su contexto. Capturando el contexto de `this` te evita encontrarte este problema. + + *¿Por qué?*: La palabra `this` es contextual y cuando es usada dentro de una función en un controlador puede cambiar su contexto. Capturando el contexto de `this` te evita encontrarte este problema. ```javascript /* evitar */ @@ -362,14 +362,14 @@ Mientras que esta guía explica el *qué*, *por qué* y *cómo*, me resulta úti } ``` - Nota: Puedes evitar los warnings de [jshint](http://www.jshint.com/) escribiendo un comentario encima de la línea de c´pdigo. Sin embargo no hace falta si el nombre de la función empieza por mayúsculas, ya que esa es la convención para las funciones de los constructores, que es lo que un controller en Angular es. + Nota: Puedes evitar los warnings de [jshint](http://www.jshint.com/) escribiendo un comentario encima de la línea de código. Sin embargo no hace falta si el nombre de la función empieza con mayúsculas, ya que esa es la convención para las funciones de los constructores, que es lo que un controller en Angular es. ```javascript /* jshint validthis: true */ var vm = this; ``` - Nota: Cuando crees watches en un controller usando `controller as`, puedes observar la variable `vm.*` usando la siguiente sintaxis.(Crea los watchers con precación ya que añaden mucha carca al ciclo de digest) + Nota: Cuando crees watchers en un controlador usando `controller as`, puedes observar la variable `vm.*` usando la siguiente sintaxis.(Crea los watchers con precaución ya que añaden mucha carga al ciclo de digest) ```html @@ -387,14 +387,14 @@ Mientras que esta guía explica el *qué*, *por qué* y *cómo*, me resulta úti } ``` -### Bindable Members Up Top +### Miembros Bindeables Arriba ###### [Style [Y033](#style-y033)] - - Coloca las asociaciones en la parte superior del controller, por orden alfabético y no separados a lo largo del código del controller. + - Coloca las asociaciones en la parte superior del controlador, ordenalas alfabéticamente y no las distribuyas a lo largo del código del controlador. - *¿Por qué?*: Colocar las variables asignables arriba hace más fácil la lectura y te ayuda a identificar qué variables del controlador pueden ser asociadas y usadas en la View. + *¿Por qué?*: Colocar las variables asignables arriba hace más fácil la lectura y te ayuda a identificar qué variables del controlador pueden ser asociadas y usadas en la Vista. - *¿Por qué?*: Setear funciones anónimas puede ser fácil, pero cuando esas funciones tienen más de una línea de código se hace menos legible. Definiendo las funciones bajo a las variables, hace que los detalles de implementación estén abajo, deja las variables arriba y las funciones abajo. + *¿Por qué?*: Setear funciones anónimas puede ser fácil, pero cuando esas funciones tienen más de una línea de código se hace menos legible. Definir las funciones bajo las variables bindeables (las declaraciones de las funciones serán movidas hacia arriba en el proceso de hoisting), hace que los detalles de implementación estén abajo, deja las variables arriba y más sencilla la lectura. ```javascript /* evitar */ @@ -451,8 +451,8 @@ Mientras que esta guía explica el *qué*, *por qué* y *cómo*, me resulta úti vm.gotoSession = gotoSession; vm.refresh = function() { - /** - * líneas + /** + * líneas * de * código * que afectan a @@ -476,24 +476,26 @@ Mientras que esta guía explica el *qué*, *por qué* y *cómo*, me resulta úti vm.title = 'Sessions'; ``` -### Function Declarations to Hide Implementation Details +### Declaraciones de Funciones para Esconder los Detalles de Implementación ###### [Style [Y034](#style-y034)] - - Declara funciones para ocultar detalles de implementación. Mantén las variables asignables arriba. Cuando necesites asignar una función a un controlador referencia una función que aparezca después en el archivo. Esto está directamente relacionado con la sección: Bindable Members Up Top. Para más detalles mira [este post](http://www.johnpapa.net/angular-function-declarations-function-expressions-and-readable-code). + - Declara funciones para ocultar detalles de implementación. Mantén las variables bindeables arriba. Cuando necesites bindear una función a un controlador referencia una función que aparezca después en el archivo. Esto está directamente relacionado con la sección: Miembros Bindeables Arriba. Para más detalles mira [este post](http://www.johnpapa.net/angular-function-declarations-function-expressions-and-readable-code). - *¿Por qué?*: Colocar las variables asignables arriba hace más fácil la lectura y te ayuda a identificar qué variables del controlador pueden ser asociadas y usadas en la View. + *¿Por qué?*: Colocar las variables bindeables arriba hace más fácil la lectura y te ayuda a identificar qué variables del controlador pueden ser asociadas y usadas en la Vista. - *¿Por qué?*: Colocar los detalles de implementación de una función al final del deja la complejidad fuera de la vista, con las cosas importantes arriba. + *¿Por qué?*: Colocar los detalles de implementación de una función al final del archivo deja la complejidad fuera de vista así puedes ver las cosas importantes arriba. - *¿Por qué?*: Evitamos problemas usando funciones antes de ser definidas. + *¿Por qué?*: La declaración de las funciones son movidas arriba por el + proceso de hoisting así que no tenemos que preocuparnos por usar una + función antes de que sea definida (como la habría si fueran funciones en forma de expresión) *¿Por qué?*: No tendrás que propcuparte de que si pones `var a` antes de `var b` se rompa el código porque `a` dependa de `b`. - *¿Por qué?*: El orden es crítico para las funciones + *¿Por qué?*: El orden es crítico para las funciones en forma de expresión ```javascript - /** - * evitar + /** + * evitar * Using function expressions. */ function Avengers(dataservice, logger) { @@ -520,13 +522,13 @@ Mientras que esta guía explica el *qué*, *por qué* y *cómo*, me resulta úti } ``` - Nótese que lo importante está disperso en el ejemplo anterior. En el siguiente ejemplo, lo importante está arriba. Por ejemplo, las variables asociadas al controller como `vm.avengers` y `vm.title`. Los detalles de implementación están debajo. Así es más fácil de leer. + Nótese que las cosas importantes están dispersas en el ejemplo anterior. En el siguiente ejemplo, lo importante está arriba. Por ejemplo, las variables asociadas al controller como `vm.avengers` y `vm.title`. Los detalles de implementación están debajo. Así es más fácil de leer. ```javascript /* * recomendado - * Usando declaraciones de funciones y - * asignandola a las variables arriba. + * Usando declaraciones de funciones y + * miembros bindeables arriba. */ function Avengers(dataservice, logger) { var vm = this; @@ -551,16 +553,16 @@ Mientras que esta guía explica el *qué*, *por qué* y *cómo*, me resulta úti } ``` -### Defer Controller Logic +### Diferir la Lógica del Controlador ###### [Style [Y035](#style-y035)] - - Difiera la lógica dentro de un controller delegándola en services y factories. + - Difiera la lógica dentro de un controlador delegándola a servicios y factories. - *¿Por qué?*: La lógica podría ser reutilizada por varios controllers cuando la colocas en un service y la expones como una función. + *¿Por qué?*: La lógica podría ser reutilizada por varios controladores cuando la colocas en un servicio y la expones como una función. *¿Por qué?*: La lógica en un servicio puede ser aislada en un test unitario, mientras que la lógica de llamadas en un controller se puede mockear fácilmente. - *¿Por qué?*: Elimina dependencias y esconde detalles de implementación del controller. + *¿Por qué?*: Elimina dependencias y esconde detalles de implementación del controlador. ```javascript @@ -601,7 +603,7 @@ Mientras que esta guía explica el *qué*, *por qué* y *cómo*, me resulta úti vm.isCreditOk; vm.total = 0; - function checkCredit() { + function checkCredit() { return creditService.isOrderTotalOk(vm.total) .then(function(isOk) { vm.isCreditOk = isOk; }) .catch(showServiceError); @@ -609,21 +611,21 @@ Mientras que esta guía explica el *qué*, *por qué* y *cómo*, me resulta úti } ``` -### Keep Controllers Focused +### Mantén tus Controladores Enfocados ###### [Style [Y037](#style-y037)] - - Define un controller para una vista, no intentes reutilizar el controller para otras views. En lugar de eso, mueve la lógica que se pueda reutilizar en factories y deja el controller simple, enfocándose en su view. + - Define un controller para una vista, no intentes reutilizar el controller para otras vistas. En lugar de eso, mueve la lógica que se pueda reutilizar a factories y deja el controlador simple y enfocado en su vista. - *¿Por qué?*: Reutilizar controllers con varias views es arriesgado y necesitarías un buen end to end (e2e) test para asegurar que todo funciona bien en la aplicación. + *¿Por qué?*: Reutilizar controladores con varias vistas es arriesgado y necesitarías buena cobertura de tests end to end (e2e) para asegurar que todo funciona bien en la aplicación. -### Assigning Controllers +### Asignando Controladores ###### [Style [Y038](#style-y038)] - - Cuando un controller debe ser asociado a una view y cada componente puede ser reutilizado por otros controllers o views, define controllers con sus rutas. + - Cuando un controlador debe ser asociado a una vista y cada componente puede ser reutilizado por otros controladores o vistas, define controladores con sus rutas. - Nota: Si una View es cargada por otra además de por la ruta, entonces usa la sintaxis `ng-controller="Avengers as vm"`. + Nota: Si una Vista es cargada por otra además de por la ruta, entonces usa la sintaxis `ng-controller="Avengers as vm"`. - *¿Por qué?*: Emparejar el controller en la ruta permite a diferentes rutas invocar diferentes pares de controllers y views. Cuando los controllers son asignados en la view usando [`ng-controller`](https://docs.angularjs.org/api/ng/directive/ngController), esa view siempre estará asociada al mismo controller. + *¿Por qué?*: Emparejar el controlador en la ruta permite a diferentes rutas invocar diferentes pares de controladores y vistas. Cuando los controladores son asignados en la vista usando [`ng-controller`](https://docs.angularjs.org/api/ng/directive/ngController), esa vista siempre estará asociada al mismo controlador. ```javascript /* evitar - cuando se use con una ruta y queramos asociarlo dinámicamente */ @@ -673,12 +675,12 @@ Mientras que esta guía explica el *qué*, *por qué* y *cómo*, me resulta úti **[Volver arriba](#table-of-contents)** -## Services +## Servicios ### Singletons ###### [Style [Y040](#style-y040)] - - Los Services son instanciados con un `new`, usan `this` para los métodos públicos y las variables. Ya que son muy similares a las factories, usa una factory en su lugar por consistencia. + - Los Servicios son instanciados con un `new`, usan `this` para los métodos públicos y las variables. Ya que son muy similares a las factories, usa una factory en su lugar por consistencia. Nota: [Todos los servicios AngularJS son singletons](https://docs.angularjs.org/guide/services). Esto significa que sólo hay una instancia de un servicio por inyector. @@ -714,7 +716,7 @@ Mientras que esta guía explica el *qué*, *por qué* y *cómo*, me resulta úti ## Factories -### Single Responsibility +### Responsabilidad Única ###### [Style [Y050](#style-y050)] - Las factories deben tener una [responsabilidad única](http://en.wikipedia.org/wiki/Single_responsibility_principle), que es encapsulada por su contexto. Cuando una factory empiece a exceder el principio de responsabilidad única, una nueva factory debe ser creada. @@ -726,25 +728,25 @@ Mientras que esta guía explica el *qué*, *por qué* y *cómo*, me resulta úti Nota: [Todos los servicios AngularJS son singletons](https://docs.angularjs.org/guide/services). -### Accessible Members Up Top +### Miembros accesibles Arriba ###### [Style [Y052](#style-y052)] - - Expón las variables que se llaman del servicio (su interfaz) arriba, usando la técnica deribada de [Revealing Module Pattern](http://addyosmani.com/resources/essentialjsdesignpatterns/book/#revealingmodulepatternjavascript). + - Expón las variables que se llaman del servicio (su interfaz) arriba, usando la técnica deribada de [Revealing Module Pattern](http://addyosmani.com/resources/essentialjsdesignpatterns/book/#revealingmodulepatternjavascript). - *¿Por qué?*: Colocar los elementos que se llamand arriba hace más fácil la lectura y te ayuda a identificar los elementos del servicio que se pueden llamar y se deben testear (y/o mockear). + *¿Por qué?*: Colocar los elementos que se llaman arriba hace más fácil la lectura y te ayuda a identificar los elementos del servicio que se pueden llamar y se deben testear (y/o mockear). *¿Por qué?*: Es especialmente útil cuando el archivo se hace más largo, ya que ayuda a evitar el scroll para ver qué se expone. - *¿Por qué?*: Setear las funciones puede ser fácil, pero cuando tienen más de una línea ser reduce la legibilidad. Definiendo la interfaz mueve los detalles de implementación abajo, mantiene la interfaz que se llama arriba y lo hace más fácil de leer. + *¿Por qué?*: Setear las funciones puede ser fácil, pero cuando tienen más de una línea ser reduce la legibilidad. Definiendo la interfaz mueve los detalles de implementación abajo, mantiene la interfaz que va a ser llamada arriba y lo hace más fácil de leer. ```javascript /* evitar */ function dataService() { var someValue = ''; - function save() { + function save() { /* */ }; - function validate() { + function validate() { /* */ }; @@ -769,62 +771,62 @@ Mientras que esta guía explica el *qué*, *por qué* y *cómo*, me resulta úti //////////// - function save() { + function save() { /* */ }; - function validate() { + function validate() { /* */ }; } ``` - De esta forma se asocian los enlaces desde el objeto que lo mantiene, los valores primitivos no se pueden modificar por si solos usando este patrón + De esta forma se asocian los bindeos desde el objeto que lo mantiene, los valores primitivos no se pueden modificar por si solos usando este patrón ![Factories Usando "Above the Fold"](https://raw.githubusercontent.com/johnpapa/angularjs-styleguide/master/assets/above-the-fold-2.png) -### Function Declarations to Hide Implementation Details +### Declaración de Funciones para Esconder los Detalles de Implementación ###### [Style [Y053](#style-y053)] - Declara funciones para esconder detalles de implementación. Manten los elementos accesibles en la parte superior de la factory. Referencia a los que aparezcan después en el archivo. Para más detalles visita [este post](http://www.johnpapa.net/angular-function-declarations-function-expressions-and-readable-code). - *¿Por qué?*: Coloca los elementos accesibles en la parte superior para hacerlo más fácil de leer y ayudarte instantáneamente a identificar qué funciones de la factory te pueden ayudar externamente. + *¿Por qué?*: Coloca los elementos accesibles en la parte superior para hacerlo más fácil de leer y ayudarte a identificar instantáneamente qué funciones de la factory se pueden accesar externamente. *¿Por qué?*: Colocar los detalles de implementación de una función al final del archivo mueve esa complegidad fuera de la vista, de esta forma puedes dejar lo importante arriba. - *¿Por qué?*: Las declaraciones de las funciones son "hoisted" de esta forma no hay problemas en usar una función antes de su definición (como la habría si fuera una expresión). + *¿Por qué?*: Las declaraciones de las funciones son "hoisted" de esta forma no hay problemas en usar una función antes de su definición (como la habría si fueran funciones en forma de expresión). *¿Por qué?*: No tendrás que propcuparte de que si pones `var a` antes de `var b` se rompa el código porque `a` dependa de `b`. - *¿Por qué?*: El orden es crítico para las expresiones + *¿Por qué?*: El orden es crítico para las funciones en forma de expresión ```javascript /** * evitar - * Usar function expressions + * Usar función como expresión */ function dataservice($http, $location, $q, exception, logger) { var isPrimed = false; var primePromise; var getAvengers = function() { - // implementation details go here + // detalles de implementación van aquí }; var getAvengerCount = function() { - // implementation details go here + // detalles de implementación van aquí }; var getAvengersCast = function() { - // implementation details go here + // detalles de implementación van aquí }; var prime = function() { - // implementation details go here + // detalles de implementación van aquí }; var ready = function(nextPromises) { - // implementation details go here + // detalles de implementación van aquí }; var service = { @@ -841,8 +843,8 @@ Mientras que esta guía explica el *qué*, *por qué* y *cómo*, me resulta úti ```javascript /** * recomendado - * Using function declarations - * and accessible members up top. + * Usar declaración de funciones + * y miembros accesibles arriba */ function dataservice($http, $location, $q, exception, logger) { var isPrimed = false; @@ -860,23 +862,23 @@ Mientras que esta guía explica el *qué*, *por qué* y *cómo*, me resulta úti //////////// function getAvengers() { - // implementation details go here + // detalles de implementación van aquí } function getAvengerCount() { - // implementation details go here + // detalles de implementación van aquí } function getAvengersCast() { - // implementation details go here + // detalles de implementación van aquí } function prime() { - // implementation details go here + // detalles de implementación van aquí } function ready(nextPromises) { - // implementation details go here + // detalles de implementación van aquí } } ``` @@ -888,13 +890,13 @@ Mientras que esta guía explica el *qué*, *por qué* y *cómo*, me resulta úti ### Separate Data Calls ###### [Style [Y060](#style-y060)] - - Refactoriza la lógica para hacer operaciones e interaciones con datos en una factory, que los servicios responsables de las peticiones XHR, local storage, memoria o cualquier otra operación con datos. + - Refactoriza la lógica para hacer operaciones e interaciones con datos en una factory. Crear data services responsables de las peticiones XHR, local storage, memoria o cualquier otra operación con datos. - *¿Por qué?*: La responsabilidad del controller es la presentación y recoger la información para la view. No debe importarle cómo se consiguen los datos, sólo saber cómo conseguirlos. Separando los servicios de datos movemos la lógica de cómo conseguirlos al servicio de datos, y deja el controller simple, enfocandose en la vista. + *¿Por qué?*: La responsabilidad del controlador es la de presentar y recoger información para la vista. No debe importarle cómo se consiguen los datos, sólo saber cómo conseguirlos. Separando los data services movemos la lógica de cómo conseguirlos al data service, y deja el controlador simple, enfocándose en la vista. - *¿Por qué?*: Lo hace más fácil de testear (mock o real) las llamadas de datos cuando testeamos un controller que usa un servicio de datos. + *¿Por qué?*: Hace más fácil testear (mock o real) las llamadas de datos cuando testeamos un controlador que usa un data service. - *¿Por qué?*: La implementación del servicio de datos puede tener código muy específico para usar el repositorio de datos. Podría incluir cabeceras, cómo hablar a los datos, u otros servicios como $http. Separando la lógica en servicios de datos encapsulamos la lógica en un único lugar, escondiendo la implementación de sus consumidores externos (quizá un controller), de esta forma es más fácil cambiar la implementación. + *¿Por qué?*: La implementación del data service puede tener código muy específico para usar el repositorio de datos. Podría incluir cabeceras, cómo hablar a los datos, u otros servicios como $http. Separando la lógica en data services encapsulamos la lógica en un único lugar, escondiendo la implementación de sus consumidores externos (quizá un controlador), de esta forma es más fácil cambiar la implementación. ```javascript /* recomendado */ @@ -926,13 +928,13 @@ Mientras que esta guía explica el *qué*, *por qué* y *cómo*, me resulta úti } } ``` - - Nota: El servicio de datos es llamado desde los consumidores, como el controller, escondiendo la implementación del consumidor como se muestra a continuación. + + Nota: El data service es llamado desde los consumidores, como el controlador, escondiendo la implementación del consumidor como se muestra a continuación. ```javascript /* recomendado */ - // controller llamando a la factory del servicio de datos + // controller llamando a la factory del data service angular .module('app.avengers') .controller('Avengers', Avengers); @@ -958,15 +960,15 @@ Mientras que esta guía explica el *qué*, *por qué* y *cómo*, me resulta úti return vm.avengers; }); } - } + } ``` -### Return a Promise from Data Calls +### Regresa una Promesa desde las Llamadas a Datos ###### [Style [Y061](#style-y061)] - - Cuando llamamos a servicios de datos que devuelven una promesa como $http, devuelve una promesa en la llamada de tu función también. + - Cuando llamamos a data services que devuelven una promesa como $http, devuelve una promesa en la llamada de tu función también. - *¿Por qué?*: Puedes encadenar promesas y hacer algo cuando la llamada se complete y resuelva o rechaze la promesa. + *¿Por qué?*: Puedes encadenar promesas y hacer algo cuando la llamada se complete y resuelva o rechace la promesa. ```javascript /* recomendado */ @@ -991,14 +993,14 @@ Mientras que esta guía explica el *qué*, *por qué* y *cómo*, me resulta úti function getAvengers() { /** * Step 2 - * Pide al servicio de datos los datos y espera + * Pide al data service los datos y espera * por la promesa */ return dataservice.getAvengers() .then(function(data) { /** * Step 3 - * setea los datos y resuelva la promesa + * setea los datos y resuelve la promesa */ vm.avengers = data; return vm.avengers; @@ -1008,13 +1010,13 @@ Mientras que esta guía explica el *qué*, *por qué* y *cómo*, me resulta úti **[Volver arriba](#table-of-contents)** -## Directives -### Limit 1 Per File +## Directivas +### Limitadas a 1 Por Archivo ###### [Style [Y070](#style-y070)] - - Crea una directiva por archivo. Llama al archivo como la directiva. + - Crea una directiva por archivo. Llama al archivo como la directiva. - *¿Por qué?*: Es muy fácil colocar todas las directivas en un archivo, pero será más difícil de partir para ser compartida entre aplicaciones, modulos o para un simple módulo. + *¿Por qué?*: Es muy fácil colocar todas las directivas en un archivo, pero será más difícil de partir para ser compartida entre aplicaciones, módulos o para un simple módulo. *¿Por qué?*: Una directiva por archivo es fácil de mantener. @@ -1025,25 +1027,27 @@ Mientras que esta guía explica el *qué*, *por qué* y *cómo*, me resulta úti angular .module('app.widgets') - /* order directive that is specific to the order module */ + /* directiva de órdenes que es específica del módulo de órdenes*/ .directive('orderCalendarRange', orderCalendarRange) - /* sales directive that can be used anywhere across the sales app */ + /* directiva de ventas que puede ser usada en algún otro lado a lo + largo de la aplicación de ventas */ .directive('salesCustomerInfo', salesCustomerInfo) - /* spinner directive that can be used anywhere across apps */ + /* directiva de spinner que puede ser usada a lo largo de las + aplicaciones */ .directive('sharedSpinner', sharedSpinner); function orderCalendarRange() { - /* implementation details */ + /* detalles de implementación */ } function salesCustomerInfo() { - /* implementation details */ + /* detalles de implementación */ } function sharedSpinner() { - /* implementation details */ + /* detalles de implementación */ } ``` @@ -1052,7 +1056,7 @@ Mientras que esta guía explica el *qué*, *por qué* y *cómo*, me resulta úti /* calendarRange.directive.js */ /** - * @desc order directive that is specific to the order module at a company named Acme + * @desc directiva de órdenes que es específica al módulo de órdenes en la compañía Acme * @example
*/ angular @@ -1060,7 +1064,7 @@ Mientras que esta guía explica el *qué*, *por qué* y *cómo*, me resulta úti .directive('acmeOrderCalendarRange', orderCalendarRange); function orderCalendarRange() { - /* implementation details */ + /* detalles de implementación */ } ``` @@ -1069,15 +1073,15 @@ Mientras que esta guía explica el *qué*, *por qué* y *cómo*, me resulta úti /* customerInfo.directive.js */ /** - * @desc spinner directive that can be used anywhere across the sales app at a company named Acme + * @desc directiva de ventas que puede ser usada a lo largo de la aplicación de ventas en la compañía Acme * @example
- */ + */ angular .module('sales.widgets') .directive('acmeSalesCustomerInfo', salesCustomerInfo); function salesCustomerInfo() { - /* implementation details */ + /* detalles de implementación */ } ``` @@ -1086,7 +1090,7 @@ Mientras que esta guía explica el *qué*, *por qué* y *cómo*, me resulta úti /* spinner.directive.js */ /** - * @desc spinner directive that can be used anywhere across apps at a company named Acme + * @desc directiva de spinner que puede ser usada a lo largo de las applicaciones en la compañía Acme * @example
*/ angular @@ -1094,36 +1098,36 @@ Mientras que esta guía explica el *qué*, *por qué* y *cómo*, me resulta úti .directive('acmeSharedSpinner', sharedSpinner); function sharedSpinner() { - /* implementation details */ + /* detalles de implementación */ } ``` - Nota: Hay muchas formas de llamar a las directivas, especialmente cuando pueden ser usadas en scopes específicas. Elige un nombre que tenga sentido para la directiva y que su archivo sea distintivo y claro. Hemos visto algunos ejemplos antes, pero veremos más en la sección de cómo nombrar. + Nota: Hay muchas formas de llamar a las directivas, especialmente cuando pueden ser usadas en scopes específicos. Elige un nombre que tenga sentido para la directiva y que su archivo sea distintivo y claro. Hemos visto algunos ejemplos antes, pero veremos más en la sección de cómo nombrar. -### Manipulate DOM in a Directive +### Manipula el DOM en una Directiva ###### [Style [Y072](#style-y072)] - - Cuando manipules DOM directamente, usa una directiva. Si hay alguna alternativa como usando un CSS para cambiar el estilo o el [animation services](https://docs.angularjs.org/api/ngAnimate), Angular templating, [`ngShow`](https://docs.angularjs.org/api/ng/directive/ngShow) o [`ngHide`](https://docs.angularjs.org/api/ng/directive/ngHide), Entonces úsalos en su lugar. Por ejemplo, si la directiva sólo muestra o esconde elementos, usa ngHide/ngShow. + - Cuando manipules DOM directamente, usa una directiva. Si hay alguna alternativa como usando CSS para cambiar los estilos o los [animation services](https://docs.angularjs.org/api/ngAnimate), Angular templating, [`ngShow`](https://docs.angularjs.org/api/ng/directive/ngShow) o [`ngHide`](https://docs.angularjs.org/api/ng/directive/ngHide), entonces úsalos en su lugar. Por ejemplo, si la directiva sólo muestra o esconde elementos, usa ngHide/ngShow. - *¿Por qué?*: Manipular el DOM puede ser dificil de testear, debugear y normalmente hay mejores maneras (e.g. CSS, animations, templates) + *¿Por qué?*: Manipular el DOM puede ser difícil de testear, debugear y normalmente hay mejores maneras (e.g. CSS, animations, templates) -### Provide a Unique Directive Prefix +### Provee un Prefijo Único de Directiva ###### [Style [Y073](#style-y073)] - - Proporciona prefijo corto, único y descriptiovo como `acmeSalesCustomerInfo` que se declara en el HTML como `acme-sales-customer-info`. + - Proporciona un prefijo corto, único y descriptivo como `acmeSalesCustomerInfo` que se declare en el HTML como `acme-sales-customer-info`. - *¿Por qué?*: El prefijo corto y único identifica el contexto de la directiva y el origen. Por ejemplo el prefijo `cc-` puede indicar que la directiva en particular es parte de la aplicación CodeCamper, mientras que `acme-` pudiera indicar que la directiva es de la compañía Acme. + *¿Por qué?*: El prefijo corto y único identifica el contexto de la directiva y el origen. Por ejemplo el prefijo `cc-` puede indicar que la directiva en particular es parte de la aplicación CodeCamper, mientras que `acme-` pudiera indicar que la directiva es de la compañía Acme. - Nota: Evita `ng-` ya que está reservado para las directivas AngularJS. Estudia sabiamente las directivas usadas para evitar conflictos de nombres, como `ion-` de [Ionic Framework](http://ionicframework.com/). + Nota: Evita `ng-` ya que está reservado para las directivas AngularJS. Estudia sabiamente las directivas usadas para evitar conflictos de nombres, como `ion-` de [Ionic Framework](http://ionicframework.com/). -### Restrict to Elements and Attributes +### Limitate a Elementos y Atributos ###### [Style [Y074](#style-y074)] - - Cuando crees directivas que tengan sentido como elemento, restringe `E` (elemento personalizado) y opcionalmente restringe `A` (atributo personalizado). Generalmente, si puede ser su control propio, `E` es apropiado, La guía genera es permitir `EA` pero intenta implementarlo como un elemento cuando sea un elemento único y como un atributo cuando añada elementos a su propio DOM. + - Cuando crees directivas que tengan sentido como elemento, restringe `E` (elemento personalizado) y opcionalmente restringe `A` (atributo personalizado). Generalmente, si puede ser su control propio, `E` es apropiado, La pauta general es permitir `EA` pero intenta implementarlo como un elemento cuando sea un elemento único y como un atributo cuando añada mejoras a su propio elemento existente en el DOM. *¿Por qué?*: Tiene sentido. - *¿Por qué?*: Mientras permitamos que una directiva sea usada como una clase, si esa directiva realmente estáa actuando como un elemento, tiene sentido que sea un elemento, o al menos un atributo. + *¿Por qué?*: Mientras permitamos que una directiva sea usada como una clase, si esa directiva realmente está actuando como un elemento, tiene sentido que sea un elemento, o al menos un atributo. Nota: En AngularJS 1.3+ EA es el valor por defecto @@ -1157,7 +1161,7 @@ Mientras que esta guía explica el *qué*, *por qué* y *cómo*, me resulta úti
``` - + ```javascript /* recomendado */ angular @@ -1178,18 +1182,18 @@ Mientras que esta guía explica el *qué*, *por qué* y *cómo*, me resulta úti } ``` -### Directives and ControllerAs +### Directivas y ControllerAs ###### [Style [Y075](#style-y075)] - - Usa la sintaxis `controller as` con una directiva para ser consistente con el uso de `controller as` con los pares de view y controller. + - Usa la sintaxis `controller as` con una directiva para ser consistente con el uso de `controller as` con los pares de vista y controlador. - *¿Por qué?*: Tiene sentido y no es dificil. + *¿Por qué?*: Tiene sentido y no es difícil. - Nota: La siguiente directiva demuestra algunas de las formas en las que puedes usar el scope dentro de un link y controllers de una directiva, usando controllerAs. He puesto la template para dejarlo todo en un lugar. + Nota: La siguiente directiva demuestra algunas de las formas en las que puedes usar el scope dentro del link y el controlador de una directiva, usando controllerAs. He puesto la template para dejarlo todo en un lugar. Nota: En cuanto a la inyección de dependencias, mira [Identificar Dependencias Manualmente](#manual-annotating-for-dependency-injection). - Nota: Nótese que la directiva controller está fuera del closure de la directiva. Este estilo elimina los problemas que genera la inyección de dependencias donde la inyección es creada en un código no alcanzable después del `return`. + Nota: Nótese que el controlador de la directiva está fuera del closure de la directiva. Este estilo elimina los problemas que genera la inyección de dependencias donde la inyección es creada en un código no alcanzable después del `return`. ```html
@@ -1210,7 +1214,7 @@ Mientras que esta guía explica el *qué*, *por qué* y *cómo*, me resulta úti link: linkFunc, controller: ExampleController, controllerAs: 'vm', - bindToController: true // because the scope is isolated + bindToController: true // porque el scope is aislado }; return directive; @@ -1226,7 +1230,7 @@ Mientras que esta guía explica el *qué*, *por qué* y *cómo*, me resulta úti ExampleController.$inject = ['$scope']; function ExampleController($scope) { - // Injecting $scope just for comparison + // Inyectando el $scope solo para comparación var vm = this; vm.min = 3; @@ -1249,9 +1253,9 @@ Mientras que esta guía explica el *qué*, *por qué* y *cómo*, me resulta úti - Usa `bindToController = true` cuando uses `controller as` con una directiva cuando quieras asociar el scope exterior al scope del controller de la directiva. - *¿Por qué?*: Lo hace más fácil a la hora de asociar el scope exterior al scope del controller de la directiva. + *¿Por qué?*: Lo hace más fácil a la hora de asociar el scope exterior al scope del controlador de la directiva. - Nota: `bindToController` fue introducido en Angular 1.3.0. + Nota: `bindToController` fue introducido en Angular 1.3.0. ```html
@@ -1294,19 +1298,19 @@ Mientras que esta guía explica el *qué*, *por qué* y *cómo*, me resulta úti **[Volver arriba](#table-of-contents)** -## Resolving Promises for a Controller +## Resolviendo Promesas en un Controlador -### Controller Activation Promises +### Promesas de Activación de un Controlador ###### [Style [Y080](#style-y080)] - - Resuelve la lógica de inicialización de un controller en una función `activate`. - - *¿Por qué?*: Colocar la lógica de inicialización en un lugar consistente del controller lo hace más fácil de localizar, más consistente de testear, y ayuda a evitar que la lógica de activación se propage a lo largo del controller. + - Resuelve la lógica de inicialización de un controlador en una función `activate`. + + *¿Por qué?*: Colocar la lógica de inicialización en un lugar consistente del controlador lo hace más fácil de localizar, más consistente de testear, y ayuda a evitar que la lógica de activación se propage a lo largo del controlador. - *¿Por qué?*: El controller `activate` hace que la lógica para refrescar el controller/View sea reutilizable, mantiene la lógica junta, proporciona al usuario la View más rápido, hace las animacines más fáciles en `ng-view` o `ui-view` y lo hace más rápido a la vista del usuario. + *¿Por qué?*: El `activate` del controlador hace que la lógica para refrescar el controlador/Vista sea reutilizable, mantiene la lógica junta, lleva el usuario a la Vista más rápido, hace las animaciones más fáciles en `ng-view` o `ui-view` y lo hace más rápido a la vista del usuario. Nota: Si necesitas condicionalmente cancelar la ruta antes de empezar el controller, usa en su lugar [route resolve](#style-y081). - + ```javascript /* evitar */ function Avengers(dataservice) { @@ -1341,18 +1345,18 @@ Mientras que esta guía explica el *qué*, *por qué* y *cómo*, me resulta úti } ``` -### Route Resolve Promises +### Resolución de Promesas en la Ruta ###### [Style [Y081](#style-y081)] - - Cuando un controller depende en una promesa a ser resuelta antes de que el controller se active, resuelve esas dependencias en el `$routeProvider` antes de que la lógica del controller sea ejecutada. Si necesitas condicionalmente cancelar una ruta antes de que el controller sea activado, usa un route resolver. + - Cuando un controlador depende en una promesa a ser resuelta antes de que el controlador se active, resuelve esas dependencias en el `$routeProvider` antes de que la lógica del controlador sea ejecutada. Si necesitas condicionalmente cancelar una ruta antes de que el controlador sea activado, usa un route resolver. - - Usa un route resolver cuando decidas cancelar la ruta antes de transicionar la View. + - Usa un route resolver cuando decidas cancelar la ruta antes de transicionar a la Vista. - *¿Por qué?*: Un controller puede requerir datos antes de que se cargue. Esos datos deben venir desde una promesa a través de una factory o de [$http](https://docs.angularjs.org/api/ng/service/$http). Using a [route resolve](https://docs.angularjs.org/api/ngRoute/provider/$routeProvider) permitiendo que la promesa se resuelva antes de que la lógica del controller se ejecute, así puedes tomar decisiones basándote en los datos de la promesa. + *¿Por qué?*: Un controlador puede requerir datos antes de que se cargue. Esos datos deben venir desde una promesa a través de una factory o de [$http](https://docs.angularjs.org/api/ng/service/$http). Usando un [route resolve](https://docs.angularjs.org/api/ngRoute/provider/$routeProvider) permite que la promesa se resuelva antes de que la lógica del controlador se ejecute, así puedes tomar decisiones basándote en los datos de la promesa. - *¿Por qué?*: El código se ejecuta después de la ruta y la función activate del controller. La View empieza a cargar al instante. Los Data binding se ejecutan cuando la promesa del activate se resuelva. Una animación de "Cargando" se puede mostrar mientras la transición de la view (via ng-view o ui-view) + *¿Por qué?*: El código se ejecuta después de la ruta y la función activate del controlador. La Vista empieza a cargar al instante. El bindeo de los datos se jecutan cuando la promesa del activate se resuelva. Una animación de "Cargando" se puede mostrar durante la transición de la vista (via ng-view o ui-view) - Nota: El código se ejecuta antes que la ruta mediante una promesa. Rechazar la promesa cancela la ruta. Resolverla hace que la nueva view espere a que la ruta sea resuelta. Una animación de "Cargando" puede ser mostrada antes de que se resuelva. Si quieres que la View aparezca más rápido y no necesitas un checkpoint para decidir si puedes mostrar o no la view, considera la técnica [controller `activate`](#style-y080). + Nota: El código se ejecuta antes que la ruta mediante una promesa. Rechazar la promesa cancela la ruta. Resolverla hace que la nueva vista espere a que la ruta sea resuelta. Una animación de "Cargando" puede ser mostrada antes de que se resuelva. Si quieres que la Vista aparezca más rápido y no necesitas un checkpoint para decidir si puedes mostrar o no la view, considera la técnica [controller `activate`](#style-y080). ```javascript /* evitar */ @@ -1362,9 +1366,9 @@ Mientras que esta guía explica el *qué*, *por qué* y *cómo*, me resulta úti function Avengers(movieService) { var vm = this; - // unresolved + // sin resolver vm.movies; - // resolved asynchronously + // resulta asincronamente movieService.getMovies().then(function(response) { vm.movies = response.movies; }); @@ -1405,7 +1409,7 @@ Mientras que esta guía explica el *qué*, *por qué* y *cómo*, me resulta úti } ``` - Nota: El siguiente ejemplo muestra una ruta que cuando se resuelve apunta a una función, haciéndolo más fácil de debugear y más fácil de manejar inyección de dependencias. + Nota: El siguiente ejemplo muestra una ruta que cuando se resuelve apunta a una función, haciéndolo más fácil de debugear y más fácil de manejar la inyección de dependencias. ```javascript /* even better */ @@ -1442,17 +1446,17 @@ Mientras que esta guía explica el *qué*, *por qué* y *cómo*, me resulta úti vm.movies = moviesPrepService.movies; } ``` - Nota: El código del ejemplo de dependencia en `movieService` no se puede minimizar tal cual. Para detalles en cómo hacer este código sea minimizable, mira la sección de [inyección de dependencias](#manual-annotating-for-dependency-injection) y en [minimización y anotación](#minification-and-annotation). + Nota: El código del ejemplo de dependencia en `movieService` no se puede minimizar tal cual. Para detalles en cómo hacer este código sea minimizable, mira la sección en [inyección de dependencias](#manual-annotating-for-dependency-injection) y en [minimización y anotación](#minification-and-annotation). **[Volver arriba](#table-of-contents)** -## Manual Annotating for Dependency Injection +## Anotación Manual para la Inyección de Dependencias -### UnSafe from Minification +### Insegura después de la Minificación ###### [Style [Y090](#style-y090)] - Evita usar la sintaxis acortada para declarar dependencias sin usar algún método que permita minimifación. - + *¿Por qué?*: Los parámetros al componente (e.g. controller, factory, etc) se convertirán en variables acortadas. Por ejemplo, `common` y `dataservice` se convertirán `a` o `b` y no serán encontradas por AngularJS. ```javascript @@ -1472,23 +1476,23 @@ Mientras que esta guía explica el *qué*, *por qué* y *cómo*, me resulta úti angular.module('app').controller('Dashboard', d);function d(a, b) { } ``` -### Manually Identify Dependencies +### Identifica Dependencias Manualmente ###### [Style [Y091](#style-y091)] - Usa `$inject` Para identificar manualmente las dependencias de tus componentes AngularJS. - + *¿Por qué?*: Esta técnica es la misma que se usa con [`ng-annotate`](https://github.com/olov/ng-annotate), la cuál recomiendo para automatizar la creación de dependencias minificadas de forma segura. Si `ng-annotate` detecta que la inyección ha sido hecha, no la duplicará. *¿Por qué?*: Esto salvaguarda tus dependencias de ser vulnerables de problemas a la hora de minimizar cuando los parámetros se acorten. Por ejemplo, `common` y `dataservice` se convertirán `a` o `b` y no serán encontradas por AngularJS. - *¿Por qué?*: Evita crear dependencias en la línea, ya que las listas largas pueden ser dificil de leer en el array. También puede ser confuso que el array es una serie de cadenas mientras que el último componente e suna función. + *¿Por qué?*: Evita crear dependencias en línea, ya que las listas largas pueden ser difícil de leer en el array. También puede ser confuso que el array sea una serie de cadenas mientras que el último componente es una función. ```javascript /* evitar */ angular .module('app') - .controller('Dashboard', - ['$location', '$routeParams', 'common', 'dataservice', + .controller('Dashboard', + ['$location', '$routeParams', 'common', 'dataservice', function Dashboard($location, $routeParams, common, dataservice) {} ]); ``` @@ -1497,9 +1501,9 @@ Mientras que esta guía explica el *qué*, *por qué* y *cómo*, me resulta úti /* evitar */ angular .module('app') - .controller('Dashboard', + .controller('Dashboard', ['$location', '$routeParams', 'common', 'dataservice', Dashboard]); - + function Dashboard($location, $routeParams, common, dataservice) { } ``` @@ -1516,7 +1520,7 @@ Mientras que esta guía explica el *qué*, *por qué* y *cómo*, me resulta úti } ``` - Nota: Cuando tu función está debajo de un return, $inject puede ser inalcanzable (esto puede pasar en una directiva). Puedes solucionarlo moviendo el $inject encima del return o usando la sintaxis de array para inyectar.by either moving the $inject above the return statement or by using the alternate array injection syntax. + Nota: Cuando tu función está debajo de un return, $inject puede ser inalcanzable (esto puede pasar en una directiva). Puedes solucionarlo moviendo el $inject encima del return o usando la sintaxis de array para inyectar. Nota: [`ng-annotate 0.10.0`](https://github.com/olov/ng-annotate) introduce una funcionalidad donde mueve `$inject` donde es alcanzable. @@ -1583,10 +1587,10 @@ Mientras que esta guía explica el *qué*, *por qué* y *cómo*, me resulta úti ###### [Style [Y100](#style-y100)] - Use [ng-annotate](//github.com/olov/ng-annotate) for [Gulp](http://gulpjs.com) or [Grunt](http://gruntjs.com) and comment functions that need automated dependency injection using `/** @ngInject */` - + *¿Por qué?*: This safeguards your code from any dependencies that may not be using minification-safe practices. - *¿Por qué?*: [`ng-min`](https://github.com/btford/ngmin) is deprecated + *¿Por qué?*: [`ng-min`](https://github.com/btford/ngmin) is deprecated >I prefer Gulp as I feel it is easier to write, to read, and to debug. @@ -1660,7 +1664,7 @@ Mientras que esta guía explica el *qué*, *por qué* y *cómo*, me resulta úti ###### [Style [Y101](#style-y101)] - Use [gulp-ng-annotate](https://www.npmjs.org/package/gulp-ng-annotate) or [grunt-ng-annotate](https://www.npmjs.org/package/grunt-ng-annotate) in an automated build task. Inject `/* @ngInject */` prior to any function that has dependencies. - + *¿Por qué?*: ng-annotate will catch most dependencies, but it sometimes requires hints using the `/* @ngInject */` syntax. The following code is an example of a gulp task using ngAnnotate @@ -1694,7 +1698,7 @@ Mientras que esta guía explica el *qué*, *por qué* y *cómo*, me resulta úti ###### [Style [Y110](#style-y110)] - Use a [decorator](https://docs.angularjs.org/api/auto/service/$provide#decorator), at config time using the [`$provide`](https://docs.angularjs.org/api/auto/service/$provide) service, on the [`$exceptionHandler`](https://docs.angularjs.org/api/ng/service/$exceptionHandler) service to perform custom actions when exceptions occur. - + *¿Por qué?*: Provides a consistent way to handle uncaught AngularJS exceptions for development-time or run-time. Nota: Another option is to override the service instead of using a decorator. This is a fine option, but if you want to keep the default behavior and extend it a decorator is recommended. @@ -1716,9 +1720,9 @@ Mientras que esta guía explica el *qué*, *por qué* y *cómo*, me resulta úti function extendExceptionHandler($delegate, toastr) { return function(exception, cause) { $delegate(exception, cause); - var errorData = { - exception: exception, - cause: cause + var errorData = { + exception: exception, + cause: cause }; /** * Could add the error to a service's collection, @@ -1804,10 +1808,10 @@ Mientras que esta guía explica el *qué*, *por qué* y *cómo*, me resulta úti - Use consistent names for all components following a pattern that describes the component's feature then (optionally) its type. My recommended pattern is `feature.type.js`. There are 2 names for most assets: * the file name (`avengers.controller.js`) * the registered component name with Angular (`AvengersController`) - + *¿Por qué?*: Naming conventions help provide a consistent way to find content at a glance. Consistency within the project is vital. Consistency with a team is important. Consistency across a company provides tremendous efficiency. - *¿Por qué?*: The naming conventions should simply help you find your code faster and make it easier to understand. + *¿Por qué?*: The naming conventions should simply help you find your code faster and make it easier to understand. ### Feature File Names ###### [Style [Y121](#style-y121)] @@ -1820,7 +1824,7 @@ Mientras que esta guía explica el *qué*, *por qué* y *cómo*, me resulta úti ```javascript /** - * common options + * common options */ // Controllers @@ -1849,7 +1853,7 @@ Mientras que esta guía explica el *qué*, *por qué* y *cómo*, me resulta úti // constants constants.js - + // module definition avengers.module.js @@ -1859,7 +1863,7 @@ Mientras que esta guía explica el *qué*, *por qué* y *cómo*, me resulta úti // configuration avengers.config.js - + // directives avenger-profile.directive.js avenger-profile.directive.spec.js @@ -1997,7 +2001,7 @@ Mientras que esta guía explica el *qué*, *por qué* y *cómo*, me resulta úti ### Modules ###### [Style [Y127](#style-y127)] - - When there are multiple modules, the main module file is named `app.module.js` while other dependent modules are named after what they represent. For example, an admin module is named `admin.module.js`. The respective registered module names would be `app` and `admin`. + - When there are multiple modules, the main module file is named `app.module.js` while other dependent modules are named after what they represent. For example, an admin module is named `admin.module.js`. The respective registered module names would be `app` and `admin`. *¿Por qué?*: Provides consistency for multiple module apps, and for expanding to large applications. @@ -2015,7 +2019,7 @@ Mientras que esta guía explica el *qué*, *por qué* y *cómo*, me resulta úti ### Routes ###### [Style [Y129](#style-y129)] - - Separate route configuration into its own file. Examples might be `app.route.js` for the main module and `admin.route.js` for the `admin` module. Even in smaller apps I prefer this separation from the rest of the configuration. + - Separate route configuration into its own file. Examples might be `app.route.js` for the main module and `admin.route.js` for the `admin` module. Even in smaller apps I prefer this separation from the rest of the configuration. **[Volver arriba](#table-of-contents)** @@ -2023,12 +2027,12 @@ Mientras que esta guía explica el *qué*, *por qué* y *cómo*, me resulta úti ### LIFT ###### [Style [Y140](#style-y140)] - - Structure your app such that you can `L`ocate your code quickly, `I`dentify the code at a glance, keep the `F`lattest structure you can, and `T`ry to stay DRY. The structure should follow these 4 basic guidelines. + - Structure your app such that you can `L`ocate your code quickly, `I`dentify the code at a glance, keep the `F`lattest structure you can, and `T`ry to stay DRY. The structure should follow these 4 basic guidelines. *Why LIFT?*: Provides a consistent structure that scales well, is modular, and makes it easier to increase developer efficiency by finding code quickly. Another way to check your app structure is to ask yourself: How quickly can you open and work in all of the related files for a feature? When I find my structure is not feeling comfortable, I go back and revisit these LIFT guidelines - + 1. `L`ocating our code is easy 2. `I`dentify code at a glance 3. `F`lat structure as long as we can @@ -2078,7 +2082,7 @@ Mientras que esta guía explica el *qué*, *por qué* y *cómo*, me resulta úti - Be DRY, but don't go nuts and sacrifice readability. - *¿Por qué?*: Being DRY is important, but not crucial if it sacrifices the others in LIFT, which is why I call it T-DRY. I don’t want to type session-view.html for a view because, well, it’s obviously a view. If it is not obvious or by convention, then I name it. + *¿Por qué?*: Being DRY is important, but not crucial if it sacrifices the others in LIFT, which is why I call it T-DRY. I don’t want to type session-view.html for a view because, well, it’s obviously a view. If it is not obvious or by convention, then I name it. **[Volver arriba](#table-of-contents)** @@ -2094,16 +2098,16 @@ Mientras que esta guía explica el *qué*, *por qué* y *cómo*, me resulta úti ### Layout ###### [Style [Y151](#style-y151)] - - Place components that define the overall layout of the application in a folder named `layout`. These may include a shell view and controller may act as the container for the app, navigation, menus, content areas, and other regions. + - Place components that define the overall layout of the application in a folder named `layout`. These may include a shell view and controller may act as the container for the app, navigation, menus, content areas, and other regions. *¿Por qué?*: Organizes all layout in a single place re-used throughout the application. ### Folders-by-Feature Structure ###### [Style [Y152](#style-y152)] - - Create folders named for the feature they represent. When a folder grows to contain more than 7 files, start to consider creating a folder for them. Your threshold may be different, so adjust as needed. + - Create folders named for the feature they represent. When a folder grows to contain more than 7 files, start to consider creating a folder for them. Your threshold may be different, so adjust as needed. - *¿Por qué?*: A developer can locate the code, identify what each file represents at a glance, the structure is flat as can be, and there is no repetitive nor redundant names. + *¿Por qué?*: A developer can locate the code, identify what each file represents at a glance, the structure is flat as can be, and there is no repetitive nor redundant names. *¿Por qué?*: The LIFT guidelines are all covered. @@ -2154,12 +2158,12 @@ Mientras que esta guía explica el *qué*, *por qué* y *cómo*, me resulta úti Nota: Do not use structuring using folders-by-type. This requires moving to multiple folders when working on a feature and gets unwieldy quickly as the app grows to 5, 10 or 25+ views and controllers (and other features), which makes it more difficult than folder-by-feature to locate files. ```javascript - /* + /* * avoid * Alternative folders-by-type. * I recommend "folders-by-feature", instead. */ - + app/ app.module.js app.config.js @@ -2190,7 +2194,7 @@ Mientras que esta guía explica el *qué*, *por qué* y *cómo*, me resulta úti speakers.html speaker-detail.html topnav.html - ``` + ``` **[Volver arriba](#table-of-contents)** @@ -2217,7 +2221,7 @@ Mientras que esta guía explica el *qué*, *por qué* y *cómo*, me resulta úti *¿Por qué?*: Adding additional roles to the application root to get remote data, display views, or other logic not related to pulling the app together muddies the app module and make both sets of features harder to reuse or turn off. - *¿Por qué?*: The app module becomes a manifest that describes which modules help define the application. + *¿Por qué?*: The app module becomes a manifest that describes which modules help define the application. ### Feature Areas are Modules ###### [Style [Y163](#style-y163)] @@ -2228,7 +2232,7 @@ Mientras que esta guía explica el *qué*, *por qué* y *cómo*, me resulta úti *¿Por qué?*: Sprints or iterations can focus on feature areas and turn them on at the end of the sprint or iteration. - *¿Por qué?*: Separating feature areas into modules makes it easier to test the modules in isolation and reuse code. + *¿Por qué?*: Separating feature areas into modules makes it easier to test the modules in isolation and reuse code. ### Reusable Blocks are Modules ###### [Style [Y164](#style-y164)] @@ -2244,15 +2248,15 @@ Mientras que esta guía explica el *qué*, *por qué* y *cómo*, me resulta úti ![Modularity and Dependencies](https://raw.githubusercontent.com/johnpapa/angularjs-styleguide/master/assets/modularity-1.png) - *¿Por qué?*: The main app module contains a quickly identifiable manifest of the application's features. + *¿Por qué?*: The main app module contains a quickly identifiable manifest of the application's features. - *¿Por qué?*: Each feature area contains a manifest of what it depends on, so it can be pulled in as a dependency in other applications and still work. + *¿Por qué?*: Each feature area contains a manifest of what it depends on, so it can be pulled in as a dependency in other applications and still work. *¿Por qué?*: Intra-App features such as shared data services become easy to locate and share from within `app.core` (choose your favorite name for this module). Nota: This is a strategy for consistency. There are many good options here. Choose one that is consistent, follows AngularJS's dependency rules, and is easy to maintain and scale. - > My structures vary slightly between projects but they all follow these guidelines for structure and modularity. The implementation may vary depending on the features and the team. In other words, don't get hung up on an exact like-for-like structure but do justify your structure using consistency, maintainability, and efficiency in mind. + > My structures vary slightly between projects but they all follow these guidelines for structure and modularity. The implementation may vary depending on the features and the team. In other words, don't get hung up on an exact like-for-like structure but do justify your structure using consistency, maintainability, and efficiency in mind. > In a small app, you can also consider putting all the shared dependencies in the app module where the feature modules have no direct dependencies. This makes it easier to maintain the smaller application, but makes it harder to reuse modules outside of this application. @@ -2272,7 +2276,7 @@ Mientras que esta guía explica el *qué*, *por qué* y *cómo*, me resulta úti .module('app') .config(configure); - configure.$inject = + configure.$inject = ['routerHelperProvider', 'exceptionHandlerProvider', 'toastr']; function configure (routerHelperProvider, exceptionHandlerProvider, toastr) { @@ -2398,14 +2402,14 @@ Unit testing helps maintain clean code, as such I included some of my recommenda - Use [PhantomJS](http://phantomjs.org/) to run your tests on a server. - *¿Por qué?*: PhantomJS is a headless browser that helps run your tests without needing a "visual" browser. So you do not have to install Chrome, Safari, IE, or other browsers on your server. + *¿Por qué?*: PhantomJS is a headless browser that helps run your tests without needing a "visual" browser. So you do not have to install Chrome, Safari, IE, or other browsers on your server. Nota: You should still test on all browsers in your environment, as appropriate for your target audience. ### Code Analysis ###### [Style [Y195](#style-y195)] - - Run JSHint on your tests. + - Run JSHint on your tests. *¿Por qué?*: Tests are code. JSHint can help identify code quality issues that may cause the test to work improperly. @@ -2427,7 +2431,7 @@ Unit testing helps maintain clean code, as such I included some of my recommenda - Place unit test files (specs) side-by-side with your client code. Place specs that cover server integration or test multiple components in a separate `tests` folder. - *¿Por qué?*: Unit tests have a direct correlation to a specific component and file in source code. + *¿Por qué?*: Unit tests have a direct correlation to a specific component and file in source code. *¿Por qué?*: It is easier to keep them up to date since they are always in sight. When coding whether you do TDD or test during development or test after development, the specs are side-by-side and never out of sight nor mind, and thus more likely to be maintained which also helps maintain code coverage. @@ -2465,7 +2469,7 @@ Unit testing helps maintain clean code, as such I included some of my recommenda ### Sub Second ###### [Style [Y211](#style-y211)] - - Use short durations for animations. I generally start with 300ms and adjust until appropriate. + - Use short durations for animations. I generally start with 300ms and adjust until appropriate. *¿Por qué?*: Long animations can have the reverse affect on User Experience and perceived performance by giving the appearance of a slow application. @@ -2521,7 +2525,7 @@ Unit testing helps maintain clean code, as such I included some of my recommenda /** * @name logError * @desc Logs errors - * @param {String} msg Message to log + * @param {String} msg Message to log * @returns {String} * @memberOf Factories.Logger */ @@ -2635,7 +2639,7 @@ Unit testing helps maintain clean code, as such I included some of my recommenda .constant('moment', moment); })(); ``` - + ###### [Style [Y241](#style-y241)] - Use constants for values that do not change and do not come from another service. When constants are used only for a module that may be reused in multiple applications, place constants in a file per module named after the module. Until this is required, keep constants in the main module in a `constants.js` file. @@ -2644,7 +2648,7 @@ Unit testing helps maintain clean code, as such I included some of my recommenda *¿Por qué?*: Constants can be injected into any angular component, including providers. - *¿Por qué?*: When an application is separated into modules that may be reused in other applications, each stand-alone module should be able to operate on its own including any dependent constants. + *¿Por qué?*: When an application is separated into modules that may be reused in other applications, each stand-alone module should be able to operate on its own including any dependent constants. ```javascript // Constants used by the entire app @@ -2669,13 +2673,13 @@ Use file templates or snippets to help follow consistent styles and patterns. He ### Sublime Text ###### [Style [Y250](#style-y250)] - - AngularJS snippets that follow these styles and guidelines. + - AngularJS snippets that follow these styles and guidelines. - - Download the [Sublime Angular snippets](assets/sublime-angular-snippets.zip?raw=true) + - Download the [Sublime Angular snippets](assets/sublime-angular-snippets.zip?raw=true) - Place it in your Packages folder - - Restart Sublime + - Restart Sublime - In a JavaScript file type these commands followed by a `TAB` - + ```javascript ngcontroller // creates an Angular controller ngdirective // creates an Angular directive @@ -2697,7 +2701,7 @@ Use file templates or snippets to help follow consistent styles and patterns. He - AngularJS snippets and file templates that follow these styles and guidelines. You can import them into your WebStorm settings: - - Download the [WebStorm AngularJS file templates and snippets](assets/webstorm-angular-file-template.settings.jar?raw=true) + - Download the [WebStorm AngularJS file templates and snippets](assets/webstorm-angular-file-template.settings.jar?raw=true) - Open WebStorm and go to the `File` menu - Choose the `Import Settings` menu option - Select the file and click `OK` @@ -2793,7 +2797,7 @@ Open an issue first to discuss potential changes/additions. If you have question *By contributing to this repository you are agreeing to make your content available subject to the license of this repository.* ### Process - 1. Discuss the changes in a GitHub issue. + 1. Discuss the changes in a GitHub issue. 2. Open a Pull Request against the develop branch, reference the issue, and explain the change and why it adds value. 3. The Pull Request will be evaluated and either merged or declined. From 68d6604353c1593e45ff2fcc5b14632f8121e0ba Mon Sep 17 00:00:00 2001 From: Gilberto Villa Date: Wed, 25 Feb 2015 09:52:08 -0600 Subject: [PATCH 198/567] Add more :es: translations --- i18n/es-ES.md | 646 +++++++++++++++++++++++++------------------------- 1 file changed, 326 insertions(+), 320 deletions(-) diff --git a/i18n/es-ES.md b/i18n/es-ES.md index a144c997..cf787bf7 100644 --- a/i18n/es-ES.md +++ b/i18n/es-ES.md @@ -6,20 +6,20 @@ Si estás buscando una guía colaborativa sobre sintaxis, convenciones y estruct El propósito de esta guía de estilos es proporcionar una guía de cómo construir aplicaciones con AngularJS enseñando convenciones que uso y, lo más importante, el porqué. ->Si te gusta esta guía, écha un vistazo al curso de Pluralsight [AngularJS Patterns: Clean Code](http://jpapa.me/ngclean). +>Si te gusta esta guía, echa un vistazo al curso de Pluralsight [AngularJS Patterns: Clean Code](http://jpapa.me/ngclean). [![AngularJs Patterns: Clean Code](https://raw.githubusercontent.com/johnpapa/angularjs-styleguide/master/assets/ng-clean-code-banner.png)](http://jpapa.me/ngclean) ## Asombrosa comunidad y créditos -Nunca trabajes solo. Personalmente, la comunidad de AngularJS es un increíble grupo apasionado por compartir experiencias. Como por ejemplo, mi amigo y experto en AngularJS Todd Motto, con el que he colaborado en muchos de los estilos y convenciones. Estamos de acuerdo en la mayoría, y en otras no. Te recomiendo que le eches un vistazo a [Todd's guidelines](https://github.com/toddmotto/angularjs-styleguide) para que le des sentido a ésta guía y la compares. +Nunca trabajes solo. Personalmente, la comunidad de AngularJS es un increíble grupo apasionado por compartir experiencias. Como por ejemplo, mi amigo y experto en AngularJS Todd Motto, con el que he colaborado en muchos de los estilos y convenciones. Estamos de acuerdo en la mayoría, y en otras no. Te recomiendo que le eches un vistazo a [Todd's guidelines](https://github.com/toddmotto/angularjs-styleguide) para que le des sentido a esta guía y la compares. -Muchos de los estilos han salido de las muchas sesiones de pair programming que [Ward Bell](http://twitter.com/wardbell) y yo hemos tenido. Aunque no siempre coincidimos, mi amigo Ward me ha ayudado con la última evolución de ésta guía. +Muchos de los estilos han salido de las muchas sesiones de pair programming que [Ward Bell](http://twitter.com/wardbell) y yo hemos tenido. Aunque no siempre coincidimos, mi amigo Ward me ha ayudado con la última evolución de esta guía. ## Mira los estilos en la aplicación de ejemplo -Mientras que esta guía explica el *qué*, *por qué* y *cómo*, me resulta útil verlos en práctica. Ésta guía viene acompañada de una aplicación de ejemplo que sigue los estilos y patrones. La puedes encontrar en [aplicación de ejemplo (llamada modular) aquí](https://github.com/johnpapa/ng-demos) dentro del directorio `modular`. Siéntete libre de cogerla, hacerle clone o un fork. [Instrucciones de cómo arrancarla en su readme](https://github.com/johnpapa/ng-demos/tree/master/modular). +Mientras que esta guía explica el *qué*, *por qué* y *cómo*, me resulta útil verlos en práctica. Esta guía viene acompañada de una aplicación de ejemplo que sigue los estilos y patrones. La puedes encontrar en [aplicación de ejemplo (llamada modular) aquí](https://github.com/johnpapa/ng-demos) dentro del directorio `modular`. Siéntete libre de cogerla, hacerle clone o un fork. [Instrucciones de cómo arrancarla en su readme](https://github.com/johnpapa/ng-demos/tree/master/modular). ## Traducciones -[Traducciones de ésta guía de estilos Angular](https://github.com/johnpapa/angularjs-styleguide/tree/master/i18n) son mantenidas por la comunidad y las puedes encontrar aquí. +[Traducciones de esta guía de estilos Angular](https://github.com/johnpapa/angularjs-styleguide/tree/master/i18n) son mantenidas por la comunidad y las puedes encontrar aquí. ## Tabla de contenidos @@ -31,28 +31,28 @@ Mientras que esta guía explica el *qué*, *por qué* y *cómo*, me resulta úti 1. [Factories](#factories) 1. [Data Services](#data-services) 1. [Directivas](#directives) - 1. [Resolving Promises for a Controller](#resolving-promises-for-a-controller) - 1. [Manual Annotating for Dependency Injection](#manual-annotating-for-dependency-injection) + 1. [Resolviendo Promesas en un Controlador](#resolving-promises-for-a-controller) + 1. [Anotación Manual para Inyección de Dependencias](#manual-annotating-for-dependency-injection) 1. [Minification and Annotation](#minification-and-annotation) - 1. [Exception Handling](#exception-handling) - 1. [Naming](#naming) - 1. [Application Structure LIFT Principle](#application-structure-lift-principle) - 1. [Application Structure](#application-structure) - 1. [Modularity](#modularity) - 1. [Startup Logic](#startup-logic) - 1. [Angular $ Wrapper Services](#angular--wrapper-services) - 1. [Testing](#testing) - 1. [Animations](#animations) - 1. [Comments](#comments) + 1. [Manejo de Excepciones](#exception-handling) + 1. [Cómo Nombrar](#naming) + 1. [Estructura de la Aplicación El Principio LIFT](#application-structure-lift-principle) + 1. [Estructura de la Aplicación](#application-structure) + 1. [Modularidad](#modularity) + 1. [Lógica de Arranque](#startup-logic) + 1. [Servicios Envoltorios $ de Angular](#angular--wrapper-services) + 1. [Pruebas](#testing) + 1. [Animaciones](#animations) + 1. [Comentarios](#comments) 1. [JSHint](#js-hint) - 1. [Constants](#constants) - 1. [File Templates and Snippets](#file-templates-and-snippets) - 1. [Yeoman Generator](#yeoman-generator) - 1. [Routing](#routing) - 1. [Task Automation](#task-automation) + 1. [Constantes](#constants) + 1. [Plantillas y Snippets](#file-templates-and-snippets) + 1. [Generador de Yeoman](#yeoman-generator) + 1. [Ruteo](#routing) + 1. [Automatización de Tareas](#task-automation) 1. [AngularJS Docs](#angularjs-docs) - 1. [Contributing](#contributing) - 1. [License](#license) + 1. [Contribuyendo](#contributing) + 1. [Licencia](#license) ## Single Responsibility o Responsabilidad Única @@ -1550,14 +1550,14 @@ Mientras que esta guía explica el *qué*, *por qué* y *cómo*, me resulta úti } ``` -### Manually Identify Route Resolver Dependencies +### Identifica Manualmente Dependencias del Route Resolver ###### [Style [Y092](#style-y092)] - - Use $inject to manually identify your route resolver dependencies for AngularJS components. + - Usa $inject para identificar manualmente las dependencias de tu route resolver para componentes de AngularJS. - *¿Por qué?*: This technique breaks out the anonymous function for the route resolver, making it easier to read. + *¿Por qué?*: Esta técnica separa la función anónima para el route resolver, haciendola más fácil de leer. - *¿Por qué?*: An `$inject` statement can easily precede the resolver to handle making any dependencies minification safe. + *¿Por qué?*: Una declaración `$inject` puede ser fácilmente preceder al route resolver para hacer cualquier minificación de dependencias segura. ```javascript /* recomendado */ @@ -1581,20 +1581,20 @@ Mientras que esta guía explica el *qué*, *por qué* y *cómo*, me resulta úti **[Volver arriba](#table-of-contents)** -## Minification and Annotation +## Minificación y Anotación ### ng-annotate ###### [Style [Y100](#style-y100)] - - Use [ng-annotate](//github.com/olov/ng-annotate) for [Gulp](http://gulpjs.com) or [Grunt](http://gruntjs.com) and comment functions that need automated dependency injection using `/** @ngInject */` + - Usa [ng-annotate](//github.com/olov/ng-annotate) para [Gulp](http://gulpjs.com) or [Grunt](http://gruntjs.com) y comenta funciones que necesiten inyección de dependencias automatizadas usando `/** @ngInject */` - *¿Por qué?*: This safeguards your code from any dependencies that may not be using minification-safe practices. + *¿Por qué?*: Salvaguarda tu código de cualquier dependencia que pueda no estar usando prácticas de minificación segura. - *¿Por qué?*: [`ng-min`](https://github.com/btford/ngmin) is deprecated + *¿Por qué?*: [`ng-min`](https://github.com/btford/ngmin) está obsoleto - >I prefer Gulp as I feel it is easier to write, to read, and to debug. + >Yo prefiero Gulp porque siento que es más fácil de escribir, leer, y debugear. - The following code is not using minification safe dependencies. + El siguiente código no está usando minificación de dependencias segura. ```javascript angular @@ -1614,7 +1614,7 @@ Mientras que esta guía explica el *qué*, *por qué* y *cómo*, me resulta úti } ``` - When the above code is run through ng-annotate it will produce the following output with the `$inject` annotation and become minification-safe. + Cuando el código de arriba es ejecutado a través de ng-annotate producirá la siguiente salida con la anotación `$inject` y será seguro para ser minificado. ```javascript angular @@ -1636,9 +1636,9 @@ Mientras que esta guía explica el *qué*, *por qué* y *cómo*, me resulta úti Avengers.$inject = ['storageService', 'avengerService']; ``` - Nota: If `ng-annotate` detects injection has already been made (e.g. `@ngInject` was detected), it will not duplicate the `$inject` code. + Nota: Si `ng-annotate` detecta que la inyección ya ha sido hecha (e.g. `@ngInject` fué detectado), no duplicará el código de `$inject`. - Nota: When using a route resolver you can prefix the resolver's function with `/* @ngInject */` and it will produce properly annotated code, keeping any injected dependencies minification safe. + Nota: Al usar un route resolver puedes prefijar a la función del resolver con `/* @ngInject */` y producirá código propiamente anotado, manteniendo cualquier inyección de dependencias segura para ser minificada. ```javascript // Using @ngInject annotations @@ -1657,17 +1657,18 @@ Mientras que esta guía explica el *qué*, *por qué* y *cómo*, me resulta úti } ``` - > Nota: Starting from AngularJS 1.3 use the [`ngApp`](https://docs.angularjs.org/api/ng/directive/ngApp) directive's `ngStrictDi` parameter. When present the injector will be created in "strict-di" mode causing the application to fail to invoke functions which do not use explicit function annotation (these may not be minification safe). Debugging info will be logged to the console to help track down the offending code. + > Nota: A partir de AngularJS 1.3 usa el párametro `ngStrictDi` de la directiva [`ngApp`](https://docs.angularjs.org/api/ng/directive/ngApp). Al presentarse el injector será creado en modo "strict-di" causando que la aplicación falle al invocar funciones que no usan explícitamente anotación de funciones (éstas podrían no estar minificadas en forma segura). Información para debugear será mostrada en la consola para ayudar a rastrear el código infractor. `` -### Use Gulp or Grunt for ng-annotate +### Usa Gulp o Grunt para ng-annotate ###### [Style [Y101](#style-y101)] - - Use [gulp-ng-annotate](https://www.npmjs.org/package/gulp-ng-annotate) or [grunt-ng-annotate](https://www.npmjs.org/package/grunt-ng-annotate) in an automated build task. Inject `/* @ngInject */` prior to any function that has dependencies. + - Usa [gulp-ng-annotate](https://www.npmjs.org/package/gulp-ng-annotate) o [grunt-ng-annotate](https://www.npmjs.org/package/grunt-ng-annotate) en una tarea de construcción automática. Inyecta `/* @ngInject */` antes de cualquier función que tenga dependecias. - *¿Por qué?*: ng-annotate will catch most dependencies, but it sometimes requires hints using the `/* @ngInject */` syntax. + *¿Por qué?*: ng-annotate atrapará la mayoría de las dependecias, pero algunas veces requiere indicios usando la sintaxis `/* @ngInject */`. - The following code is an example of a gulp task using ngAnnotate + El código siguiente es un ejemplo de una tarea de Gulp que usa + ngAnnotate ```javascript gulp.task('js', ['jshint'], function() { @@ -1675,10 +1676,10 @@ Mientras que esta guía explica el *qué*, *por qué* y *cómo*, me resulta úti return gulp.src(source) .pipe(sourcemaps.init()) .pipe(concat('all.min.js', {newLine: ';'})) - // Annotate before uglify so the code get's min'd properly. + // Agrega la notación antes de ofuscar para que el código sea minificicado apropiadamente. .pipe(ngAnnotate({ - // true helps add where @ngInject is not used. It infers. - // Doesn't work with resolve, so we must be explicit there + // true ayuda a añadir @ngInject donde no es usado. Infiere. + // No funciona con resolve, así que tenemos que ser explícitos en ese caso add: true })) .pipe(bytediff.start()) @@ -1692,16 +1693,16 @@ Mientras que esta guía explica el *qué*, *por qué* y *cómo*, me resulta úti **[Volver arriba](#table-of-contents)** -## Exception Handling +## Manejo de Excepciones ### decorators ###### [Style [Y110](#style-y110)] - - Use a [decorator](https://docs.angularjs.org/api/auto/service/$provide#decorator), at config time using the [`$provide`](https://docs.angularjs.org/api/auto/service/$provide) service, on the [`$exceptionHandler`](https://docs.angularjs.org/api/ng/service/$exceptionHandler) service to perform custom actions when exceptions occur. + - Usa un [decorator](https://docs.angularjs.org/api/auto/service/$provide#decorator), en tiempo de configuración usando el servicio [`$provide`](https://docs.angularjs.org/api/auto/service/$provide), en el servicio [`$exceptionHandler`](https://docs.angularjs.org/api/ng/service/$exceptionHandler) para realizar acciones personalizadas cuando una excepción ocurra. - *¿Por qué?*: Provides a consistent way to handle uncaught AngularJS exceptions for development-time or run-time. + *¿Por qué?*: Provee una manera consistente de manejar excepciones de AngularJS que no están siendo capturadas en tiempo de desarrollo o en tiempo de ejecución. - Nota: Another option is to override the service instead of using a decorator. This is a fine option, but if you want to keep the default behavior and extend it a decorator is recommended. + Nota: Otra opción es sobreescribir el servicio en lugar de usar un decorator. Esto está bien, pero si quiere mantener el comportamiento por default y extenderlo se recomienda usar un decorator. ```javascript /* recomendado */ @@ -1725,24 +1726,25 @@ Mientras que esta guía explica el *qué*, *por qué* y *cómo*, me resulta úti cause: cause }; /** - * Could add the error to a service's collection, - * add errors to $rootScope, log errors to remote web server, - * or log locally. Or throw hard. It is entirely up to you. - * throw exception; + * Pudieramos agregar el error a la colección de un servicio, + * agregar los errores en el $rootScope, + * logear los errores a un servidor remoto, + * o logear localmente. O arrojarlos llanamente. Dependende totalmente de tí. + * arrojar excepción; */ toastr.error(exception.msg, errorData); }; } ``` -### Exception Catchers +### Cachadores de Excepciones ###### [Style [Y111](#style-y111)] - - Create a factory that exposes an interface to catch and gracefully handle exceptions. + - Crea una factory que exponga una interfaz para cachar y manejar excepciones elegantemente. - *¿Por qué?*: Provides a consistent way to catch exceptions that may be thrown in your code (e.g. during XHR calls or promise failures). + *¿Por qué?*: Provee de una manera consistente de cachar excepciones que puedan ser arrojadas en tu código (e.g. durante llamadas XHR o promesas que fallaron). - Nota: The exception catcher is good for catching and reacting to specific exceptions from calls that you know may throw one. For example, when making an XHR call to retrieve data from a remote web service and you want to catch any exceptions from that service and react uniquely. + Nota: El cachador de excepciones es bueno para cachar y reaccionar a excepciones específicas de llamadas que tu sabes van a arrojar una. Por ejemplo, al hacer una llamada XHR para obtener datos desde un servicio web remoto y quieres cachar cualquier excepción de ese servicio y reaccionar únicamente. ```javascript /* recomendado */ @@ -1766,22 +1768,24 @@ Mientras que esta guía explica el *qué*, *por qué* y *cómo*, me resulta úti } ``` -### Route Errors +### Errores de Ruta ###### [Style [Y112](#style-y112)] - - Handle and log all routing errors using [`$routeChangeError`](https://docs.angularjs.org/api/ngRoute/service/$route#$routeChangeError). + - Maneja y logea todos los errors de ruteo usando [`$routeChangeError`](https://docs.angularjs.org/api/ngRoute/service/$route#$routeChangeError). - *¿Por qué?*: Provides a consistent way handle all routing errors. + *¿Por qué?*: Provee una manera consistente de manejar todos los + errores de ruteo. - *¿Por qué?*: Potentially provides a better user experience if a routing error occurs and you route them to a friendly screen with more details or recovery options. + *¿Por qué?*: Potencialmente provee una mejor experiencia de usuario si un error de ruteo ocurre y tu los redirijes a una pantalla amigable con más detalles u opciones de recuperación. ```javascript /* recomendado */ function handleRoutingErrors() { /** * Route cancellation: - * On routing error, go to the dashboard. - * Provide an exit clause if it tries to do it twice. + * Cancelación de la Ruta: + * En un error de ruteo, ir al dashboard. + * Proveer una cláusula de salida si trata de hacerlo dos veces. */ $rootScope.$on('$routeChangeError', function(event, current, previous, rejection) { @@ -1790,6 +1794,7 @@ Mientras que esta guía explica el *qué*, *por qué* y *cómo*, me resulta úti var msg = 'Error routing to ' + destination + '. ' + (rejection.msg || ''); /** * Optionally log using a custom service or $log. + * Opcionalmente logear usando un servicio personalizado o $log. * (Don't forget to inject custom service) */ logger.warning(msg, [current]); @@ -1800,39 +1805,39 @@ Mientras que esta guía explica el *qué*, *por qué* y *cómo*, me resulta úti **[Volver arriba](#table-of-contents)** -## Naming +## Cómo Nombrar -### Naming Guidelines +### Pautas para nombrar ###### [Style [Y120](#style-y120)] - - Use consistent names for all components following a pattern that describes the component's feature then (optionally) its type. My recommended pattern is `feature.type.js`. There are 2 names for most assets: - * the file name (`avengers.controller.js`) - * the registered component name with Angular (`AvengersController`) + - Usa nombres consistentes para todos los componentes siguiendo un patrón que describa las características del componente y después (opcionalmente) su tipo. Mi patrón recomendado es `feature.type.js`. Hay dos nombres para la mayoría de los assets: + * el nombre del archivo (`avengers.controller.js`) + * el nombre del componente registrado en Angular (`AvengersController`) - *¿Por qué?*: Naming conventions help provide a consistent way to find content at a glance. Consistency within the project is vital. Consistency with a team is important. Consistency across a company provides tremendous efficiency. + *¿Por qué?*: Las pautas de como nombrar nos ayudan a proveer una manera consistente para encontrar contenido en un vistazo. La Consistencia es vital dentro del proyecto. La Consistencia es importante dentro de un equipo. La Consistencia a lo largo de una compañía provee de una tremenda eficacia. - *¿Por qué?*: The naming conventions should simply help you find your code faster and make it easier to understand. + *¿Por qué?*: Las pautas para nombrar deberían simplemente ayudarte a encontrar tu código rápidamente y hacerlo más fácil de entender. -### Feature File Names +### Nombres de Archivo para Feature ###### [Style [Y121](#style-y121)] - - Use consistent names for all components following a pattern that describes the component's feature then (optionally) its type. My recommended pattern is `feature.type.js`. + - Usa nombres consistentes para todos los componentes siguiendo un patrón que describa el feature del componente y después (opcionalmente) su tipo. Mi patrón recomendado es `feature.type.js`. - *¿Por qué?*: Provides a consistent way to quickly identify components. + *¿Por qué?*: Provee de una manera consistente para identificar componentes rápidamente. - *¿Por qué?*: Provides pattern matching for any automated tasks. + *¿Por qué?*: Provee un patrón de coincidencia para tareas automatizadas. ```javascript /** - * common options + * opciones comunes */ - // Controllers + // Controladores avengers.js avengers.controller.js avengersController.js - // Services/Factories + // Servicios/Factories logger.js logger.service.js loggerService.js @@ -1840,58 +1845,58 @@ Mientras que esta guía explica el *qué*, *por qué* y *cómo*, me resulta úti ```javascript /** - * recommended + * recomendado */ // controllers avengers.controller.js avengers.controller.spec.js - // services/factories + // servicios/factories logger.service.js logger.service.spec.js - // constants + // constantes constants.js - // module definition + // definición de módulos avengers.module.js - // routes + // rutas avengers.routes.js avengers.routes.spec.js - // configuration + // configuración avengers.config.js - // directives + // directivas avenger-profile.directive.js avenger-profile.directive.spec.js ``` - Nota: Another common convention is naming controller files without the word `controller` in the file name such as `avengers.js` instead of `avengers.controller.js`. All other conventions still hold using a suffix of the type. Controllers are the most common type of component so this just saves typing and is still easily identifiable. I recommend you choose 1 convention and be consistent for your team. + Nota: Otra convención común es nombrar archivos de controladores sin la palabra `controller` en el archivo tal como `avengers.js` en lugar de `avengers.controller.js`. Todas las demás convenciones todavía usan un sufijo del tipo. Los Controladores son el tipo más común de componente así que esto nos ahorra escribir y aún es fácilmente identificable. Yo recomiendo que elijas 1 convención y seas consistente dentro de tu equipo. ```javascript /** - * recommended + * recomendado */ - // Controllers + // Controladores avengers.js avengers.spec.js ``` -### Test File Names +### Nombres de Archivos de Prueba ###### [Style [Y122](#style-y122)] - - Name test specifications similar to the component they test with a suffix of `spec`. + - Nombra especificaciones de pruebas de manera similar a la del componente que estan probando con un sufijo de `spec`. - *¿Por qué?*: Provides a consistent way to quickly identify components. + *¿Por qué?*: Provee de una manera consistente de idenficar componentes rápidamente. - *¿Por qué?*: Provides pattern matching for [karma](http://karma-runner.github.io/) or other test runners. + *¿Por qué?*: Provee de un patrón de coincidencia para [karma](http://karma-runner.github.io/) u otros test runners. ```javascript /** - * recommended + * recomendado */ avengers.controller.spec.js logger.service.spec.js @@ -1899,18 +1904,18 @@ Mientras que esta guía explica el *qué*, *por qué* y *cómo*, me resulta úti avenger-profile.directive.spec.js ``` -### Controller Names +### Nombres de Controladores ###### [Style [Y123](#style-y123)] - - Use consistent names for all controllers named after their feature. Use UpperCamelCase for controllers, as they are constructors. + - Usa nombres consistentes para todos los controladores nombrados a partir de lo que hacen. Usa UpperCamelCase para controladores, ya que son constructores. - *¿Por qué?*: Provides a consistent way to quickly identify and reference controllers. + *¿Por qué?*: Provee de una manera consistente de identificar y referenciar controladores rápidamente. - *¿Por qué?*: UpperCamelCase is conventional for identifying object that can be instantiated using a constructor. + *¿Por qué?*: UpperCamelCase es convencional para identificar objetos que pueden ser instanciados usando un constructor. ```javascript /** - * recommended + * recomendado */ // avengers.controller.js @@ -1921,18 +1926,19 @@ Mientras que esta guía explica el *qué*, *por qué* y *cómo*, me resulta úti function HeroAvengers() { } ``` -### Controller Name Suffix +### Sufijo para el Nombre del Controlador ###### [Style [Y124](#style-y124)] - - Append the controller name with the suffix `Controller` or with no suffix. Choose 1, not both. + - Agrega el sufijo `Controller` al nombre del controlador o déjalo sin + sufijo. Escoje 1, no uses ambos. - *¿Por qué?*: The `Controller` suffix is more commonly used and is more explicitly descriptive. + *¿Por qué?*: El sufijo `Controller` es usado más comúnmente y es más descriptivo explícitamente. - *¿Por qué?*: Omitting the suffix is more succinct and the controller is often easily identifiable even without the suffix. + *¿Por qué?*: Omitir el sufijo es más sucinto y el controlador es fácilmente identificable más seguido incluso sin el sufijo. ```javascript /** - * recommended: Option 1 + * recomendado: Opción 1 */ // avengers.controller.js @@ -1945,7 +1951,7 @@ Mientras que esta guía explica el *qué*, *por qué* y *cómo*, me resulta úti ```javascript /** - * recommended: Option 2 + * recomendado: Opción 2 */ // avengers.controller.js @@ -1956,16 +1962,16 @@ Mientras que esta guía explica el *qué*, *por qué* y *cómo*, me resulta úti function AvengersController() { } ``` -### Factory Names +### Nombres de Factories ###### [Style [Y125](#style-y125)] - - Use consistent names for all factories named after their feature. Use camel-casing for services and factories. + - Usa nombres consistentes para todas las factories nombradas a partir de lo que hacen. Usa camel-casing para los servicios y las factories. - *¿Por qué?*: Provides a consistent way to quickly identify and reference factories. + *¿Por qué?*: Provee una manera consistente de identificar y referenciar factories rápidamente. ```javascript /** - * recommended + * recomendado */ // logger.service.js @@ -1976,16 +1982,16 @@ Mientras que esta guía explica el *qué*, *por qué* y *cómo*, me resulta úti function logger() { } ``` -### Directive Component Names +### Nombres para Directivas ###### [Style [Y126](#style-y126)] - - Use consistent names for all directives using camel-case. Use a short prefix to describe the area that the directives belong (some example are company prefix or project prefix). + - Usa nombres consistentes para todas las directivas usando camel-case. Usa un prefijo corto para describir el área a la que la directiva pertenece (algunos ejemplos son un prefijo según la compañía o un prefijo según el proyecto). - *¿Por qué?*: Provides a consistent way to quickly identify and reference components. + *¿Por qué?*: Provee una manera consistente de identificar y referenciar componentes rápidamente. ```javascript /** - * recommended + * recomendado */ // avenger-profile.directive.js @@ -1993,57 +1999,57 @@ Mientras que esta guía explica el *qué*, *por qué* y *cómo*, me resulta úti .module .directive('xxAvengerProfile', xxAvengerProfile); - // usage is + // el uso es function xxAvengerProfile() { } ``` -### Modules +### Módulos ###### [Style [Y127](#style-y127)] - - When there are multiple modules, the main module file is named `app.module.js` while other dependent modules are named after what they represent. For example, an admin module is named `admin.module.js`. The respective registered module names would be `app` and `admin`. + - Cuando haya múltiples módulos, el archivo del módulo principal es nombrado `app.module.js` mientras que otros módulos que dependan de él son nombrados a partir de lo que ellos representan. Por ejemplo, un módulo de admin es nombrado `admin.module.js`. Los nombres de los módulos registrados serán respectivamente `app` y `admin`. - *¿Por qué?*: Provides consistency for multiple module apps, and for expanding to large applications. + *¿Por qué?*: Provee consistencia para múltiples módulos de aplicación, y para poder expandirse a aplicaciones más grandes. - *¿Por qué?*: Provides easy way to use task automation to load all module definitions first, then all other angular files (for bundling). + *¿Por qué?*: Provee una manera fácil de usar tareas automatizadas para cargar todas las definiciones de módulos primero, y luego todos los otros archivos de angular (agrupación). -### Configuration +### Configuración ###### [Style [Y128](#style-y128)] - - Separate configuration for a module into its own file named after the module. A configuration file for the main `app` module is named `app.config.js` (or simply `config.js`). A configuration for a module named `admin.module.js` is named `admin.config.js`. + - Separa la configuración de un módulo en un archivo propio nombrado a partir del nombre del módulo. Un archivo de configuración para el módulo principal de `app` es nombrado `app.config.js` (o simplemente `config.js`). La configuración para un módulo llamado `admin.module.js` es nombrada `admin.config.js`. - *¿Por qué?*: Separates configuration from module definition, components, and active code. + *¿Por qué?*: Separa la configuración de la definición del módulo, componentes y código activo. - *¿Por qué?*: Provides a identifiable place to set configuration for a module. + *¿Por qué?*: Provee un lugar identificable para establecer configuración para un módulo. -### Routes +### Rutas ###### [Style [Y129](#style-y129)] - - Separate route configuration into its own file. Examples might be `app.route.js` for the main module and `admin.route.js` for the `admin` module. Even in smaller apps I prefer this separation from the rest of the configuration. + - Separa la configuración de la ruta en un arhivo propio. Algunos ejemplos pueden ser `app.route.js` para el módulo principal y `admin.route.js` para el módulo admin `admin`. Incluso en aplicaciones pequeñas prefiero esta separación del resto de la configuración. **[Volver arriba](#table-of-contents)** -## Application Structure LIFT Principle +## Estructura de la Aplicación El Principio LIFT ### LIFT ###### [Style [Y140](#style-y140)] - - Structure your app such that you can `L`ocate your code quickly, `I`dentify the code at a glance, keep the `F`lattest structure you can, and `T`ry to stay DRY. The structure should follow these 4 basic guidelines. + - Estructura tu aplicación de tal manera que puedas Localizar (`L`ocate) tu código rápidamente, Identificar (`I`dentify) el código de un vistazo, mantener la estructura más plana (`F`lattest) que puedas, y Trata (`T`ry) de mantenerte DRY. La estructura debe de seguir estas 4 pautas básicas. - *Why LIFT?*: Provides a consistent structure that scales well, is modular, and makes it easier to increase developer efficiency by finding code quickly. Another way to check your app structure is to ask yourself: How quickly can you open and work in all of the related files for a feature? + *¿Por qué LIFT?*: Provee una estructura consistente que escala bien, es modular, y hace más fácil incrementar la eficiencia de los desarrolladores al encontrar código rápidamente. Otra manera de checar la estructura de tu aplicación es preguntarte a ti mismo: ¿Qué tan rápido puede abrir y trabajar en todos los arhivos relacionados a una feature? - When I find my structure is not feeling comfortable, I go back and revisit these LIFT guidelines + Cuando encuentro que mi estructura no se siente cómoda, regreso y revisito estas pautas LIFT - 1. `L`ocating our code is easy - 2. `I`dentify code at a glance - 3. `F`lat structure as long as we can - 4. `T`ry to stay DRY (Don’t Repeat Yourself) or T-DRY + 1. `L`ocating - Localizar nuestro código es fácil + 2. `I`dentify - Identificar código de un vistazo + 3. `F`lat - Estructura plana tanto como sea posible + 4. `T`ry - Tratar de mantenerse DRY (Don't Repeat Yourself) or T-DRY -### Locate +### Localizar ###### [Style [Y141](#style-y141)] - - Make locating your code intuitive, simple and fast. + - Has que la localizar tu código sea intuitivo, simple y rápido. - *¿Por qué?*: I find this to be super important for a project. If the team cannot find the files they need to work on quickly, they will not be able to work as efficiently as possible, and the structure needs to change. You may not know the file name or where its related files are, so putting them in the most intuitive locations and near each other saves a ton of time. A descriptive folder structure can help with this. + *¿Por qué?*: Encuentro que esto es super importante para un proyecto. Si el equipo no puede encontrar los archivos en los que necesita trabajar rápidamente, no podran trabajar tan eficientemente como sea posible, y la estructura necesita cambiar. Puede que no conozcas el nombre del archivo o donde están sus archivos relacionados, así que poniéndolos en las locaciones más intuitivas y cerca de los otros ahorra mucho tiempo. Una estructura de directorios descriptiva puede ayudar con esto. ``` /bower_components @@ -2063,61 +2069,61 @@ Mientras que esta guía explica el *qué*, *por qué* y *cómo*, me resulta úti .bower.json ``` -### Identify +### Identificar ###### [Style [Y142](#style-y142)] - - When you look at a file you should instantly know what it contains and represents. + - Cuando miras en un arhivo deberías saber instantáneamente qué contiene y qué representa. - *¿Por qué?*: You spend less time hunting and pecking for code, and become more efficient. If this means you want longer file names, then so be it. Be descriptive with file names and keeping the contents of the file to exactly 1 component. Avoid files with multiple controllers, multiple services, or a mixture. There are deviations of the 1 per file rule when I have a set of very small features that are all related to each other, they are still easily identifiable. + *¿Por qué?*: Gastas menos tiempo buscando y urgando por código, y es más eficiente. Si esto significa que quieres nombres de archivos más largos, entonces que así sea. Se descriptivo con los nombres de los archivos y mantén el contenido del arhivo a exactamente 1 componente. Evita archivos con múltiples controladores, o una mezcla. Hay excepciones a la regla de 1 por archivo cuando tengo un conjunto de pequeñas features que están relacionadas unas con otras, aún así son fácilmente identificables. -### Flat +### Estructura Plana ###### [Style [Y143](#style-y143)] - - Keep a flat folder structure as long as possible. When you get to 7+ files, begin considering separation. + - Mantén una estructura de directorios plana tanto como sea posible. Cuando llegues a un total de 7+ archivos, comienza a considerar separación. - *¿Por qué?*: Nobody wants to search 7 levels of folders to find a file. Think about menus on web sites … anything deeper than 2 should take serious consideration. In a folder structure there is no hard and fast number rule, but when a folder has 7-10 files, that may be time to create subfolders. Base it on your comfort level. Use a flatter structure until there is an obvious value (to help the rest of LIFT) in creating a new folder. + *¿Por qué?*: Nadie quiere buscar en 7 niveles de directorios por un arhivo. Piensa en los menús de los sitios web … cualquiera más profundo que 2 debería ser seriamente considerado. En una estructura de directorios no hay una regla dura o rápida en cuanto a un número, pero cuando un directorio tiene de 7 a 10 archivos, tal vez ese sea el momento para empezar a crear subdirectorios. Básate en tu nivel de confort. Usa una estructura más plana hasta que haya un valor obvio (para ayudar al resto de LIFT) en crear un nuevo directorio. -### T-DRY (Try to Stick to DRY) +### T-DRY (Try to Stick to DRY - Trata de Apegarte a DRY) ###### [Style [Y144](#style-y144)] - - Be DRY, but don't go nuts and sacrifice readability. + - Se DRY, pero no te vuelvas loco y sacrifiques legibilidad. - *¿Por qué?*: Being DRY is important, but not crucial if it sacrifices the others in LIFT, which is why I call it T-DRY. I don’t want to type session-view.html for a view because, well, it’s obviously a view. If it is not obvious or by convention, then I name it. + *¿Por qué?*: Ser DRY es importante, pero no crucial si sacrifica otras partes de LIFT, es por eso que lo llamo T-DRY. No quiero escribir session-view.html por una vista porque, obviamente es una vista. Si no es obvio o por convención, entonces la nombro así. **[Volver arriba](#table-of-contents)** -## Application Structure +## Estructura de la Aplicación -### Overall Guidelines +### Pautas Universales ###### [Style [Y150](#style-y150)] - - Have a near term view of implementation and a long term vision. In other words, start small and but keep in mind on where the app is heading down the road. All of the app's code goes in a root folder named `app`. All content is 1 feature per file. Each controller, service, module, view is in its own file. All 3rd party vendor scripts are stored in another root folder and not in the `app` folder. I didn't write them and I don't want them cluttering my app (`bower_components`, `scripts`, `lib`). + - Ten una visión de implementación de corto y largo plazo. En otras palabras, empieza con poco pero ten en mente hacia donde se dirige la aplicación. Todo el código de la aplicación va en el directorio raíz llamado `app`. Todo el contenido es separado en 1 feature por archivo. Cada controlador, servicio, módulo, vista tiene su propio archivo. Todos los vendor scripts de terceros son almacenados en otro directorio raíz y no en el directorio `app`. Si yo no lo escribí no los quiero saturando mi aplicación (`bower_components`, `scripts`, `lib`). - Nota: Find more details and reasoning behind the structure at [this original post on application structure](http://www.johnpapa.net/angular-app-structuring-guidelines/). + Nota: Encuentra más detalles y el razonamiento detrás de esta estructura en [este post original sobre la estructura de una aplicación](http://www.johnpapa.net/angular-app-structuring-guidelines/). ### Layout ###### [Style [Y151](#style-y151)] - - Place components that define the overall layout of the application in a folder named `layout`. These may include a shell view and controller may act as the container for the app, navigation, menus, content areas, and other regions. + - Coloca los componentes que definen el layout universal de la aplicación en un directorio llamado `layout`. Estos pueden incluir una vista caparazón y un controlador que actuen como un contenedor para la aplicación, navegación, menús, áreas de contenido, y otras regiones. - *¿Por qué?*: Organizes all layout in a single place re-used throughout the application. + *¿Por qué?*: Organiza todo el layout en un lugar único reusado a lo largo de la aplicación. -### Folders-by-Feature Structure +### Estructura de Carpetas-por-Feature ###### [Style [Y152](#style-y152)] - - Create folders named for the feature they represent. When a folder grows to contain more than 7 files, start to consider creating a folder for them. Your threshold may be different, so adjust as needed. + - Crea carpetas llamadas de acuerdo al feature que representan. Cuando un folder crezca para contener más de 7 archivos, comienza a considerar la creación de una carpeta para ellos. Tu límite puede ser diferente, así que ajusta de acuerdo a tus necesidades. - *¿Por qué?*: A developer can locate the code, identify what each file represents at a glance, the structure is flat as can be, and there is no repetitive nor redundant names. + *¿Por qué?*: Un desarrollador puede localizar el código, identificar cada qué representa cada archivo de un vistazo, la estructura es tan plana como puede ser, y no hay nombres repetidos o redundantes. - *¿Por qué?*: The LIFT guidelines are all covered. + *¿Por qué?*: Las pautas LIFT estarán cubiertas. - *¿Por qué?*: Helps reduce the app from becoming cluttered through organizing the content and keeping them aligned with the LIFT guidelines. + *¿Por qué?*: Ayuda a evitar que la aplicación se sature a través de organizar el contenido y conservarlo alineado con las pautas LIFT. - *¿Por qué?*: When there are a lot of files (10+) locating them is easier with a consistent folder structures and more difficult in flat structures. + *¿Por qué?*: Cuando hay demasiados archivos (10+) localizarlos es más fácil con una estructura de directorios consistente y más díficiles en una estructura plana. ```javascript /** - * recommended + * recomendado */ app/ @@ -2155,13 +2161,13 @@ Mientras que esta guía explica el *qué*, *por qué* y *cómo*, me resulta úti ![Sample App Structure](https://raw.githubusercontent.com/johnpapa/angularjs-styleguide/master/assets/modularity-2.png) - Nota: Do not use structuring using folders-by-type. This requires moving to multiple folders when working on a feature and gets unwieldy quickly as the app grows to 5, 10 or 25+ views and controllers (and other features), which makes it more difficult than folder-by-feature to locate files. + Nota: No estructures tu aplicación usando directorios-por-tipo. Esto require mover múltiples directorios cuando se está trabajando en una feature y se vuelve díficil de manejar conforme la aplicación crece a 5, 10 o 25+ vistas y controladores (y otras features), lo que lo hace más díficil que localizar archivos en una aplicación estructura en directorios-por-feature. ```javascript /* - * avoid - * Alternative folders-by-type. - * I recommend "folders-by-feature", instead. + * evita + * Alternativa directorios-por-tipo + * Yo recomiendo "directorios-por-feature", en su lugar. */ app/ @@ -2198,78 +2204,78 @@ Mientras que esta guía explica el *qué*, *por qué* y *cómo*, me resulta úti **[Volver arriba](#table-of-contents)** -## Modularity +## Modularidad -### Many Small, Self Contained Modules +### Muy Pequeños, Módulos Autocontenidos ###### [Style [Y160](#style-y160)] - - Create small modules that encapsulate one responsibility. + - Crea módulos pequeños que encapsulen una responsabilidad. - *¿Por qué?*: Modular applications make it easy to plug and go as they allow the development teams to build vertical slices of the applications and roll out incrementally. This means we can plug in new features as we develop them. + *¿Por qué?*: Aplicaciones modulares hace más fácil el plug and go ya que permiten a los equipos de desarrollo construir porciones verticales de la aplicación y lanzarlas incrementalmente. Esto significa que podemos conectar nuevas features conforme las desarrollamos. -### Create an App Module +### Crea un Módulo App ###### [Style [Y161](#style-y161)] - - Create an application root module whose role is pull together all of the modules and features of your application. Name this for your application. + - Crea una módulo raíz de aplicación cuyo rol sea unir todos los módulos y features de tu aplicación. Nombra éste de acuerdo a tu aplicación. - *¿Por qué?*: AngularJS encourages modularity and separation patterns. Creating an application root module whose role is to tie your other modules together provides a very straightforward way to add or remove modules from your application. + *¿Por qué?*: AngularJS incentiva la modularidad y patrones de separación. Crear un módulo raíz de aplicación cuyo rol es atar otros módulos juntos provee una manera muy directa de agregar o remover módulos de tu aplicación. -### Keep the App Module Thin +### Mantén el Módulo App Delgado ###### [Style [Y162](#style-y162)] - - Only put logic for pulling together the app in the application module. Leave features in their own modules. + - Solo coloca lógica para unir la aplicación en el módulo app. Deja las features en sus propios módulos. - *¿Por qué?*: Adding additional roles to the application root to get remote data, display views, or other logic not related to pulling the app together muddies the app module and make both sets of features harder to reuse or turn off. + *¿Por qué?*: Agregar roles adicionales a la aplicación raíz para obtener datos remotos, mostrar vistas, u otra lógica no relaciona a la unión de la aplicación enturbia el módulo app y hace ambos conjuntos de features díficles de reusar y apagar. - *¿Por qué?*: The app module becomes a manifest that describes which modules help define the application. + *¿Por qué?*: El módulo app se convierte en el manifiesto que describe qué módulos definen la aplicación. -### Feature Areas are Modules +### Áreas de Features son Módulos ###### [Style [Y163](#style-y163)] - - Create modules that represent feature areas, such as layout, reusable and shared services, dashboards, and app specific features (e.g. customers, admin, sales). + - Crea módulos que representen áreas de features, como el layout, servicios reusables y compartidos, dashboards, y features específicos de la aplicación (e.g. customers, admin, sales). - *¿Por qué?*: Self contained modules can be added to the application with little or no friction. + *¿Por qué?*: Módulos autocontenidos pueden ser agregados a la aplicación con poca o sin ninguna fricción. - *¿Por qué?*: Sprints or iterations can focus on feature areas and turn them on at the end of the sprint or iteration. + *¿Por qué?*: Sprints o iteraciones pueden enfocarse en áreas de features y encendarlas al final del sprint o iteración. - *¿Por qué?*: Separating feature areas into modules makes it easier to test the modules in isolation and reuse code. + *¿Por qué?*: Separar áreas de features en módulos hace más fácil testear módulos en aislamiento y reusar código. -### Reusable Blocks are Modules +### Bloques Reusables son Módulos ###### [Style [Y164](#style-y164)] - - Create modules that represent reusable application blocks for common services such as exception handling, logging, diagnostics, security, and local data stashing. + - Crea módulos que representen bloques de la aplicación reusables para servicios cómunes como manejo de excepciones, logeo, diagnóstico, seguridad, y almacenamiento local de datos. - *¿Por qué?*: These types of features are needed in many applications, so by keeping them separated in their own modules they can be application generic and be reused across applications. + *¿Por qué?*: Este tipo de features son necesarias en muchas aplicaciones, así que mantenerlas separadas en sus propios módulos pueden ser genéricas de aplicación y pueden ser reusadas a lo largo de varias aplicaciones. -### Module Dependencies +### Dependencias de Módulos ###### [Style [Y165](#style-y165)] - - The application root module depends on the app specific feature modules and any shared or reusable modules. + - El módulo raíz de la aplicación depende de módulos de features específicos y cualquier módulo compartido o reusable. ![Modularity and Dependencies](https://raw.githubusercontent.com/johnpapa/angularjs-styleguide/master/assets/modularity-1.png) - *¿Por qué?*: The main app module contains a quickly identifiable manifest of the application's features. + *¿Por qué?*: El módulo principal de la aplicación contiene un manifiesto rápidamente identificable de las features de la aplicación. - *¿Por qué?*: Each feature area contains a manifest of what it depends on, so it can be pulled in as a dependency in other applications and still work. + *¿Por qué?*: Cada área de feature contiene un manifiesto de lo que depende, así que puede ser extraído como dependecia en otras aplicaciones y seguir funcionando. - *¿Por qué?*: Intra-App features such as shared data services become easy to locate and share from within `app.core` (choose your favorite name for this module). + *¿Por qué?*: Features internas de la aplicación como servicios de datos compartidos se hacen fácil de localizar y compartir desde `app.core` (elije tu nombre favorito para este módulo). - Nota: This is a strategy for consistency. There are many good options here. Choose one that is consistent, follows AngularJS's dependency rules, and is easy to maintain and scale. + Nota: Esta es una estrategia para consistencia. Hay muy buenas opciones aquí. Escoje una que sea consistente, que siga las reglas de dependencias de AngularJS, y que sea fácil de mantener y escalar. - > My structures vary slightly between projects but they all follow these guidelines for structure and modularity. The implementation may vary depending on the features and the team. In other words, don't get hung up on an exact like-for-like structure but do justify your structure using consistency, maintainability, and efficiency in mind. + > Mis estructuras varian ligeramente entre proyetos pero todas ellas siguen estas pautas para estructuras y modularidad. La implementación puede variar dependiendo de las features y el equipo. En otras palabras, no te quedes colgado en una estructura igual pero justifica tu estructura usando consistencia, mantenibilidad, y eficacia en mente. - > In a small app, you can also consider putting all the shared dependencies in the app module where the feature modules have no direct dependencies. This makes it easier to maintain the smaller application, but makes it harder to reuse modules outside of this application. + > En una aplicación pequeña, también puedes considerar poner todas las dependencias compartidas en el módulo principal dónde los módulos de features no tienen dependencias directas. Esto hace más fácil mantener aplicaciones pequeñas, pero hace más díficil el reusar módulos fuera de esta aplicación. **[Volver arriba](#table-of-contents)** -## Startup Logic +## Lógica de Arranque -### Configuration +### Configuración ###### [Style [Y170](#style-y170)] - - Inject code into [module configuration](https://docs.angularjs.org/guide/module#module-loading-dependencies) that must be configured before running the angular app. Ideal candidates include providers and constants. + - Inyecta código dentro de [module configuration](https://docs.angularjs.org/guide/module#module-loading-dependencies) que necesite ser configurado antes de correr la aplicación angular. Candidatos ideales incluyen providers y constantes. - *¿Por qué?*: This makes it easier to have a less places for configuration. + *¿Por qué?*: Esto hace más fácil tener menos lugares para la configuración. ```javascript angular @@ -2296,12 +2302,12 @@ Mientras que esta guía explica el *qué*, *por qué* y *cómo*, me resulta úti } ``` -### Run Blocks +### Bloques Run ###### [Style [Y171](#style-y171)] - - Any code that needs to run when an application starts should be declared in a factory, exposed via a function, and injected into the [run block](https://docs.angularjs.org/guide/module#module-loading-dependencies). + - Cualquier código que necesite ser ejecutado cuando una aplicación arranca debe ser declarado en una factory, ser expuesto a través de una función, o inyectado en el [bloque run](https://docs.angularjs.org/guide/module#module-loading-dependencies). - *¿Por qué?*: Code directly in a run block can be difficult to test. Placing in a factory makes it easier to abstract and mock. + *¿Por qué?*: Código que está directamente en un bloque run puede ser díficil de testear. Colocarlo en una factory lo hace fácil de abstraer y mockear. ```javascript angular @@ -2318,33 +2324,33 @@ Mientras que esta guía explica el *qué*, *por qué* y *cómo*, me resulta úti **[Volver arriba](#table-of-contents)** -## Angular $ Wrapper Services +## Servicios Envoltorios $ de Angular -### $document and $window +### $document y $window ###### [Style [Y180](#style-y180)] - - Use [`$document`](https://docs.angularjs.org/api/ng/service/$document) and [`$window`](https://docs.angularjs.org/api/ng/service/$window) instead of `document` and `window`. + - Usa [`$document`](https://docs.angularjs.org/api/ng/service/$document) y [`$window`](https://docs.angularjs.org/api/ng/service/$window) en lugar de `document` y `window`. - *¿Por qué?*: These services are wrapped by Angular and more easily testable than using document and window in tests. This helps you avoid having to mock document and window yourself. + *¿Por qué?*: Estos servicios son envueltos por Angular y son más fáciles de testear en lugar de usar document y window en las pruebas. Esto te ayuda a evitar que tener que mockear document y window tu mismo. -### $timeout and $interval +### $timeout y $interval ###### [Style [Y181](#style-y181)] - - Use [`$timeout`](https://docs.angularjs.org/api/ng/service/$timeout) and [`$interval`](https://docs.angularjs.org/api/ng/service/$interval) instead of `setTimeout` and `setInterval` . + - Usa [`$timeout`](https://docs.angularjs.org/api/ng/service/$timeout) y [`$interval`](https://docs.angularjs.org/api/ng/service/$interval) en lugar de `setTimeout` y `setInterval` . - *¿Por qué?*: These services are wrapped by Angular and more easily testable and handle AngularJS's digest cycle thus keeping data binding in sync. + *¿Por qué?*: Estos servicios están envueltos por Angular y son más fáciles de testear y manejar el ciclo digest de AngularJS así que mantienen el bindeo de los datos en sincronización. **[Volver arriba](#table-of-contents)** -## Testing -Unit testing helps maintain clean code, as such I included some of my recommendations for unit testing foundations with links for more information. +## Pruebas +Las pruebas unitarias ayudan a mantener el código limpio, así que incluyo algunas de mis recomendaciones en los fundamentos del testeo unitario con links para mayor información. -### Write Tests with Stories +### Escribe Pruebas con Historias ###### [Style [Y190](#style-y190)] - - Write a set of tests for every story. Start with an empty test and fill them in as you write the code for the story. + - Escribe un conjunto de pruebas para cada historia. Comienza con un test vacío y llénalo conforme escribas el código para la historia. - *¿Por qué?*: Writing the test descriptions helps clearly define what your story will do, will not do, and how you can measure success. + *¿Por qué?*: Escribir descripciones para la prueba ayuda a definir claramente qué es lo que tu historia hará, qué no hará, y cómo puedes medir el éxito. ```javascript it('should have Avengers controller', function() { @@ -2363,62 +2369,62 @@ Unit testing helps maintain clean code, as such I included some of my recommenda // TODO ($httpBackend?) }); - // and so on + // y así ``` -### Testing Library +### Librería para las Pruebas ###### [Style [Y191](#style-y191)] - - Use [Jasmine](http://jasmine.github.io/) or [Mocha](http://mochajs.org) for unit testing. + - Usa [Jasmine](http://jasmine.github.io/) o [Mocha](http://mochajs.org) para las pruebas unitarias. - *¿Por qué?*: Both Jasmine and Mocha are widely used in the AngularJS community. Both are stable, well maintained, and provide robust testing features. + *¿Por qué?*: Ambas Jasmine y Mocha son usadas ampliamente por la comunidad de AngularJS. Ambas son estables, bien mantenidas, y proveen de features de pruebas robustas. Nota: When using Mocha, also consider choosing an assert library such as [Chai](http://chaijs.com). ### Test Runner ###### [Style [Y192](#style-y192)] - - Use [Karma](http://karma-runner.github.io) as a test runner. + - Usa [Karma](http://karma-runner.github.io) como test runner. - *¿Por qué?*: Karma is easy to configure to run once or automatically when you change your code. + *¿Por qué?*: Karma es fácil de configurar para correr una vez o automáticamente cuando cambias tu código. - *¿Por qué?*: Karma hooks into your Continuous Integration process easily on its own or through Grunt or Gulp. + *¿Por qué?*: Karma encaja en tu proceso de Integración Continua fácilmente por sí sola o a través de Grunt o Gulp. - *¿Por qué?*: Some IDE's are beginning to integrate with Karma, such as [WebStorm](http://www.jetbrains.com/webstorm/) and [Visual Studio](http://visualstudiogallery.msdn.microsoft.com/02f47876-0e7a-4f6c-93f8-1af5d5189225). + *¿Por qué?*: Algunos IDE's están comenzando a integrarse con Karma, tal como [WebStorm](http://www.jetbrains.com/webstorm/) y [Visual Studio](http://visualstudiogallery.msdn.microsoft.com/02f47876-0e7a-4f6c-93f8-1af5d5189225). - *¿Por qué?*: Karma works well with task automation leaders such as [Grunt](http://www.gruntjs.com) (with [grunt-karma](https://github.com/karma-runner/grunt-karma)) and [Gulp](http://www.gulpjs.com) (with [gulp-karma](https://github.com/lazd/gulp-karma)). + *¿Por qué?*: Karma funciona bien con líderes de automatización de tareas tales como [Grunt](http://www.gruntjs.com) (con [grunt-karma](https://github.com/karma-runner/grunt-karma)) y [Gulp](http://www.gulpjs.com) (con [gulp-karma](https://github.com/lazd/gulp-karma)). -### Stubbing and Spying +### Stubear y Espíar ###### [Style [Y193](#style-y193)] - - Use [Sinon](http://sinonjs.org/) for stubbing and spying. + - Usa [Sinon](http://sinonjs.org/) para el stubeo y espíar. - *¿Por qué?*: Sinon works well with both Jasmine and Mocha and extends the stubbing and spying features they offer. + *¿Por qué?*: Sinon funciona bien con ambos Jasmine y Mocha y extiende las features de stubeo y espío que ellos ofrecen. - *¿Por qué?*: Sinon makes it easier to toggle between Jasmine and Mocha, if you want to try both. + *¿Por qué?*: Sinon hace más fácil cambiar entre Jasmine y Mocha, si quieres probar ambos. ### Headless Browser ###### [Style [Y194](#style-y194)] - - Use [PhantomJS](http://phantomjs.org/) to run your tests on a server. + - Usa [PhantomJS](http://phantomjs.org/) para correr tus pruebas en un servidor. - *¿Por qué?*: PhantomJS is a headless browser that helps run your tests without needing a "visual" browser. So you do not have to install Chrome, Safari, IE, or other browsers on your server. + *¿Por qué?*: PhantomJS es un navegador headless que ayuda a correr las pruebas necesitar una navegador "visual". Así que no necistas instalar Chrom, Safari u otros navegadores en tu servidor. - Nota: You should still test on all browsers in your environment, as appropriate for your target audience. + Nota: Aún debes testear en todos los navegadores de tu entorno, así como sea apropiado para tu audiencia meta. -### Code Analysis +### Ánalisis de Código ###### [Style [Y195](#style-y195)] - - Run JSHint on your tests. + - Corre JSHint en tus pruebas. - *¿Por qué?*: Tests are code. JSHint can help identify code quality issues that may cause the test to work improperly. + *¿Por qué?*: Las pruebas son código. JSHint puede ayudar a identificar problemas en la calidad del código que pueden causar que tus pruebas funcionen inapropiadamente. -### Alleviate Globals for JSHint Rules on Tests +### Mitiga Palabras Globales dentro de las Reglas de JSHint en las Pruebas ###### [Style [Y196](#style-y196)] - - Relax the rules on your test code to allow for common globals such as `describe` and `expect`. + - Relaja las reglas en tu código de prueba para permitir palabras globales comúnes como `describe` y `expect`. - *¿Por qué?*: Your tests are code and require the same attention and code quality rules as all of your production code. However, global variables used by the testing framework, for example, can be relaxed by including this in your test specs. + *¿Por qué?*: Tus pruebas son código y requieren la misma atención y reglas de calidad de código que todo tu código de producción. Sin embargo, variables globales usadas por el framework para pruebas, por ejemplo, puede ser relajado al incluir esto en tus specs de prueba. ```javascript /* global sinon, describe, it, afterEach, beforeEach, expect, inject */ @@ -2426,22 +2432,22 @@ Unit testing helps maintain clean code, as such I included some of my recommenda ![Testing Tools](https://raw.githubusercontent.com/johnpapa/angularjs-styleguide/master/assets/testing-tools.png) -### Organizing Tests +### Organizando las Pruebas ###### [Style [Y197](#style-y197)] - - Place unit test files (specs) side-by-side with your client code. Place specs that cover server integration or test multiple components in a separate `tests` folder. + - Coloca archivos de pruebas unitarias (specs) lado a lado con tu código del cliente. Coloca tus specs que cubren la integración con el servidor o que prueban múltiples componentes en un directorio `tests` separado. - *¿Por qué?*: Unit tests have a direct correlation to a specific component and file in source code. + *¿Por qué?*: Las Pruebas Unitarias tiene una correlación directa con un componente y archivo específico en tu código fuente. - *¿Por qué?*: It is easier to keep them up to date since they are always in sight. When coding whether you do TDD or test during development or test after development, the specs are side-by-side and never out of sight nor mind, and thus more likely to be maintained which also helps maintain code coverage. + *¿Por qué?*: Es más fácil mantenerlas actualizadas ya que siempre están a la vista. Al escribir código ya sea que realices TDD o pruebes durante el desarrollo o después del desarrollo, los specs están lado a lado y nunca fuera de la vista o de la mente, así es más probable que sean mantenidas lo cual ayuda a mantener la cobertura de pruebas. - *¿Por qué?*: When you update source code it is easier to go update the tests at the same time. + *¿Por qué?*: Cuando actualices código fuente es más fácil ir y actualizar las pruebas al mismo tiempo. - *¿Por qué?*: Placing them side-by-side makes it easy to find them and easy to move them with the source code if you move the source. + *¿Por qué?*: Colocarlas lado a lado hace más fácil encontrarlas y fácil de moverlas con el código fuente si mueves la fuente. - *¿Por qué?*: Having the spec nearby makes it easier for the source code reader to learn how the component is supposed to be used and to discover its known limitations. + *¿Por qué?*: Tener el spec cerca hace más fácil al lector del código fuente aprender cómo se supone que el componente es usado y descubrir sus propias limitaciones. - *¿Por qué?*: Separating specs so they are not in a distributed build is easy with grunt or gulp. + *¿Por qué?*: Separar specs para que no estén un build de distribución es fácil con grunt o gulp. ``` /src/client/app/customers/customer-detail.controller.js @@ -2455,49 +2461,49 @@ Unit testing helps maintain clean code, as such I included some of my recommenda **[Volver arriba](#table-of-contents)** -## Animations +## Animaciones -### Usage +### Uso ###### [Style [Y210](#style-y210)] - - Use subtle [animations with AngularJS](https://docs.angularjs.org/guide/animations) to transition between states for views and primary visual elements. Include the [ngAnimate module](https://docs.angularjs.org/api/ngAnimate). The 3 keys are subtle, smooth, seamless. + - Usa sutiles [animaciones con AngularJS](https://docs.angularjs.org/guide/animations) para transicionar entre estados en vistas y elementos visuales primarios. Incluye el [módulo ngAnimate](https://docs.angularjs.org/api/ngAnimate). Las 3 claves son sutil, fluido, transparente. - *¿Por qué?*: Subtle animations can improve User Experience when used appropriately. + *¿Por qué?*: Animaciones sutiles pueden mejorar la Experiencia de Usuario cuando son usadas apropiadamente. - *¿Por qué?*: Subtle animations can improve perceived performance as views transition. + *¿Por qué?*: Animaciones sutiles pueden mejorar el performance percibido como una transición de vista. -### Sub Second +### Sub Segundos ###### [Style [Y211](#style-y211)] - - Use short durations for animations. I generally start with 300ms and adjust until appropriate. + - Usa duraciones cortas para las animaciones. Yo generalmente empiezo con 300ms y ajusto hasta que es apropiado. - *¿Por qué?*: Long animations can have the reverse affect on User Experience and perceived performance by giving the appearance of a slow application. + *¿Por qué?*: Animaciones largas pueden tener el efecto contrario en la Experiencia de Usuario y el performance percibido al dar la apariencia de una aplicación lenta. ### animate.css ###### [Style [Y212](#style-y212)] - - Use [animate.css](http://daneden.github.io/animate.css/) for conventional animations. + - Usa [animate.css](http://daneden.github.io/animate.css/) para animaciones convencionales. - *¿Por qué?*: The animations that animate.css provides are fast, smooth, and easy to add to your application. + *¿Por qué?*: Las animaciones que animate.css provee son rápidas, fluidas, y fáciles de agregar en tu aplicación. - *¿Por qué?*: Provides consistency in your animations. + *¿Por qué?*: Provee consistencia en tus animaciones. - *¿Por qué?*: animate.css is widely used and tested. + *¿Por qué?*: animate.css está ampliamente usado y testeado. - Nota: See this [great post by Matias Niemelä on AngularJS animations](http://www.yearofmoo.com/2013/08/remastered-animation-in-angularjs-1-2.html) + Nota: Ve este [ excelente post de Matias Niemelä sobre animaciones AngularJS](http://www.yearofmoo.com/2013/08/remastered-animation-in-angularjs-1-2.html) **[Volver arriba](#table-of-contents)** -## Comments +## Comentarios ### jsDoc ###### [Style [Y220](#style-y220)] - - If planning to produce documentation, use [`jsDoc`](http://usejsdoc.org/) syntax to document function names, description, params and returns. Use `@namespace` and `@memberOf` to match your app structure. + - Si planeas producir documentación, usa la sintaxis [`jsDoc`](http://usejsdoc.org/) para documentar nombres de funciones, descripción, parámetros y devoluciones. Usa `@namespace` y `@memberOf` para igualar la estructura de tu aplicación. - *¿Por qué?*: You can generate (and regenerate) documentation from your code, instead of writing it from scratch. + *¿Por qué?*: Puedes generar (y regenerar) documentación desde tu código, en lugar de escribirla desde cero. - *¿Por qué?*: Provides consistency using a common industry tool. + *¿Por qué?*: Provee consistencia al usar una herramienta industrial cómun. ```javascript /** @@ -2542,14 +2548,14 @@ Unit testing helps maintain clean code, as such I included some of my recommenda ## JS Hint -### Use an Options File +### Usa un Archivo de Opciones ###### [Style [Y230](#style-y230)] - - Use JS Hint for linting your JavaScript and be sure to customize the JS Hint options file and include in source control. See the [JS Hint docs](http://www.jshint.com/docs/) for details on the options. + - Usa JS Hint para resaltar problemas en tu JavaScript y asegurate de personalizar el arhivo de opciones de JS Hint e incluirlo en el control de versiones. Ve los [JS Hint docs](http://www.jshint.com/docs/) para detalles sobre estas opciones. - *¿Por qué?*: Provides a first alert prior to committing any code to source control. + *¿Por qué?*: Provee una primera alerta antes de commitear cualquire código al control de versiones. - *¿Por qué?*: Provides consistency across your team. + *¿Por qué?*: Provee consistencia a lo largo de tu equipo. ```javascript { @@ -2617,14 +2623,14 @@ Unit testing helps maintain clean code, as such I included some of my recommenda **[Volver arriba](#table-of-contents)** -## Constants +## Constantes -### Vendor Globals +### Globales de Vendor ###### [Style [Y240](#style-y240)] - - Create an AngularJS Constant for vendor libraries' global variables. + - Crea una Constante de Angular para variables globales en librerías vendor. - *¿Por qué?*: Provides a way to inject vendor libraries that otherwise are globals. This improves code testability by allowing you to more easily know what the dependencies of your components are (avoids leaky abstractions). It also allows you to mock these dependencies, where it makes sense. + *¿Por qué?*: Provee una manera de inyectar librerías vendor que de otra manera son globales. Esto mejora la testeabilidad al permitirte saber más fácilmente cuáles son las dependencias de tus componentes (evita abstraciones malformadas). También te permite mockear estas dependencias, cuando tiene sentido. ```javascript // constants.js @@ -2642,21 +2648,21 @@ Unit testing helps maintain clean code, as such I included some of my recommenda ###### [Style [Y241](#style-y241)] - - Use constants for values that do not change and do not come from another service. When constants are used only for a module that may be reused in multiple applications, place constants in a file per module named after the module. Until this is required, keep constants in the main module in a `constants.js` file. + - Usa constantes para valores que no cambian y no vienen de otro servicio. Cuando las constantes son usadas solo por para un módulo que pueda ser reutilizado en múltiples aplicaciones, coloca las constantes en un archivo por módulo nombrado a partir del módulo. Hasta que esto sea requerido, mantén las constantes en el módulo principal en un archivo `constants.js`. - *¿Por qué?*: A value that may change, even infrequently, should be retrieved from a service so you do not have to change the source code. For example, a url for a data service could be placed in a constants but a better place would be to load it from a web service. + *¿Por qué?*: Un valor que puede cambiar, incluso infrecuentemente, debería ser obtenido desde un servicio así no tendrás que cambiar el código fuente. Por ejemplo, una url para un data service puede ser colocada en una constante pero un mejor lugar sería cargarla desde un servicio web. - *¿Por qué?*: Constants can be injected into any angular component, including providers. + *¿Por qué?*: Las Constantes pueden ser inyectadas en cualquire componente de angular, incluyendo providers. - *¿Por qué?*: When an application is separated into modules that may be reused in other applications, each stand-alone module should be able to operate on its own including any dependent constants. + *¿Por qué?*: Cuando una aplicación es separada en módulos que pueden ser reutilizados en otras aplicaciones, cada módulo autónomo debería ser capaz de operar por sí mismo incluyendo cualquer constante de la cual dependa. ```javascript - // Constants used by the entire app + // Constantes usadas por la aplicación entera angular .module('app.core') .constant('moment', moment); - // Constants used only by the sales module + // Constantes usadas solo por el módulo de ventas angular .module('app.sales') .constant('events', { @@ -2667,73 +2673,73 @@ Unit testing helps maintain clean code, as such I included some of my recommenda **[Volver arriba](#table-of-contents)** -## File Templates and Snippets -Use file templates or snippets to help follow consistent styles and patterns. Here are templates and/or snippets for some of the web development editors and IDEs. +## Plantillas y Snippets +Usa Plantillas o snippets para ayudarte a seguir estilos consistentes o patrones. Aquí hay plantillas y/o snippets para algunos de los editores de desarrollo web e IDEs. ### Sublime Text ###### [Style [Y250](#style-y250)] - - AngularJS snippets that follow these styles and guidelines. + - Snippets de AngularJS que siguen estos estilos y directrices. - - Download the [Sublime Angular snippets](assets/sublime-angular-snippets.zip?raw=true) - - Place it in your Packages folder - - Restart Sublime - - In a JavaScript file type these commands followed by a `TAB` + - Descarga los [snippets de Angular para Sublime](assets/sublime-angular-snippets.zip?raw=true) + - Colócalos en tu directorio de Packages + - Reinicia Sublime + - En un archivo de JavaScript escibe estos comandos seguidos de un `TAB` ```javascript - ngcontroller // creates an Angular controller - ngdirective // creates an Angular directive - ngfactory // creates an Angular factory - ngmodule // creates an Angular module + ngcontroller // crea un controlador de Angular + ngdirective // crea una directiva de Angular + ngfactory // crea una factory de Angular + ngmodule // crea un módulo de Angular ``` ### Visual Studio ###### [Style [Y251](#style-y251)] - - AngularJS file templates that follow these styles and guidelines can be found at [SideWaffle](http://www.sidewaffle.com) + - Plantillas de AngularJS que siguen estos estilos y directrices pueden ser encontrados en [SideWaffle](http://www.sidewaffle.com) - - Download the [SideWaffle](http://www.sidewaffle.com) Visual Studio extension (vsix file) - - Run the vsix file - - Restart Visual Studio + - Descarga la extensión [SideWaffle](http://www.sidewaffle.com) de Visual Studio (archivo vsix) + - Corre el archivo vsix + - Reinicia Visual Studio ### WebStorm ###### [Style [Y252](#style-y252)] - - AngularJS snippets and file templates that follow these styles and guidelines. You can import them into your WebStorm settings: + - Snippets y arhicos de AngularJS que siguen estos estilos y directrices. Puedes importarlos en tus configuraciones de WebStorm: - - Download the [WebStorm AngularJS file templates and snippets](assets/webstorm-angular-file-template.settings.jar?raw=true) - - Open WebStorm and go to the `File` menu - - Choose the `Import Settings` menu option - - Select the file and click `OK` - - In a JavaScript file type these commands followed by a `TAB`: + - Descarga los [snippets y plantillas de AngularJS para WebStorm](assets/webstorm-angular-file-template.settings.jar?raw=true) + - Abre WebStorm y ve al menú `File` + - Elije la opción `Import Settings` + - Selecciona el archivo y da click en `OK` + - En un archivo de JavaScript escribe estos comandos seguidos de un `TAB`: ```javascript - ng-c // creates an Angular controller - ng-f // creates an Angular factory - ng-m // creates an Angular module + ng-c // crea un controlador de Angular + ng-f // crea una factory de Angular + ng-m // crea un módulo de Angular ``` **[Volver arriba](#table-of-contents)** -## Yeoman Generator +## Generador de Yeoman ###### [Style [Y260](#style-y260)] -You can use the [HotTowel yeoman generator](http://jpapa.me/yohottowel) to create an app that serves as a starting point for Angular that follows this style guide. +Puedes usar el [generador de yeoman HotTowel](http://jpapa.me/yohottowel) para crear una aplicación que te sirve como punto de inicio en Angular que sigue esta guía de estilos. -1. Install generator-hottowel +1. Instala generator-hottowel ``` npm install -g generator-hottowel ``` -2. Create a new folder and change directory to it +2. Crea un nuevo directorio y entra en el ``` mkdir myapp cd myapp ``` -3. Run the generator +3. Corre el generador ``` yo hottowel helloWorld @@ -2741,44 +2747,44 @@ You can use the [HotTowel yeoman generator](http://jpapa.me/yohottowel) to creat **[Volver arriba](#table-of-contents)** -## Routing -Client-side routing is important for creating a navigation flow between views and composing views that are made of many smaller templates and directives. +## Ruteo +Ruteo del lado del Cliente es importante para crear un flujo de navegación entre vistas y vistas de composición que están hechas de muchas pequeñas plantillas y directivas. ###### [Style [Y270](#style-y270)] - - Use the [AngularUI Router](http://angular-ui.github.io/ui-router/) for client-side routing. + - Usa el [AngularUI Router](http://angular-ui.github.io/ui-router/) para ruteo del lado del cliente. - *¿Por qué?*: UI Router offers all the features of the Angular router plus a few additional ones including nested routes and states. + *¿Por qué?*: UI Router ofrece todas las features del router de Angular mas algunas adicionales allincluyendo rutas anidadas the f y estados. - *¿Por qué?*: The syntax is quite similar to the Angular router and is easy to migrate to UI Router. + *¿Por qué?*: La sintaxis es bastante similar al router de Angular y es fácil de migrar al UI Router. ###### [Style [Y271](#style-y271)] - - Define routes for views in the module where they exist. Each module should contain the routes for the views in the module. + - Define rutas para vistas en el módulo dónde éstas existen. Cada módulo debería contener las rutas para las vistas en ese módulo. - *¿Por qué?*: Each module should be able to stand on its own. + *¿Por qué?*: Cada módulo debe ser capaz de funcionar por sí mismo. - *¿Por qué?*: When removing a module or adding a module, the app will only contain routes that point to existing views. + *¿Por qué?*: Al remover un módulo o al agregar un módulo, la aplicación solo contendrá rutas que apunten a las vistas existentes. - *¿Por qué?*: This makes it easy to enable or disable portions of an application without concern over orphaned routes. + *¿Por qué?*: Esto hace más fácil habilitar o deshabilitar porciones de una aplicación sin preocuparse de rutas huérfanas. **[Volver arriba](#table-of-contents)** -## Task Automation -Use [Gulp](http://gulpjs.com) or [Grunt](http://gruntjs.com) for creating automated tasks. Gulp leans to code over configuration while Grunt leans to configuration over code. I personally prefer Gulp as I feel it is easier to read and write, but both are excellent. +## Automatización de Tareas +Usa [Gulp](http://gulpjs.com) o [Grunt](http://gruntjs.com) para crear tareas automatizadas. Gulp deriva a código sobre configuración mientras que Grunt deriva a configuración sobre código. Personalmente yo prefiero Gulp ya que se siente más fácil de leer y escribir, pero ambos son excelentes. ###### [Style [Y400](#style-y400)] - - Use task automation to list module definition files `*.module.js` before all other application JavaScript files. + - Usa automatización de tareas para listar archivos que definan módulos `*.module.js` antes que otros archivos de JavaScript en la aplicación. - *¿Por qué?*: Angular needs the module definitions to be registered before they are used. + *¿Por qué?*: Angular necesita la definición de módulos para ser registrados antes de que sean usados. - *¿Por qué?*: Naming modules with a specific pattern such as `*.module.js` makes it easy to grab them with a glob and list them first. + *¿Por qué?*: Nombra módulos con un patrón específico como `*.module.js` hace más fácil tomarlos con un glob y listarlos primero. ```javascript var clientApp = './src/client/app/'; - // Always grab module files first + // Siempre toma archivos de módulos primero var files = [ clientApp + '**/*.module.js', clientApp + '**/*.js' @@ -2788,22 +2794,22 @@ Use [Gulp](http://gulpjs.com) or [Grunt](http://gruntjs.com) for creating automa **[Volver arriba](#table-of-contents)** ## AngularJS docs -For anything else, API reference, check the [Angular documentation](//docs.angularjs.org/api). +Para cualquier otra cosa, refiérete a la API, mira la [documentación de Angular](//docs.angularjs.org/api). -## Contributing +## Contribuyendo -Open an issue first to discuss potential changes/additions. If you have questions with the guide, feel free to leave them as issues in the repository. If you find a typo, create a pull request. The idea is to keep the content up to date and use github’s native feature to help tell the story with issues and PR’s, which are all searchable via google. Why? Because odds are if you have a question, someone else does too! You can learn more here at about how to contribute. +Primero abre un issue para discutir cambios/agregados potenciales. Si tienes preguntas acerca de esta guía, siéntete libre de dejarlas como issues en el repositorio. Si encuentras un typo, crea un pull request. La idea es mantener el contenido actualizado y usar las features de github para ayudar a contar la historia con issues y PR’s, los cuales pueden ser encontrados a través de google. ¿Por qué? Porque las probabilidades son que si tu tienes una pregunta, !alguien más también! Puedes aprender más aquí de cómo contribuir. -*By contributing to this repository you are agreeing to make your content available subject to the license of this repository.* +*Al contribuir a este repositorio estás acordando hacer tu contenido disponible a ser parte de la licencia de este repositorio.* -### Process - 1. Discuss the changes in a GitHub issue. - 2. Open a Pull Request against the develop branch, reference the issue, and explain the change and why it adds value. - 3. The Pull Request will be evaluated and either merged or declined. +### Proceso + 1. Discute los cambios en un issue de Github. + 2. Abre un Pull Request sobre la rama de develop, referencia el issue, y explica el cambio y por qué agrega valor. + 3. El Pull Request será evaluado y ya sea mergeado o declinado. -## License +## Licencia -_tldr; Use this guide. Attributions are appreciated._ +_tldr; Usa esta guía. Reconocimientos son apreciados._ ### (The MIT License) From b968bba4e1c991e0ba3bd81afb199afa056febc5 Mon Sep 17 00:00:00 2001 From: Gilberto Villa Date: Wed, 25 Feb 2015 10:20:51 -0600 Subject: [PATCH 199/567] Fix navigation in the es translations --- i18n/es-ES.md | 109 +++++++++++++++++++++++++------------------------- 1 file changed, 55 insertions(+), 54 deletions(-) diff --git a/i18n/es-ES.md b/i18n/es-ES.md index cf787bf7..1192728f 100644 --- a/i18n/es-ES.md +++ b/i18n/es-ES.md @@ -23,36 +23,37 @@ Mientras que esta guía explica el *qué*, *por qué* y *cómo*, me resulta úti ## Tabla de contenidos - 1. [Responsabilidad Única](#single-responsibility) + 1. [Responsabilidad + Única](#single-responsibility-o-responsabilidad-única) 1. [IIFE](#iife) - 1. [Módulos](#modules) - 1. [Controladores](#controllers) - 1. [Servicios](#services) + 1. [Módulos](#módulos) + 1. [Controladores](#controladores) + 1. [Servicios](#servicios) 1. [Factories](#factories) 1. [Data Services](#data-services) - 1. [Directivas](#directives) - 1. [Resolviendo Promesas en un Controlador](#resolving-promises-for-a-controller) - 1. [Anotación Manual para Inyección de Dependencias](#manual-annotating-for-dependency-injection) - 1. [Minification and Annotation](#minification-and-annotation) - 1. [Manejo de Excepciones](#exception-handling) - 1. [Cómo Nombrar](#naming) - 1. [Estructura de la Aplicación El Principio LIFT](#application-structure-lift-principle) - 1. [Estructura de la Aplicación](#application-structure) - 1. [Modularidad](#modularity) - 1. [Lógica de Arranque](#startup-logic) - 1. [Servicios Envoltorios $ de Angular](#angular--wrapper-services) - 1. [Pruebas](#testing) - 1. [Animaciones](#animations) - 1. [Comentarios](#comments) + 1. [Directivas](#directivas) + 1. [Resolviendo Promesas en un Controlador](#resolviendo-promesas-en-un-controlador) + 1. [Anotación Manual para la Inyección de Dependencias](#anotación-manual-para-la-inyección-de-dependencias) + 1. [Minificación y Anotación](#minificación-y-anotación) + 1. [Manejo de Excepciones](#manejo-de-excepciones) + 1. [Cómo Nombrar](#cómo-nombrar) + 1. [Estructura de la Aplicación El Principio LIFT](#estructura-de-la-aplicación-el-principio-lift) + 1. [Estructura de la Aplicación](#estructura-de-la-aplicación) + 1. [Modularidad](#modularidad) + 1. [Lógica de Arranque](#lógica-de-arranque) + 1. [Servicios Envoltorios $ de Angular](#servicios-envoltorios--de-angular) + 1. [Pruebas](#pruebas) + 1. [Animaciones](#animaciones) + 1. [Comentarios](#comentarios) 1. [JSHint](#js-hint) - 1. [Constantes](#constants) - 1. [Plantillas y Snippets](#file-templates-and-snippets) - 1. [Generador de Yeoman](#yeoman-generator) - 1. [Ruteo](#routing) - 1. [Automatización de Tareas](#task-automation) + 1. [Constantes](#constantes) + 1. [Plantillas y Snippets](#plantillas-y-snippets) + 1. [Generador de Yeoman](#generador-de-yeoman) + 1. [Ruteo](#ruteo) + 1. [Automatización de Tareas](#automatización-de-tareas) 1. [AngularJS Docs](#angularjs-docs) - 1. [Contribuyendo](#contributing) - 1. [Licencia](#license) + 1. [Contribuyendo](#contribuyendo) + 1. [Licencia](#licencia) ## Single Responsibility o Responsabilidad Única @@ -107,7 +108,7 @@ Mientras que esta guía explica el *qué*, *por qué* y *cómo*, me resulta úti function someFactory() { } ``` -**[Volver arriba](#table-of-contents)** +**[Volver arriba](#tabla-de-contenidos)** ## IIFE ### Closures de JavaScript @@ -172,7 +173,7 @@ Mientras que esta guía explica el *qué*, *por qué* y *cómo*, me resulta úti - Nota: IIFE previente que el código de los tests llegue a sus variables privadas, como expresiones regulares o funciones de ayuda que normalmente vienen bien para hacer pruebas por sí solas. Sin embargo, puedes acceder a ellas creando accesorios o accediendo a través de sus componentes. Por ejemplo, poniendo las funciones de ayuda, expresiones regulares o constantes en su propia factory. -**[Volver arriba](#table-of-contents)** +**[Volver arriba](#tabla-de-contenidos)** ## Módulos @@ -282,7 +283,7 @@ Mientras que esta guía explica el *qué*, *por qué* y *cómo*, me resulta úti function logger() { } ``` -**[Volver arriba](#table-of-contents)** +**[Volver arriba](#tabla-de-contenidos)** ## Controladores @@ -673,7 +674,7 @@ Mientras que esta guía explica el *qué*, *por qué* y *cómo*, me resulta úti ``` -**[Volver arriba](#table-of-contents)** +**[Volver arriba](#tabla-de-contenidos)** ## Servicios @@ -712,7 +713,7 @@ Mientras que esta guía explica el *qué*, *por qué* y *cómo*, me resulta úti } ``` -**[Volver arriba](#table-of-contents)** +**[Volver arriba](#tabla-de-contenidos)** ## Factories @@ -883,7 +884,7 @@ Mientras que esta guía explica el *qué*, *por qué* y *cómo*, me resulta úti } ``` -**[Volver arriba](#table-of-contents)** +**[Volver arriba](#tabla-de-contenidos)** ## Data Services @@ -1008,7 +1009,7 @@ Mientras que esta guía explica el *qué*, *por qué* y *cómo*, me resulta úti } ``` - **[Volver arriba](#table-of-contents)** + **[Volver arriba](#tabla-de-contenidos)** ## Directivas ### Limitadas a 1 Por Archivo @@ -1296,7 +1297,7 @@ Mientras que esta guía explica el *qué*, *por qué* y *cómo*, me resulta úti
min={{vm.min}}
``` -**[Volver arriba](#table-of-contents)** +**[Volver arriba](#tabla-de-contenidos)** ## Resolviendo Promesas en un Controlador @@ -1446,9 +1447,9 @@ Mientras que esta guía explica el *qué*, *por qué* y *cómo*, me resulta úti vm.movies = moviesPrepService.movies; } ``` - Nota: El código del ejemplo de dependencia en `movieService` no se puede minimizar tal cual. Para detalles en cómo hacer este código sea minimizable, mira la sección en [inyección de dependencias](#manual-annotating-for-dependency-injection) y en [minimización y anotación](#minification-and-annotation). + Nota: El código del ejemplo de dependencia en `movieService` no se puede minimizar tal cual. Para detalles en cómo hacer este código sea minimizable, mira la sección en [inyección de dependencias](#anotación-manual-para-la-inyección-de-dependencias) y en [minimización y anotación](#minificación-y-anotación). -**[Volver arriba](#table-of-contents)** +**[Volver arriba](#tabla-de-contenidos)** ## Anotación Manual para la Inyección de Dependencias @@ -1579,7 +1580,7 @@ Mientras que esta guía explica el *qué*, *por qué* y *cómo*, me resulta úti } ``` -**[Volver arriba](#table-of-contents)** +**[Volver arriba](#tabla-de-contenidos)** ## Minificación y Anotación @@ -1691,7 +1692,7 @@ Mientras que esta guía explica el *qué*, *por qué* y *cómo*, me resulta úti ``` -**[Volver arriba](#table-of-contents)** +**[Volver arriba](#tabla-de-contenidos)** ## Manejo de Excepciones @@ -1803,7 +1804,7 @@ Mientras que esta guía explica el *qué*, *por qué* y *cómo*, me resulta úti } ``` -**[Volver arriba](#table-of-contents)** +**[Volver arriba](#tabla-de-contenidos)** ## Cómo Nombrar @@ -2027,7 +2028,7 @@ Mientras que esta guía explica el *qué*, *por qué* y *cómo*, me resulta úti - Separa la configuración de la ruta en un arhivo propio. Algunos ejemplos pueden ser `app.route.js` para el módulo principal y `admin.route.js` para el módulo admin `admin`. Incluso en aplicaciones pequeñas prefiero esta separación del resto de la configuración. -**[Volver arriba](#table-of-contents)** +**[Volver arriba](#tabla-de-contenidos)** ## Estructura de la Aplicación El Principio LIFT ### LIFT @@ -2090,7 +2091,7 @@ Mientras que esta guía explica el *qué*, *por qué* y *cómo*, me resulta úti *¿Por qué?*: Ser DRY es importante, pero no crucial si sacrifica otras partes de LIFT, es por eso que lo llamo T-DRY. No quiero escribir session-view.html por una vista porque, obviamente es una vista. Si no es obvio o por convención, entonces la nombro así. -**[Volver arriba](#table-of-contents)** +**[Volver arriba](#tabla-de-contenidos)** ## Estructura de la Aplicación @@ -2202,7 +2203,7 @@ Mientras que esta guía explica el *qué*, *por qué* y *cómo*, me resulta úti topnav.html ``` -**[Volver arriba](#table-of-contents)** +**[Volver arriba](#tabla-de-contenidos)** ## Modularidad @@ -2266,7 +2267,7 @@ Mientras que esta guía explica el *qué*, *por qué* y *cómo*, me resulta úti > En una aplicación pequeña, también puedes considerar poner todas las dependencias compartidas en el módulo principal dónde los módulos de features no tienen dependencias directas. Esto hace más fácil mantener aplicaciones pequeñas, pero hace más díficil el reusar módulos fuera de esta aplicación. -**[Volver arriba](#table-of-contents)** +**[Volver arriba](#tabla-de-contenidos)** ## Lógica de Arranque @@ -2322,7 +2323,7 @@ Mientras que esta guía explica el *qué*, *por qué* y *cómo*, me resulta úti } ``` -**[Volver arriba](#table-of-contents)** +**[Volver arriba](#tabla-de-contenidos)** ## Servicios Envoltorios $ de Angular @@ -2340,7 +2341,7 @@ Mientras que esta guía explica el *qué*, *por qué* y *cómo*, me resulta úti *¿Por qué?*: Estos servicios están envueltos por Angular y son más fáciles de testear y manejar el ciclo digest de AngularJS así que mantienen el bindeo de los datos en sincronización. -**[Volver arriba](#table-of-contents)** +**[Volver arriba](#tabla-de-contenidos)** ## Pruebas Las pruebas unitarias ayudan a mantener el código limpio, así que incluyo algunas de mis recomendaciones en los fundamentos del testeo unitario con links para mayor información. @@ -2459,7 +2460,7 @@ Las pruebas unitarias ayudan a mantener el código limpio, así que incluyo algu /customers.route.spec.js ``` -**[Volver arriba](#table-of-contents)** +**[Volver arriba](#tabla-de-contenidos)** ## Animaciones @@ -2492,7 +2493,7 @@ Las pruebas unitarias ayudan a mantener el código limpio, así que incluyo algu Nota: Ve este [ excelente post de Matias Niemelä sobre animaciones AngularJS](http://www.yearofmoo.com/2013/08/remastered-animation-in-angularjs-1-2.html) -**[Volver arriba](#table-of-contents)** +**[Volver arriba](#tabla-de-contenidos)** ## Comentarios @@ -2544,7 +2545,7 @@ Las pruebas unitarias ayudan a mantener el código limpio, así que incluyo algu })(); ``` -**[Volver arriba](#table-of-contents)** +**[Volver arriba](#tabla-de-contenidos)** ## JS Hint @@ -2621,7 +2622,7 @@ Las pruebas unitarias ayudan a mantener el código limpio, así que incluyo algu } ``` -**[Volver arriba](#table-of-contents)** +**[Volver arriba](#tabla-de-contenidos)** ## Constantes @@ -2671,7 +2672,7 @@ Las pruebas unitarias ayudan a mantener el código limpio, así que incluyo algu }); ``` -**[Volver arriba](#table-of-contents)** +**[Volver arriba](#tabla-de-contenidos)** ## Plantillas y Snippets Usa Plantillas o snippets para ayudarte a seguir estilos consistentes o patrones. Aquí hay plantillas y/o snippets para algunos de los editores de desarrollo web e IDEs. @@ -2719,7 +2720,7 @@ Usa Plantillas o snippets para ayudarte a seguir estilos consistentes o patrones ng-m // crea un módulo de Angular ``` -**[Volver arriba](#table-of-contents)** +**[Volver arriba](#tabla-de-contenidos)** ## Generador de Yeoman ###### [Style [Y260](#style-y260)] @@ -2745,7 +2746,7 @@ Puedes usar el [generador de yeoman HotTowel](http://jpapa.me/yohottowel) para c yo hottowel helloWorld ``` -**[Volver arriba](#table-of-contents)** +**[Volver arriba](#tabla-de-contenidos)** ## Ruteo Ruteo del lado del Cliente es importante para crear un flujo de navegación entre vistas y vistas de composición que están hechas de muchas pequeñas plantillas y directivas. @@ -2768,7 +2769,7 @@ Ruteo del lado del Cliente es importante para crear un flujo de navegación entr *¿Por qué?*: Esto hace más fácil habilitar o deshabilitar porciones de una aplicación sin preocuparse de rutas huérfanas. -**[Volver arriba](#table-of-contents)** +**[Volver arriba](#tabla-de-contenidos)** ## Automatización de Tareas Usa [Gulp](http://gulpjs.com) o [Grunt](http://gruntjs.com) para crear tareas automatizadas. Gulp deriva a código sobre configuración mientras que Grunt deriva a configuración sobre código. Personalmente yo prefiero Gulp ya que se siente más fácil de leer y escribir, pero ambos son excelentes. @@ -2791,7 +2792,7 @@ Usa [Gulp](http://gulpjs.com) o [Grunt](http://gruntjs.com) para crear tareas au ]; ``` -**[Volver arriba](#table-of-contents)** +**[Volver arriba](#tabla-de-contenidos)** ## AngularJS docs Para cualquier otra cosa, refiérete a la API, mira la [documentación de Angular](//docs.angularjs.org/api). @@ -2834,4 +2835,4 @@ 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. -**[Volver arriba](#table-of-contents)** +**[Volver arriba](#tabla-de-contenidos)** From 8caea0725bb6e2639a66a007a02ca7ac7177f1e8 Mon Sep 17 00:00:00 2001 From: Aleksandar Bogatinov Date: Thu, 26 Feb 2015 11:11:57 +0100 Subject: [PATCH 200/567] Updated to latest version --- i18n/mk-MK.md | 48 +++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 41 insertions(+), 7 deletions(-) diff --git a/i18n/mk-MK.md b/i18n/mk-MK.md index fd710f83..d08a5bfe 100644 --- a/i18n/mk-MK.md +++ b/i18n/mk-MK.md @@ -1735,6 +1735,8 @@ ```javascript /* препорачано */ + var handlingRouteChangeError = false; + function handleRoutingErrors() { /** * Прекин на патека: @@ -1743,14 +1745,23 @@ */ $rootScope.$on('$routeChangeError', function(event, current, previous, rejection) { - var destination = (current && (current.title || current.name || current.loadedTemplateUrl)) || - 'unknown target'; - var msg = 'Error routing to ' + destination + '. ' + (rejection.msg || ''); + if (handlingRouteChangeError) { return; } + handlingRouteChangeError = true; + var destination = (current && (current.title || + current.name || current.loadedTemplateUrl)) || + 'unknown target'; + var msg = 'Error routing to ' + destination + '. ' + + (rejection.msg || ''); /** - * Optionally log using a custom service or $log. - * (Don't forget to inject custom service) + * Опционално логирајте со рачно изработен сервис или $log. + * (Не заборавајте да го вклучите рачно изработениот сервис) */ logger.warning(msg, [current]); + + /** + * При грешка во рутирање, одете на друга рута/состојба. + */ + $location.path('/'); } ); } @@ -2612,7 +2623,7 @@ angular ###### [Style [Y252](#style-Y252)] - AngularJS кратки кодови и датотечни шаблони кои ги следат овие стилови и водичи на код. Можете да ги внесете во вашите WebStorm подесувања: - - Симнете ги [WebStorm AngularJS датотечни шаблони и кратки кодови](assets/webstorm-angular-file-template.settings.jar?raw=true) + - Симнете ги [WebStorm AngularJS датотечни шаблони и кратки кодови](../assets/webstorm-angular-file-template.settings.jar?raw=true) - Отворете го WebStorm и одберете го `File` менито - Одберете го `Import Settings` - Одберете ја датотеката и кликнете `OK` @@ -2626,6 +2637,29 @@ angular **[Назад кон содржината](#table-of-contents)** ++### Atom +###### [Style [Y253](#style-y253)] + + - AngularJS кратки кодови кои ги следат овие стилови и водичи на код. + ``` + apm install angularjs-styleguide-snippets + ``` + или + - Отворете го Atom, потоа отворете го Package Manager (Packages -> Settings View -> Install Packages/Themes) + - Побарајте го пакетот 'angularjs-styleguide-snippets' + - Кликнете на 'Install' за да го инсталирате пакетот + + - Во JavaScript датотека напишете ги следните команди и потоа кликнете `TAB` + + ```javascript + ngcontroller // создава Angular контролер + ngdirective // создава Angular директива + ngfactory // создава Angular фабрика + ngmodule // создава Angular модул + ``` + +**[Назад кон содржината](#table-of-contents)** + ## Yeoman Generator ###### [Style [Y260](#style-y260)] @@ -2709,7 +2743,7 @@ angular ### Процес 1. Дискусирајте за промените во Github Issue. - 2. Отворете Pull Request врз develop гранката, поставете референца до Issue и објаснете ја промената и како додава на вредност. + 2. Отворете Pull Request, поставете референца до Issue и објаснете ја промената и како додава на вредност. 3. Pull Request ќе биде оценето и биде или споено или одбиено. ## License From 03364488a5afa603dc3346f77c63376c4baa2916 Mon Sep 17 00:00:00 2001 From: John Papa Date: Thu, 26 Feb 2015 07:19:43 -0500 Subject: [PATCH 201/567] Update README.md --- i18n/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/i18n/README.md b/i18n/README.md index 20dd3f7e..d20b97a6 100644 --- a/i18n/README.md +++ b/i18n/README.md @@ -11,6 +11,7 @@ The [original English version](http://jpapa.me/ngstyles) is the source of truth, 5. [Portuguese-Brazil](PT-BR.md) 6. [Russian](ru-RU.md) 7. [Simplified Chinese](zh-CN.md) +8. [Spanish](es-ES.md) ## Contributing Language translations are welcomed and encouraged. The succcess of these translations depends on the community. I highly encourage new translation contributions and help to keep them up to date. From ae6f06fb62bd37299fd7cac6f923cbd2763cb4e1 Mon Sep 17 00:00:00 2001 From: John Papa Date: Thu, 26 Feb 2015 07:23:57 -0500 Subject: [PATCH 202/567] Update es-ES.md --- i18n/es-ES.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/i18n/es-ES.md b/i18n/es-ES.md index 1192728f..d03d076b 100644 --- a/i18n/es-ES.md +++ b/i18n/es-ES.md @@ -2,6 +2,10 @@ *Guía de estilos colaborativa de AngularJS para equipos por [@john_papa](//twitter.com/john_papa)* +*Translation by [Alberto Calleja](https://github.com/AlbertoImpl) and [Gilberto](https://github.com/ingilniero)* + +>The [original English version](http://jpapa.me/ngstyles) is the source of truth, as it is maintained and updated first. + Si estás buscando una guía colaborativa sobre sintaxis, convenciones y estructura de aplicaciones con AngulRJS, este es el sitio. Estos estilos están basados en mi experiencia desarrollando con [AngularJS](//angularjs.org), persentaciones, [Cursos en Pluralsight](http://pluralsight.com/training/Authors/Details/john-papa) y trabajando en equipos. El propósito de esta guía de estilos es proporcionar una guía de cómo construir aplicaciones con AngularJS enseñando convenciones que uso y, lo más importante, el porqué. From bb5992970dd1a118ffe65c93cd24390e25abe2b9 Mon Sep 17 00:00:00 2001 From: jfroffice Date: Mon, 2 Mar 2015 20:35:26 +0100 Subject: [PATCH 203/567] [FR] fix typos --- i18n/fr-FR.md | 27 +++++++++++++-------------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/i18n/fr-FR.md b/i18n/fr-FR.md index 503c2425..7d8af2bb 100644 --- a/i18n/fr-FR.md +++ b/i18n/fr-FR.md @@ -14,7 +14,7 @@ Le but de ce guide de style est de proposer des conseils sur le développement d [![AngularJs Patterns: Clean Code](https://raw.githubusercontent.com/johnpapa/angularjs-styleguide/master/assets/ng-clean-code-banner.png)](http://jpapa.me/ngclean) -## Supprématie de la Communauté et Remerciements +## Suprématie de la Communauté et Remerciements Ne jamais travailler dans le vide. J'ai trouvé que la communauté AngularJS est un incroyable groupe dont les membres ont à coeur de partager leurs expériences. Ainsi, un ami et expert AngularJS Todd Motto et moi avons collaboré sur de nombreux styles et conventions. Nous sommes d'accord sur la plupart, et nous divergeons sur d'autres. Je vous encourage à visiter [les guideslines de Todd](https://github.com/toddmotto/angularjs-styleguide) pour vous faire un sentiment sur son approche et en quoi elle est comparable. De nombreux de mes styles proviennent des maintes scéances de pair programming que [Ward Bell](http://twitter.com/wardbell) et moi avons eu. Même si nous n'étions pas toujours d'accord, mon ami Ward a assurément contribué à influencer l'évolution ultime de ce guide. @@ -295,9 +295,9 @@ Alors que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'a ét - Utilisez la syntaxe [`controllerAs`](http://www.johnpapa.net/do-you-like-your-angular-controllers-with-or-without-sugar/) au lieu de la syntaxe de `controlleur classique avec $scope`. - *Pourquoi ?* : Les controlleurs sont constuits, "new-és", and fournissent une unique nouvelle instance, et la syntaxe `controllerAs` est plus proche de celle d'un contructeur Javascript que la `syntaxe $scope classique`. + *Pourquoi ?* : Les controlleurs sont construits, recréés, et fournissent une unique nouvelle instance, et la syntaxe `controllerAs` est plus proche de celle d'un contructeur Javascript que la `syntaxe $scope classique`. - *Pourquoi ?* : Il promeut l'usage du binding entre un objet avec "point" et la Vue (ex. `customer.name` au lieu de `name`), ce qui est plus contextuel, plus facile à lire, et évite tout problème de référence qui peut arriver sans "point". + *Pourquoi ?* : Il encourage l'usage du binding entre un objet avec "point" et la Vue (ex. `customer.name` au lieu de `name`), ce qui est plus contextuel, plus facile à lire, et évite tout problème de référence qui peut arriver sans "point". *Pourquoi ?* : Permet d'éviter l'usage des appels à `$parent` dans les Vues avec des controlleurs imbriqués. @@ -559,8 +559,8 @@ Alors que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'a ét ### Déplacer la Logique des Controlleurs ###### [Style [Y035](#style-y035)] - - Déplacer la logique d'un controlleur en la déléguant à des services et des factories. - + - Déplacer la logique d'un controlleur en la déléguant à des services et des factories. + *Pourquoi ?* : La logique peut être ré-utilisée par plusieurs controlleurs lorsqu'elle est placée au sein d'un service et exposée via une fonction. *Pourquoi ?* : La logique d'un service peut plus facilement être isolée dans un test unitaire, tandis que la logique d'appel dans le controlleur peut facilement être mockée. @@ -1127,9 +1127,9 @@ Alors que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'a ét - Lors de la création d'une directive qui fait du sens comme élément indépendant, permettez la restriction `E` (élément personnalisé) et éventuellement la restriction `A` (attribut personnalisé). En général, s'il devrait avoir son propre contrôle, `E` est le plus indiqué. Le conseil le plus général est de permettre `EA` mais se dirige vers une implémentation en tant qu'élément lorsqu'il est indépendant et en tant qu'attribut lorsqu'il améliore un élément DOM existant. - *Why?* : Ça fait sens. + *Pourquoi ?* : Çela a du sens. - *Why?* : Même s'il est autorisé d'utiliser une directive en tant que classe, si la directive agit vraiement comme un élément, elle fait plus de sens en tant qu'élément ou au moins en tant qu'attribut. + *Pourquoi ?* : Même s'il est autorisé d'utiliser une directive en tant que classe, si la directive agit vraiement comme un élément, elle fait plus de sens en tant qu'élément ou au moins en tant qu'attribut. Note : EA est la valeur par défaut avec AngularJS 1.3 + @@ -1308,9 +1308,8 @@ Alors que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'a ét - Résolvez la logique de démarrage d'un controlleur dans une fonction `activate`. *Pourquoi ?* : Placer la logique de démarrage toujours au même endroit permet de le rendre plus facile à localiser, plus cohérent à tester, et permet d'éviter la dispersion de la logique d'activation à travers le controlleur. - + *Pourquoi ?* : La fonction `activate` d'un controlleur rend pratique la ré-utilisation de la logique pour un refraichissement du controlleur ou de la vue, garde cette logique à un seul endroit, envoie l'utilisateur plus rapidement à la Vue, rend les animations faciles sur la `ng-view` ou l'`ui-view`, et c'est rendu plus vif à l'utilisateur. - *Why?*: The controller `activate` makes it convenient to re-use the logic for a refresh for the controller/View, keeps the logic together, gets the user to the View faster, makes animations easy on the `ng-view` or `ui-view`, and feels snappier to the user. Note : Si vous avez besoin d'annuler sous conditions la route avant de vous mettre à utiliser le controlleur, utilisez une [résolution de route](#style-y081) à la place. @@ -1411,7 +1410,7 @@ Alors que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'a ét vm.movies = moviesPrepService.movies; } ``` - + Note : L'exemple ci-dessous montre que la résolution de routage pointe vers une fonction nommée, laquelle est plus facile à débugguer et dont l'injection de dépendance est plus facile à gérer. ```javascript @@ -2441,7 +2440,7 @@ Les tests unitaires aident à maintenir un code propre, ainsi, j'ai inclu quelqu *Pourquoi ?* : Quand vous mettez à jour le code source, il est plus facile de mettre à jour les tests en même temps. *Pourquoi ?* : Les placer côte-à-côte les rend plus facile à trouver et facile à déplacer si vous déplacez les sources. - + *Pourquoi ?* : Avoir les specs proches permet au lecteur du code source d'apprendre comment le composant est supposé être utilisé et découvrir les limitations connues. *Pourquoi ?* : La séparation des specs afin qu'ils ne soient pas inclus dans le build est facile avec grunt ou gulp. @@ -2642,7 +2641,7 @@ Les tests unitaires aident à maintenir un code propre, ainsi, j'ai inclu quelqu .constant('moment', moment); })(); ``` - + ###### [Style [Y241](#style-y241)] - Utilisez les constantes pour les valeurs qui ne changent pas et ne viennent pas d'un autre service. Quand des contantes ne sont utilisées que par un module qui peut être ré-utilisé dans d'autres applications, placez les constantes dans un seul fichier par module nommé comme le module. Tant que c'est possible, gardez les constantes dans le module principal dans un fichier `constants.js`. @@ -2715,9 +2714,9 @@ Utilisez des templates de fichier ou des fragments pour vous aider à suivre des ng-f // crée une factory Angular ng-m // crée un module Angular ``` - + **[Retour en haut de page](#table-des-matières)** - + ## Generateur Yeoman ###### [Style [Y260](#style-y260)] From f4d0dafa00238916c3b1e538c2046349513e486c Mon Sep 17 00:00:00 2001 From: John Papa Date: Wed, 4 Mar 2015 11:19:27 -0700 Subject: [PATCH 204/567] renamed all AngularJS to Angular --- README.md | 62 +++++++++++++++++++++++++++---------------------------- 1 file changed, 31 insertions(+), 31 deletions(-) diff --git a/README.md b/README.md index d4b508f0..f1d91be3 100644 --- a/README.md +++ b/README.md @@ -1,17 +1,17 @@ -# AngularJS Style Guide +# Angular Style Guide -*Opinionated AngularJS style guide for teams by [@john_papa](//twitter.com/john_papa)* +*Opinionated Angular style guide for teams by [@john_papa](//twitter.com/john_papa)* -If you are looking for an opinionated style guide for syntax, conventions, and structuring AngularJS applications, then step right in. These styles are based on my development experience with [AngularJS](//angularjs.org), presentations, [Pluralsight training courses](http://pluralsight.com/training/Authors/Details/john-papa) and working in teams. +If you are looking for an opinionated style guide for syntax, conventions, and structuring Angular applications, then step right in. These styles are based on my development experience with [Angular](//angularjs.org), presentations, [Pluralsight training courses](http://pluralsight.com/training/Authors/Details/john-papa) and working in teams. -The purpose of this style guide is to provide guidance on building AngularJS applications by showing the conventions I use and, more importantly, why I choose them. +The purpose of this style guide is to provide guidance on building Angular applications by showing the conventions I use and, more importantly, why I choose them. ->If you like this guide, check out my [AngularJS Patterns: Clean Code](http://jpapa.me/ngclean) course at Pluralsight. +>If you like this guide, check out my [Angular Patterns: Clean Code](http://jpapa.me/ngclean) course at Pluralsight. [![AngularJs Patterns: Clean Code](https://raw.githubusercontent.com/johnpapa/angularjs-styleguide/master/assets/ng-clean-code-banner.png)](http://jpapa.me/ngclean) ## Community Awesomeness and Credit -Never work in a vacuum. I find that the AngularJS community is an incredible group who are passionate about sharing experiences. As such, a friend and AngularJS expert Todd Motto and I have collaborated on many styles and conventions. We agree on most, and some we diverge. I encourage you to check out [Todd's guidelines](https://github.com/toddmotto/angularjs-styleguide) to get a sense for his approach and how it compares. +Never work in a vacuum. I find that the Angular community is an incredible group who are passionate about sharing experiences. As such, a friend and Angular expert Todd Motto and I have collaborated on many styles and conventions. We agree on most, and some we diverge. I encourage you to check out [Todd's guidelines](https://github.com/toddmotto/angularjs-styleguide) to get a sense for his approach and how it compares. Many of my styles have been from the many pair programming sessions [Ward Bell](http://twitter.com/wardbell) and I have had. While we don't always agree, my friend Ward has certainly helped influence the ultimate evolution of this guide. @@ -50,7 +50,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see 1. [Yeoman Generator](#yeoman-generator) 1. [Routing](#routing) 1. [Task Automation](#task-automation) - 1. [AngularJS Docs](#angularjs-docs) + 1. [Angular Docs](#angularjs-docs) 1. [Contributing](#contributing) 1. [License](#license) @@ -113,7 +113,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see ### JavaScript Closures ###### [Style [Y010](#style-y010)] - - Wrap AngularJS components in an Immediately Invoked Function Expression (IIFE). + - Wrap Angular components in an Immediately Invoked Function Expression (IIFE). *Why?*: An IIFE removes variables from the global scope. This helps prevent variables and function declarations from living longer than expected in the global scope, which also helps avoid variable collisions. @@ -680,7 +680,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see - Services are instantiated with the `new` keyword, use `this` for public methods and variables. Since these are so similar to factories, use a factory instead for consistency. - Note: [All AngularJS services are singletons](https://docs.angularjs.org/guide/services). This means that there is only one instance of a given service per injector. + Note: [All Angular services are singletons](https://docs.angularjs.org/guide/services). This means that there is only one instance of a given service per injector. ```javascript // service @@ -724,7 +724,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see - Factories are singletons and return an object that contains the members of the service. - Note: [All AngularJS services are singletons](https://docs.angularjs.org/guide/services). + Note: [All Angular services are singletons](https://docs.angularjs.org/guide/services). ### Accessible Members Up Top ###### [Style [Y052](#style-y052)] @@ -1114,7 +1114,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see *Why?*: The unique short prefix identifies the directive's context and origin. For example a prefix of `cc-` may indicate that the directive is part of a CodeCamper app while `acme-` may indicate a directive for the Acme company. - Note: Avoid `ng-` as these are reserved for AngularJS directives. Research widely used directives to avoid naming conflicts, such as `ion-` for the [Ionic Framework](http://ionicframework.com/). + Note: Avoid `ng-` as these are reserved for Angular directives. Research widely used directives to avoid naming conflicts, such as `ion-` for the [Ionic Framework](http://ionicframework.com/). ### Restrict to Elements and Attributes ###### [Style [Y074](#style-y074)] @@ -1125,7 +1125,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see *Why?*: While we can allow the directive to be used as a class, if the directive is truly acting as an element it makes more sense as an element or at least as an attribute. - Note: EA is the default for AngularJS 1.3 + + Note: EA is the default for Angular 1.3 + ```html @@ -1453,7 +1453,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see - Avoid using the shortcut syntax of declaring dependencies without using a minification-safe approach. - *Why?*: The parameters to the component (e.g. controller, factory, etc) will be converted to mangled variables. For example, `common` and `dataservice` may become `a` or `b` and not be found by AngularJS. + *Why?*: The parameters to the component (e.g. controller, factory, etc) will be converted to mangled variables. For example, `common` and `dataservice` may become `a` or `b` and not be found by Angular. ```javascript /* avoid - not minification-safe*/ @@ -1475,11 +1475,11 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see ### Manually Identify Dependencies ###### [Style [Y091](#style-y091)] - - Use `$inject` to manually identify your dependencies for AngularJS components. + - Use `$inject` to manually identify your dependencies for Angular components. *Why?*: This technique mirrors the technique used by [`ng-annotate`](https://github.com/olov/ng-annotate), which I recommend for automating the creation of minification safe dependencies. If `ng-annotate` detects injection has already been made, it will not duplicate it. - *Why?*: This safeguards your dependencies from being vulnerable to minification issues when parameters may be mangled. For example, `common` and `dataservice` may become `a` or `b` and not be found by AngularJS. + *Why?*: This safeguards your dependencies from being vulnerable to minification issues when parameters may be mangled. For example, `common` and `dataservice` may become `a` or `b` and not be found by Angular. *Why?*: Avoid creating in-line dependencies as long lists can be difficult to read in the array. Also it can be confusing that the array is a series of strings while the last item is the component's function. @@ -1549,7 +1549,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see ### Manually Identify Route Resolver Dependencies ###### [Style [Y092](#style-y092)] - - Use $inject to manually identify your route resolver dependencies for AngularJS components. + - Use $inject to manually identify your route resolver dependencies for Angular components. *Why?*: This technique breaks out the anonymous function for the route resolver, making it easier to read. @@ -1653,7 +1653,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see } ``` - > Note: Starting from AngularJS 1.3 use the [`ngApp`](https://docs.angularjs.org/api/ng/directive/ngApp) directive's `ngStrictDi` parameter. When present the injector will be created in "strict-di" mode causing the application to fail to invoke functions which do not use explicit function annotation (these may not be minification safe). Debugging info will be logged to the console to help track down the offending code. + > Note: Starting from Angular 1.3 use the [`ngApp`](https://docs.angularjs.org/api/ng/directive/ngApp) directive's `ngStrictDi` parameter. When present the injector will be created in "strict-di" mode causing the application to fail to invoke functions which do not use explicit function annotation (these may not be minification safe). Debugging info will be logged to the console to help track down the offending code. `` ### Use Gulp or Grunt for ng-annotate @@ -1695,7 +1695,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see - Use a [decorator](https://docs.angularjs.org/api/auto/service/$provide#decorator), at config time using the [`$provide`](https://docs.angularjs.org/api/auto/service/$provide) service, on the [`$exceptionHandler`](https://docs.angularjs.org/api/ng/service/$exceptionHandler) service to perform custom actions when exceptions occur. - *Why?*: Provides a consistent way to handle uncaught AngularJS exceptions for development-time or run-time. + *Why?*: Provides a consistent way to handle uncaught Angular exceptions for development-time or run-time. Note: Another option is to override the service instead of using a decorator. This is a fine option, but if you want to keep the default behavior and extend it a decorator is recommended. @@ -2221,7 +2221,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see - Create an application root module whose role is pull together all of the modules and features of your application. Name this for your application. - *Why?*: AngularJS encourages modularity and separation patterns. Creating an application root module whose role is to tie your other modules together provides a very straightforward way to add or remove modules from your application. + *Why?*: Angular encourages modularity and separation patterns. Creating an application root module whose role is to tie your other modules together provides a very straightforward way to add or remove modules from your application. ### Keep the App Module Thin ###### [Style [Y162](#style-y162)] @@ -2263,7 +2263,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see *Why?*: Intra-App features such as shared data services become easy to locate and share from within `app.core` (choose your favorite name for this module). - Note: This is a strategy for consistency. There are many good options here. Choose one that is consistent, follows AngularJS's dependency rules, and is easy to maintain and scale. + Note: This is a strategy for consistency. There are many good options here. Choose one that is consistent, follows Angular's dependency rules, and is easy to maintain and scale. > My structures vary slightly between projects but they all follow these guidelines for structure and modularity. The implementation may vary depending on the features and the team. In other words, don't get hung up on an exact like-for-like structure but do justify your structure using consistency, maintainability, and efficiency in mind. @@ -2341,7 +2341,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see - Use [`$timeout`](https://docs.angularjs.org/api/ng/service/$timeout) and [`$interval`](https://docs.angularjs.org/api/ng/service/$interval) instead of `setTimeout` and `setInterval` . - *Why?*: These services are wrapped by Angular and more easily testable and handle AngularJS's digest cycle thus keeping data binding in sync. + *Why?*: These services are wrapped by Angular and more easily testable and handle Angular's digest cycle thus keeping data binding in sync. **[Back to top](#table-of-contents)** @@ -2380,7 +2380,7 @@ Unit testing helps maintain clean code, as such I included some of my recommenda - Use [Jasmine](http://jasmine.github.io/) or [Mocha](http://mochajs.org) for unit testing. - *Why?*: Both Jasmine and Mocha are widely used in the AngularJS community. Both are stable, well maintained, and provide robust testing features. + *Why?*: Both Jasmine and Mocha are widely used in the Angular community. Both are stable, well maintained, and provide robust testing features. Note: When using Mocha, also consider choosing an assert library such as [Chai](http://chaijs.com). @@ -2469,7 +2469,7 @@ Unit testing helps maintain clean code, as such I included some of my recommenda ### Usage ###### [Style [Y210](#style-y210)] - - Use subtle [animations with AngularJS](https://docs.angularjs.org/guide/animations) to transition between states for views and primary visual elements. Include the [ngAnimate module](https://docs.angularjs.org/api/ngAnimate). The 3 keys are subtle, smooth, seamless. + - Use subtle [animations with Angular](https://docs.angularjs.org/guide/animations) to transition between states for views and primary visual elements. Include the [ngAnimate module](https://docs.angularjs.org/api/ngAnimate). The 3 keys are subtle, smooth, seamless. *Why?*: Subtle animations can improve User Experience when used appropriately. @@ -2493,7 +2493,7 @@ Unit testing helps maintain clean code, as such I included some of my recommenda *Why?*: animate.css is widely used and tested. - Note: See this [great post by Matias Niemelä on AngularJS animations](http://www.yearofmoo.com/2013/08/remastered-animation-in-angularjs-1-2.html) + Note: See this [great post by Matias Niemelä on Angular animations](http://www.yearofmoo.com/2013/08/remastered-animation-in-angularjs-1-2.html) **[Back to top](#table-of-contents)** @@ -2631,7 +2631,7 @@ Unit testing helps maintain clean code, as such I included some of my recommenda ### Vendor Globals ###### [Style [Y240](#style-y240)] - - Create an AngularJS Constant for vendor libraries' global variables. + - Create an Angular Constant for vendor libraries' global variables. *Why?*: Provides a way to inject vendor libraries that otherwise are globals. This improves code testability by allowing you to more easily know what the dependencies of your components are (avoids leaky abstractions). It also allows you to mock these dependencies, where it makes sense. @@ -2682,7 +2682,7 @@ Use file templates or snippets to help follow consistent styles and patterns. He ### Sublime Text ###### [Style [Y250](#style-y250)] - - AngularJS snippets that follow these styles and guidelines. + - Angular snippets that follow these styles and guidelines. - Download the [Sublime Angular snippets](assets/sublime-angular-snippets.zip?raw=true) - Place it in your Packages folder @@ -2699,7 +2699,7 @@ Use file templates or snippets to help follow consistent styles and patterns. He ### Visual Studio ###### [Style [Y251](#style-y251)] - - AngularJS file templates that follow these styles and guidelines can be found at [SideWaffle](http://www.sidewaffle.com) + - Angular file templates that follow these styles and guidelines can be found at [SideWaffle](http://www.sidewaffle.com) - Download the [SideWaffle](http://www.sidewaffle.com) Visual Studio extension (vsix file) - Run the vsix file @@ -2708,9 +2708,9 @@ Use file templates or snippets to help follow consistent styles and patterns. He ### WebStorm ###### [Style [Y252](#style-y252)] - - AngularJS snippets and file templates that follow these styles and guidelines. You can import them into your WebStorm settings: + - Angular snippets and file templates that follow these styles and guidelines. You can import them into your WebStorm settings: - - Download the [WebStorm AngularJS file templates and snippets](assets/webstorm-angular-file-template.settings.jar?raw=true) + - Download the [WebStorm Angular file templates and snippets](assets/webstorm-angular-file-template.settings.jar?raw=true) - Open WebStorm and go to the `File` menu - Choose the `Import Settings` menu option - Select the file and click `OK` @@ -2725,7 +2725,7 @@ Use file templates or snippets to help follow consistent styles and patterns. He ### Atom ###### [Style [Y253](#style-y253)] - - AngularJS snippets that follow these styles and guidelines. + - Angular snippets that follow these styles and guidelines. ``` apm install angularjs-styleguide-snippets ``` @@ -2817,7 +2817,7 @@ Use [Gulp](http://gulpjs.com) or [Grunt](http://gruntjs.com) for creating automa **[Back to top](#table-of-contents)** -## AngularJS docs +## Angular docs For anything else, API reference, check the [Angular documentation](//docs.angularjs.org/api). ## Contributing From 83fa06b683590fb0347badd9a64bab6e3dad3a96 Mon Sep 17 00:00:00 2001 From: John Papa Date: Wed, 4 Mar 2015 11:22:14 -0700 Subject: [PATCH 205/567] renamed rest of references to angularness where links wouldn't break --- README.md | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index f1d91be3..838d7dbd 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ The purpose of this style guide is to provide guidance on building Angular appli >If you like this guide, check out my [Angular Patterns: Clean Code](http://jpapa.me/ngclean) course at Pluralsight. - [![AngularJs Patterns: Clean Code](https://raw.githubusercontent.com/johnpapa/angularjs-styleguide/master/assets/ng-clean-code-banner.png)](http://jpapa.me/ngclean) + [![AngularJs Patterns: Clean Code](https://raw.githubusercontent.com/johnpapa/angular-styleguide/master/assets/ng-clean-code-banner.png)](http://jpapa.me/ngclean) ## Community Awesomeness and Credit Never work in a vacuum. I find that the Angular community is an incredible group who are passionate about sharing experiences. As such, a friend and Angular expert Todd Motto and I have collaborated on many styles and conventions. We agree on most, and some we diverge. I encourage you to check out [Todd's guidelines](https://github.com/toddmotto/angularjs-styleguide) to get a sense for his approach and how it compares. @@ -19,7 +19,7 @@ Many of my styles have been from the many pair programming sessions [Ward Bell]( While this guide explains the *what*, *why* and *how*, I find it helpful to see them in practice. This guide is accompanied by a sample application that follows these styles and patterns. You can find the [sample application (named modular) here](https://github.com/johnpapa/ng-demos) in the `modular` folder. Feel free to grab it, clone it, or fork it. [Instructions on running it are in its readme](https://github.com/johnpapa/ng-demos/tree/master/modular). ##Translations -[Translations of this Angular style guide](https://github.com/johnpapa/angularjs-styleguide/tree/master/i18n) are maintained by the community and can be found here. +[Translations of this Angular style guide](https://github.com/johnpapa/angular-styleguide/tree/master/i18n) are maintained by the community and can be found here. ## Table of Contents @@ -50,7 +50,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see 1. [Yeoman Generator](#yeoman-generator) 1. [Routing](#routing) 1. [Task Automation](#task-automation) - 1. [Angular Docs](#angularjs-docs) + 1. [Angular Docs](#angular-docs) 1. [Contributing](#contributing) 1. [License](#license) @@ -440,7 +440,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see } ``` - ![Controller Using "Above the Fold"](https://raw.githubusercontent.com/johnpapa/angularjs-styleguide/master/assets/above-the-fold-1.png) + ![Controller Using "Above the Fold"](https://raw.githubusercontent.com/johnpapa/angular-styleguide/master/assets/above-the-fold-1.png) Note: If the function is a 1 liner consider keeping it right up top, as long as readability is not affected. @@ -781,7 +781,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see This way bindings are mirrored across the host object, primitive values cannot update alone using the revealing module pattern - ![Factories Using "Above the Fold"](https://raw.githubusercontent.com/johnpapa/angularjs-styleguide/master/assets/above-the-fold-2.png) + ![Factories Using "Above the Fold"](https://raw.githubusercontent.com/johnpapa/angular-styleguide/master/assets/above-the-fold-2.png) ### Function Declarations to Hide Implementation Details ###### [Style [Y053](#style-y053)] @@ -2162,7 +2162,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see session-detail.controller.js ``` - ![Sample App Structure](https://raw.githubusercontent.com/johnpapa/angularjs-styleguide/master/assets/modularity-2.png) + ![Sample App Structure](https://raw.githubusercontent.com/johnpapa/angular-styleguide/master/assets/modularity-2.png) Note: Do not use structuring using folders-by-type. This requires moving to multiple folders when working on a feature and gets unwieldy quickly as the app grows to 5, 10 or 25+ views and controllers (and other features), which makes it more difficult than folder-by-feature to locate files. @@ -2255,7 +2255,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see - The application root module depends on the app specific feature modules and any shared or reusable modules. - ![Modularity and Dependencies](https://raw.githubusercontent.com/johnpapa/angularjs-styleguide/master/assets/modularity-1.png) + ![Modularity and Dependencies](https://raw.githubusercontent.com/johnpapa/angular-styleguide/master/assets/modularity-1.png) *Why?*: The main app module contains a quickly identifiable manifest of the application's features. @@ -2433,7 +2433,7 @@ Unit testing helps maintain clean code, as such I included some of my recommenda /* global sinon, describe, it, afterEach, beforeEach, expect, inject */ ``` - ![Testing Tools](https://raw.githubusercontent.com/johnpapa/angularjs-styleguide/master/assets/testing-tools.png) + ![Testing Tools](https://raw.githubusercontent.com/johnpapa/angular-styleguide/master/assets/testing-tools.png) ### Organizing Tests ###### [Style [Y197](#style-y197)] From 383076a0df8725a7282456a70b69b36228b22c93 Mon Sep 17 00:00:00 2001 From: John Papa Date: Wed, 4 Mar 2015 22:54:40 -0700 Subject: [PATCH 206/567] added filters. closes #48 --- README.md | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/README.md b/README.md index 838d7dbd..6521dc5e 100644 --- a/README.md +++ b/README.md @@ -50,6 +50,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see 1. [Yeoman Generator](#yeoman-generator) 1. [Routing](#routing) 1. [Task Automation](#task-automation) + 1. [Filters](#filters) 1. [Angular Docs](#angular-docs) 1. [Contributing](#contributing) 1. [License](#license) @@ -2817,6 +2818,16 @@ Use [Gulp](http://gulpjs.com) or [Grunt](http://gruntjs.com) for creating automa **[Back to top](#table-of-contents)** +## Filters + +###### [Style [Y420](#style-y420)] + + - Avoid using filters for scanning all properties of a complex object graph. Use filters for select properties. + + *Why?*: Filters can easily be abused and negatively effect performance if not used wisely, for example when a filter hits a large and deep object graph. + +**[Back to top](#table-of-contents)** + ## Angular docs For anything else, API reference, check the [Angular documentation](//docs.angularjs.org/api). From a9aaaa015ab5fcb0458a080c61cc820b8ce00095 Mon Sep 17 00:00:00 2001 From: John Papa Date: Wed, 4 Mar 2015 23:06:10 -0700 Subject: [PATCH 207/567] minor cleanup --- README.md | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 6521dc5e..4f4738c5 100644 --- a/README.md +++ b/README.md @@ -6,14 +6,14 @@ If you are looking for an opinionated style guide for syntax, conventions, and s The purpose of this style guide is to provide guidance on building Angular applications by showing the conventions I use and, more importantly, why I choose them. ->If you like this guide, check out my [Angular Patterns: Clean Code](http://jpapa.me/ngclean) course at Pluralsight. +>If you like this guide, check out my [Angular Patterns: Clean Code](http://jpapa.me/ngclean) course at Pluralsight which is a companion to this guide. [![AngularJs Patterns: Clean Code](https://raw.githubusercontent.com/johnpapa/angular-styleguide/master/assets/ng-clean-code-banner.png)](http://jpapa.me/ngclean) ## Community Awesomeness and Credit Never work in a vacuum. I find that the Angular community is an incredible group who are passionate about sharing experiences. As such, a friend and Angular expert Todd Motto and I have collaborated on many styles and conventions. We agree on most, and some we diverge. I encourage you to check out [Todd's guidelines](https://github.com/toddmotto/angularjs-styleguide) to get a sense for his approach and how it compares. -Many of my styles have been from the many pair programming sessions [Ward Bell](http://twitter.com/wardbell) and I have had. While we don't always agree, my friend Ward has certainly helped influence the ultimate evolution of this guide. +Many of my styles have been from the many pair programming sessions [Ward Bell](http://twitter.com/wardbell) and I have had. My friend Ward has certainly helped influence the ultimate evolution of this guide. ## See the Styles in a Sample App While this guide explains the *what*, *why* and *how*, I find it helpful to see them in practice. This guide is accompanied by a sample application that follows these styles and patterns. You can find the [sample application (named modular) here](https://github.com/johnpapa/ng-demos) in the `modular` folder. Feel free to grab it, clone it, or fork it. [Instructions on running it are in its readme](https://github.com/johnpapa/ng-demos/tree/master/modular). @@ -552,7 +552,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see } ``` -### Defer Controller Logic +### Defer Controller Logic to Services ###### [Style [Y035](#style-y035)] - Defer logic in a controller by delegating to services and factories. @@ -563,6 +563,8 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see *Why?*: Removes dependencies and hides implementation details from the controller. + *Why?*: Keeps the controller slim, trim, and focused. + ```javascript /* avoid */ @@ -965,7 +967,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see ### Return a Promise from Data Calls ###### [Style [Y061](#style-y061)] - - When calling a data service that returns a promise such as $http, return a promise in your calling function too. + - When calling a data service that returns a promise such as `$http`, return a promise in your calling function too. *Why?*: You can chain the promises together and take further action after the data call completes and resolves or rejects the promise. From e4a14e62635185a225c4ed6f4d78a169b3c73cfa Mon Sep 17 00:00:00 2001 From: John Papa Date: Wed, 4 Mar 2015 23:15:59 -0700 Subject: [PATCH 208/567] made y091 more clear for directives --- README.md | 32 ++++++++++++++++++-------------- 1 file changed, 18 insertions(+), 14 deletions(-) diff --git a/README.md b/README.md index 4f4738c5..3baa4ca9 100644 --- a/README.md +++ b/README.md @@ -1353,7 +1353,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see *Why?*: A controller may require data before it loads. That data may come from a promise via a custom factory or [$http](https://docs.angularjs.org/api/ng/service/$http). Using a [route resolve](https://docs.angularjs.org/api/ngRoute/provider/$routeProvider) allows the promise to resolve before the controller logic executes, so it might take action based on that data from the promise. - *Why?*: The code executes after the route and in the controller’s activate function. The View starts to load right away. Data binding kicks in when the activate promise resolves. A “busy” animation can be shown during the view transition (via ng-view or ui-view) + *Why?*: The code executes after the route and in the controller’s activate function. The View starts to load right away. Data binding kicks in when the activate promise resolves. A “busy” animation can be shown during the view transition (via `ng-view` or `ui-view`) Note: The code executes before the route via a promise. Rejecting the promise cancels the route. Resolve makes the new view wait for the route to resolve. A “busy” animation can be shown before the resolve and through the view transition. If you want to get to the View faster and do not require a checkpoint to decide if you can get to the View, consider the [controller `activate` technique](#style-y080) instead. @@ -1519,33 +1519,37 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see } ``` - Note: When your function is below a return statement the $inject may be unreachable (this may happen in a directive). You can solve this by either moving the $inject above the return statement or by using the alternate array injection syntax. - - Note: [`ng-annotate 0.10.0`](https://github.com/olov/ng-annotate) introduced a feature where it moves the `$inject` to where it is reachable. + Note: When your function is below a return statement the `$inject` may be unreachable (this may happen in a directive). You can solve this by moving the Controller outside of the directive. ```javascript + /* avoid */ // inside a directive definition function outer() { - return { - controller: DashboardPanel, + var ddo = { + controller: DashboardPanelController, + controllerAs: 'vm' }; + return ddo; - DashboardPanel.$inject = ['logger']; // Unreachable - function DashboardPanel(logger) { + DashboardPanelController.$inject = ['logger']; // Unreachable + function DashboardPanelController(logger) { } } ``` ```javascript - // inside a directive definition + /* recommended */ + // outside a directive definition function outer() { - DashboardPanel.$inject = ['logger']; // reachable - return { - controller: DashboardPanel, + var ddo = { + controller: DashboardPanelController, + controllerAs: 'vm' }; + return ddo; + } - function DashboardPanel(logger) { - } + DashboardPanelController.$inject = ['logger']; + function DashboardPanelController(logger) { } ``` From c0e5ddda967bdd3c4c8485177392d04528572a86 Mon Sep 17 00:00:00 2001 From: John Papa Date: Wed, 4 Mar 2015 23:20:54 -0700 Subject: [PATCH 209/567] clarify the note on ng-strict-di --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 3baa4ca9..0b241e42 100644 --- a/README.md +++ b/README.md @@ -1556,7 +1556,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see ### Manually Identify Route Resolver Dependencies ###### [Style [Y092](#style-y092)] - - Use $inject to manually identify your route resolver dependencies for Angular components. + - Use `$inject` to manually identify your route resolver dependencies for Angular components. *Why?*: This technique breaks out the anonymous function for the route resolver, making it easier to read. @@ -1568,7 +1568,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see $routeProvider .when('/avengers', { templateUrl: 'avengers.html', - controller: 'Avengers', + controller: 'AvengersController', controllerAs: 'vm', resolve: { moviesPrepService: moviePrepService @@ -1660,7 +1660,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see } ``` - > Note: Starting from Angular 1.3 use the [`ngApp`](https://docs.angularjs.org/api/ng/directive/ngApp) directive's `ngStrictDi` parameter. When present the injector will be created in "strict-di" mode causing the application to fail to invoke functions which do not use explicit function annotation (these may not be minification safe). Debugging info will be logged to the console to help track down the offending code. + > Note: Starting from Angular 1.3 you can use the [`ngApp`](https://docs.angularjs.org/api/ng/directive/ngApp) directive's `ngStrictDi` parameter to detect any potentially missing magnification safe dependencies. When present the injector will be created in "strict-di" mode causing the application to fail to invoke functions which do not use explicit function annotation (these may not be minification safe). Debugging info will be logged to the console to help track down the offending code. I prefer to only use `ng-strict-di` for debugging purposes only. `` ### Use Gulp or Grunt for ng-annotate From 9b885e6bf177bd333480b0aa1c81e1218e7f47b0 Mon Sep 17 00:00:00 2001 From: John Papa Date: Wed, 4 Mar 2015 23:23:19 -0700 Subject: [PATCH 210/567] clarified coice of naming controllers --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 0b241e42..15b0a1fd 100644 --- a/README.md +++ b/README.md @@ -1675,6 +1675,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see ```javascript gulp.task('js', ['jshint'], function() { var source = pkg.paths.js; + return gulp.src(source) .pipe(sourcemaps.init()) .pipe(concat('all.min.js', {newLine: ';'})) @@ -1885,7 +1886,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see avenger-profile.directive.spec.js ``` - Note: Another common convention is naming controller files without the word `controller` in the file name such as `avengers.js` instead of `avengers.controller.js`. All other conventions still hold using a suffix of the type. Controllers are the most common type of component so this just saves typing and is still easily identifiable. I recommend you choose 1 convention and be consistent for your team. + Note: Another common convention is naming controller files without the word `controller` in the file name such as `avengers.js` instead of `avengers.controller.js`. All other conventions still hold using a suffix of the type. Controllers are the most common type of component so this just saves typing and is still easily identifiable. I recommend you choose 1 convention and be consistent for your team. My preference is `avengers.controller.js`. ```javascript /** From a161ba683339c115aa1bd7cbe7759bbb565643b9 Mon Sep 17 00:00:00 2001 From: John Papa Date: Wed, 4 Mar 2015 23:24:33 -0700 Subject: [PATCH 211/567] refined naming for controllers --- README.md | 23 ++++------------------- 1 file changed, 4 insertions(+), 19 deletions(-) diff --git a/README.md b/README.md index 15b0a1fd..da42c7ec 100644 --- a/README.md +++ b/README.md @@ -1933,36 +1933,21 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see // avengers.controller.js angular .module - .controller('HeroAvengers', HeroAvengers); + .controller('HeroAvengersController', HeroAvengersController); - function HeroAvengers() { } + function HeroAvengersController() { } ``` ### Controller Name Suffix ###### [Style [Y124](#style-y124)] - - Append the controller name with the suffix `Controller` or with no suffix. Choose 1, not both. + - Append the controller name with the suffix `Controller`. *Why?*: The `Controller` suffix is more commonly used and is more explicitly descriptive. - *Why?*: Omitting the suffix is more succinct and the controller is often easily identifiable even without the suffix. - ```javascript /** - * recommended: Option 1 - */ - - // avengers.controller.js - angular - .module - .controller('Avengers', Avengers); - - function Avengers() { } - ``` - - ```javascript - /** - * recommended: Option 2 + * recommended */ // avengers.controller.js From ecc2d12690900cea8040aa10a910d3c024aedf36 Mon Sep 17 00:00:00 2001 From: John Papa Date: Wed, 4 Mar 2015 23:27:34 -0700 Subject: [PATCH 212/567] fixed routes in structure --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index da42c7ec..3d1e2a26 100644 --- a/README.md +++ b/README.md @@ -2125,7 +2125,6 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see app/ app.module.js app.config.js - app.routes.js components/ calendar.directive.js calendar.directive.html @@ -2139,6 +2138,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see people/ attendees.html attendees.controller.js + people.routes.js speakers.html speakers.controller.js speaker-detail.html @@ -2151,6 +2151,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see sessions/ sessions.html sessions.controller.js + sessions.routes.js session-detail.html session-detail.controller.js ``` From 1ef36bffe2a7ef27de6b7bbfd4fd47b66cc831c8 Mon Sep 17 00:00:00 2001 From: John Papa Date: Wed, 4 Mar 2015 23:29:35 -0700 Subject: [PATCH 213/567] added mocha preference --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 3d1e2a26..7ec248d3 100644 --- a/README.md +++ b/README.md @@ -2376,7 +2376,7 @@ Unit testing helps maintain clean code, as such I included some of my recommenda *Why?*: Both Jasmine and Mocha are widely used in the Angular community. Both are stable, well maintained, and provide robust testing features. - Note: When using Mocha, also consider choosing an assert library such as [Chai](http://chaijs.com). + Note: When using Mocha, also consider choosing an assert library such as [Chai](http://chaijs.com). I prefer Mocha. ### Test Runner ###### [Style [Y192](#style-y192)] From 34237f95deac21624821e329bbdb9624cba1c478 Mon Sep 17 00:00:00 2001 From: John Papa Date: Wed, 4 Mar 2015 23:30:34 -0700 Subject: [PATCH 214/567] sinon messages --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 7ec248d3..23887d74 100644 --- a/README.md +++ b/README.md @@ -2400,6 +2400,8 @@ Unit testing helps maintain clean code, as such I included some of my recommenda *Why?*: Sinon makes it easier to toggle between Jasmine and Mocha, if you want to try both. + *Why?*: Sinon has descriptive messages when tests fail the assertions. + ### Headless Browser ###### [Style [Y194](#style-y194)] From 94c44a4a7d92dc17be9696f87e749b010732a12e Mon Sep 17 00:00:00 2001 From: John Papa Date: Wed, 4 Mar 2015 23:31:36 -0700 Subject: [PATCH 215/567] fixed global jshint exclusions for tests --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 23887d74..99ca6ad6 100644 --- a/README.md +++ b/README.md @@ -2426,7 +2426,7 @@ Unit testing helps maintain clean code, as such I included some of my recommenda *Why?*: Your tests are code and require the same attention and code quality rules as all of your production code. However, global variables used by the testing framework, for example, can be relaxed by including this in your test specs. ```javascript - /* global sinon, describe, it, afterEach, beforeEach, expect, inject */ + /* jshint -W117, -W030 */ ``` ![Testing Tools](https://raw.githubusercontent.com/johnpapa/angular-styleguide/master/assets/testing-tools.png) From e8e02a8529476b2d101ca17ddf3902835e300ff4 Mon Sep 17 00:00:00 2001 From: John Papa Date: Wed, 4 Mar 2015 23:32:20 -0700 Subject: [PATCH 216/567] fixed global jshint exclusions for tests --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 99ca6ad6..5b68a738 100644 --- a/README.md +++ b/README.md @@ -2421,7 +2421,7 @@ Unit testing helps maintain clean code, as such I included some of my recommenda ### Alleviate Globals for JSHint Rules on Tests ###### [Style [Y196](#style-y196)] - - Relax the rules on your test code to allow for common globals such as `describe` and `expect`. + - Relax the rules on your test code to allow for common globals such as `describe` and `expect`. Relax the rules for expressions, as Mocha uses these. *Why?*: Your tests are code and require the same attention and code quality rules as all of your production code. However, global variables used by the testing framework, for example, can be relaxed by including this in your test specs. From 8466149a9ad2ba444bc0b8a38cf275f8cfc1d51c Mon Sep 17 00:00:00 2001 From: John Papa Date: Wed, 4 Mar 2015 23:37:28 -0700 Subject: [PATCH 217/567] added jscs --- README.md | 89 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 89 insertions(+) diff --git a/README.md b/README.md index 5b68a738..db40a168 100644 --- a/README.md +++ b/README.md @@ -45,6 +45,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see 1. [Animations](#animations) 1. [Comments](#comments) 1. [JSHint](#js-hint) + 1. [JSCS](#jscs) 1. [Constants](#constants) 1. [File Templates and Snippets](#file-templates-and-snippets) 1. [Yeoman Generator](#yeoman-generator) @@ -2622,6 +2623,94 @@ Unit testing helps maintain clean code, as such I included some of my recommenda **[Back to top](#table-of-contents)** +## JSCS + +### Use an Options File +###### [Style [Y235](#style-y235)] + + - Use JSCS for checking your coding styles your JavaScript and be sure to customize the JSCS options file and include in source control. See the [JSCS docs](http://www.jscs.info) for details on the options. + + *Why?*: Provides a first alert prior to committing any code to source control. + + *Why?*: Provides consistency across your team. + + ```javascript + { + "excludeFiles": ["node_modules/**", "bower_components/**"], + + "requireCurlyBraces": [ + "if", + "else", + "for", + "while", + "do", + "try", + "catch" + ], + "requireOperatorBeforeLineBreak": true, + "requireCamelCaseOrUpperCaseIdentifiers": true, + "maximumLineLength": { + "value": 100, + "allowComments": true, + "allowRegex": true + }, + "validateIndentation": 4, + "validateQuoteMarks": "'", + + "disallowMultipleLineStrings": true, + "disallowMixedSpacesAndTabs": true, + "disallowTrailingWhitespace": true, + "disallowSpaceAfterPrefixUnaryOperators": true, + "disallowMultipleVarDecl": null, + + "requireSpaceAfterKeywords": [ + "if", + "else", + "for", + "while", + "do", + "switch", + "return", + "try", + "catch" + ], + "requireSpaceBeforeBinaryOperators": [ + "=", "+=", "-=", "*=", "/=", "%=", "<<=", ">>=", ">>>=", + "&=", "|=", "^=", "+=", + + "+", "-", "*", "/", "%", "<<", ">>", ">>>", "&", + "|", "^", "&&", "||", "===", "==", ">=", + "<=", "<", ">", "!=", "!==" + ], + "requireSpaceAfterBinaryOperators": true, + "requireSpacesInConditionalExpression": true, + "requireSpaceBeforeBlockStatements": true, + "requireLineFeedAtFileEnd": true, + "disallowSpacesInsideObjectBrackets": "all", + "disallowSpacesInsideArrayBrackets": "all", + "disallowSpacesInsideParentheses": true, + + "validateJSDoc": { + "checkParamNames": true, + "requireParamTypes": true + }, + + "disallowMultipleLineBreaks": true, + + "disallowCommaBeforeLineBreak": null, + "disallowDanglingUnderscores": null, + "disallowEmptyBlocks": null, + "disallowMultipleLineStrings": null, + "disallowTrailingComma": null, + "requireCommaBeforeLineBreak": null, + "requireDotNotation": null, + "requireMultipleVarDecl": null, + "requireParenthesesAroundIIFE": true + } + ``` + +**[Back to top](#table-of-contents)** + ## Constants ### Vendor Globals From bd40584c20127000fc231962b00cf7354ebc285b Mon Sep 17 00:00:00 2001 From: John Papa Date: Wed, 4 Mar 2015 23:39:08 -0700 Subject: [PATCH 218/567] gulp preference --- README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index db40a168..b7ce8140 100644 --- a/README.md +++ b/README.md @@ -2880,7 +2880,9 @@ Client-side routing is important for creating a navigation flow between views an **[Back to top](#table-of-contents)** ## Task Automation -Use [Gulp](http://gulpjs.com) or [Grunt](http://gruntjs.com) for creating automated tasks. Gulp leans to code over configuration while Grunt leans to configuration over code. I personally prefer Gulp as I feel it is easier to read and write, but both are excellent. +Use [Gulp](http://gulpjs.com) or [Grunt](http://gruntjs.com) for creating automated tasks. + +> Gulp leans to code over configuration while Grunt leans to configuration over code. I personally prefer Gulp as I feel it is easier to read and write, but both are excellent. ###### [Style [Y400](#style-y400)] From ef16cf92f31f1baff983527b492a110cf56a169c Mon Sep 17 00:00:00 2001 From: John Papa Date: Wed, 4 Mar 2015 23:40:07 -0700 Subject: [PATCH 219/567] gulp preference --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index b7ce8140..0be121f3 100644 --- a/README.md +++ b/README.md @@ -2880,9 +2880,9 @@ Client-side routing is important for creating a navigation flow between views an **[Back to top](#table-of-contents)** ## Task Automation -Use [Gulp](http://gulpjs.com) or [Grunt](http://gruntjs.com) for creating automated tasks. +Use [Gulp](http://gulpjs.com) or [Grunt](http://gruntjs.com) for creating automated tasks. Gulp leans to code over configuration while Grunt leans to configuration over code. I personally prefer Gulp as I feel it is easier to read and write, but both are excellent. -> Gulp leans to code over configuration while Grunt leans to configuration over code. I personally prefer Gulp as I feel it is easier to read and write, but both are excellent. +> Learn more about gulp and patterns for task automation in my [Gulp Pluralsight course(http://jpapa.me/gulpps) ###### [Style [Y400](#style-y400)] From e8c8a184e809e62504779b98235aa5a5aa9182a3 Mon Sep 17 00:00:00 2001 From: John Papa Date: Wed, 4 Mar 2015 23:41:04 -0700 Subject: [PATCH 220/567] copyrite --- README.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 0be121f3..21b98893 100644 --- a/README.md +++ b/README.md @@ -2932,10 +2932,11 @@ Open an issue first to discuss potential changes/additions. If you have question _tldr; Use this guide. Attributions are appreciated._ -### (The MIT License) +### Copyright -Copyright (c) 2014 [John Papa](http://johnpapa.net) +Copyright (c) 2014-2015 [John Papa](http://johnpapa.net) +### (The MIT License) 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 From 0d5a323451619993d720e50d0ad012cd3d8a29da Mon Sep 17 00:00:00 2001 From: John Papa Date: Wed, 4 Mar 2015 23:46:08 -0700 Subject: [PATCH 221/567] gulp preference --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 21b98893..1a176128 100644 --- a/README.md +++ b/README.md @@ -2882,7 +2882,7 @@ Client-side routing is important for creating a navigation flow between views an ## Task Automation Use [Gulp](http://gulpjs.com) or [Grunt](http://gruntjs.com) for creating automated tasks. Gulp leans to code over configuration while Grunt leans to configuration over code. I personally prefer Gulp as I feel it is easier to read and write, but both are excellent. -> Learn more about gulp and patterns for task automation in my [Gulp Pluralsight course(http://jpapa.me/gulpps) +> Learn more about gulp and patterns for task automation in my [Gulp Pluralsight course](http://jpapa.me/gulpps) ###### [Style [Y400](#style-y400)] From 33549fe9dca787059d8d266edb26299dc0263ccc Mon Sep 17 00:00:00 2001 From: Xavier Haniquaut Date: Thu, 5 Mar 2015 12:00:43 +0100 Subject: [PATCH 222/567] [FR] Translate Filter section French translation for commit #383076a0 --- i18n/fr-FR.md | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/i18n/fr-FR.md b/i18n/fr-FR.md index 7d8af2bb..0056b0b4 100644 --- a/i18n/fr-FR.md +++ b/i18n/fr-FR.md @@ -54,6 +54,7 @@ Alors que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'a ét 1. [Générateur Yeoman](#générateur-yeoman) 1. [Routage](#routage) 1. [Automatisation des Tâches](#automatisation-des-taches) + 1. [Filtres](#filtres) 1. [Documentation AngularJS](#documentation-angularjs) 1. [Contribuer](#contribuer) 1. [License](#license) @@ -2789,6 +2790,16 @@ Utilisez [Gulp](http://gulpjs.com) ou [Grunt](http://gruntjs.com) pour créer de **[Retour en haut de page](#table-des-matières)** +## Filtres + +###### [Style [Y420](#style-y420)] + + - Évitez d'utiliser les filtres pour scanner toutes les propriété de l'arborescence d'un objet complexe. Utilisez les filtres pour sélectionner des propriétés. + + *Pourquoi ?*: les filtres peuvent être surutilisés et peuvent avoir des effets négatifs sur les performances s'ils ne sont pas utilisés de façon appropriée. Par exemple, quand un filtre touche un gros objet dont l'arborescence est profonde. + +**[Back to top](#table-of-contents)** + ## Documentation AngularJS Pour tout le reste, la référence des API, allez voir la [documentation Angular](//docs.angularjs.org/api). From f3594c2f3b152a06ea61564e7c42f06626d09eac Mon Sep 17 00:00:00 2001 From: John Papa Date: Thu, 5 Mar 2015 15:44:17 -0700 Subject: [PATCH 223/567] closes #271 --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 1a176128..8d104a18 100644 --- a/README.md +++ b/README.md @@ -1022,6 +1022,8 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see *Why?*: One directive per file is easy to maintain. + > Note: "**Best Practice**: Directives should clean up after themselves. You can use `element.on('$destroy', ...)` or `scope.$on('$destroy', ...)` to run a clean-up function when the directive is removed" ... from the Angular documentation + ```javascript /* avoid */ /* directives.js */ From f6ee444e731712a500780256e3b9bf8d418df03b Mon Sep 17 00:00:00 2001 From: Glen Davies Date: Sat, 7 Mar 2015 12:13:19 +1300 Subject: [PATCH 224/567] Added reference to JSHint Jasmine conf --- README.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/README.md b/README.md index 8d104a18..9c6c9bdb 100644 --- a/README.md +++ b/README.md @@ -2431,6 +2431,12 @@ Unit testing helps maintain clean code, as such I included some of my recommenda ```javascript /* jshint -W117, -W030 */ ``` + Or you can add the following to your JSHint Options file. + + ```javascript + "jasmine": true, + "mocha": true, + ``` ![Testing Tools](https://raw.githubusercontent.com/johnpapa/angular-styleguide/master/assets/testing-tools.png) From 628f3e0e848c711c64ce288a0861dbc07da51693 Mon Sep 17 00:00:00 2001 From: Xavier Haniquaut Date: Sat, 7 Mar 2015 15:21:58 +0100 Subject: [PATCH 225/567] [FR] Updates french translation from #a9aaaa to #d1e9f9 except #c0e5dd (if someone could help me) --- i18n/fr-FR.md | 248 ++++++++++++++++++++++++++++++++++---------------- 1 file changed, 171 insertions(+), 77 deletions(-) diff --git a/i18n/fr-FR.md b/i18n/fr-FR.md index 0056b0b4..e0b7407a 100644 --- a/i18n/fr-FR.md +++ b/i18n/fr-FR.md @@ -1,21 +1,21 @@ -# Le Guide de Style AngularJS +# Le Guide de Style Angular -*Le guide d'un point de vue personnel sur le style AngularJS par [@john_papa](//twitter.com/john_papa)* +*Le guide d'un point de vue personnel sur le style Angular par [@john_papa](//twitter.com/john_papa)* *Translated by [Eric Lemerdy](https://github.com/ericlemerdy)* >The [original English version](http://jpapa.me/ngstyles) is the source of truth, as it is maintained and updated first. -Si vous cherchez un guide de style pour la syntaxe, les conventions, et la structuration d'application AngularJS, alors vous êtes au bon endroit. Ces styles sont basés sur mon expérience de dévelopement avec [AngularJS](//angularjs.org), mes présentations, [mes cours sur Pluralsight](http://pluralsight.com/training/Authors/Details/john-papa) et mon travail au sein des équipes. +Si vous cherchez un guide de style pour la syntaxe, les conventions, et la structuration d'application Angular, alors vous êtes au bon endroit. Ces styles sont basés sur mon expérience de dévelopement avec [Angular](//angularjs.org), mes présentations, [mes cours sur Pluralsight](http://pluralsight.com/training/Authors/Details/john-papa) et mon travail au sein des équipes. -Le but de ce guide de style est de proposer des conseils sur le développement d'applications AngularJS en montrant les conventions que j'utilise et, plus important encore, les raisons des choix que j'ai pris. +Le but de ce guide de style est de proposer des conseils sur le développement d'applications Angular en montrant les conventions que j'utilise et, plus important encore, les raisons des choix que j'ai pris. >Si vous appréciez ce guide, visitez mon cours [AngularJS Patterns: Clean Code](http://jpapa.me/ngclean) sur Pluralsight. - [![AngularJs Patterns: Clean Code](https://raw.githubusercontent.com/johnpapa/angularjs-styleguide/master/assets/ng-clean-code-banner.png)](http://jpapa.me/ngclean) + [![AngularJs Patterns: Clean Code](https://raw.githubusercontent.com/johnpapa/angular-styleguide/master/assets/ng-clean-code-banner.png)](http://jpapa.me/ngclean) ## Suprématie de la Communauté et Remerciements -Ne jamais travailler dans le vide. J'ai trouvé que la communauté AngularJS est un incroyable groupe dont les membres ont à coeur de partager leurs expériences. Ainsi, un ami et expert AngularJS Todd Motto et moi avons collaboré sur de nombreux styles et conventions. Nous sommes d'accord sur la plupart, et nous divergeons sur d'autres. Je vous encourage à visiter [les guideslines de Todd](https://github.com/toddmotto/angularjs-styleguide) pour vous faire un sentiment sur son approche et en quoi elle est comparable. +Ne jamais travailler dans le vide. J'ai trouvé que la communauté Angular est un incroyable groupe dont les membres ont à coeur de partager leurs expériences. Ainsi, un ami et expert Angular Todd Motto et moi avons collaboré sur de nombreux styles et conventions. Nous sommes d'accord sur la plupart, et nous divergeons sur d'autres. Je vous encourage à visiter [les guideslines de Todd](https://github.com/toddmotto/angularjs-styleguide) pour vous faire un sentiment sur son approche et en quoi elle est comparable. De nombreux de mes styles proviennent des maintes scéances de pair programming que [Ward Bell](http://twitter.com/wardbell) et moi avons eu. Même si nous n'étions pas toujours d'accord, mon ami Ward a assurément contribué à influencer l'évolution ultime de ce guide. @@ -23,7 +23,7 @@ De nombreux de mes styles proviennent des maintes scéances de pair programming Alors que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'a été utile de les visualiser dans la pratique. Ce guide est accompagné par une application d'exemple qui suit ces styles et ces motifs. Vous pouvez trouver l'[application d'exemple (appellée modular) ici](https://github.com/johnpapa/ng-demos) dans le répertoire `modular`. Vous pouvez librement le récupérer, le cloner, ou le dupliquer pour le modifier. [Les instructions pour l'éxécuter sont contenues dans ce readme](https://github.com/johnpapa/ng-demos/tree/master/modular). ## Traductions -[Des traductions de ce guide stylistique Angular](https://github.com/johnpapa/angularjs-styleguide/tree/master/i18n) sont maintenues par la communauté et peuvent être trouvées ici. +[Des traductions de ce guide stylistique Angular](https://github.com/johnpapa/angular-styleguide/tree/master/i18n) sont maintenues par la communauté et peuvent être trouvées ici. ## Table des matières @@ -49,13 +49,14 @@ Alors que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'a ét 1. [Animations](#animations) 1. [Commentaires](#commentaires) 1. [JSHint](#js-hint) + 1. [JSCS](#jscs) 1. [Constantes](#constantes) 1. [Templates de Fichiers et Fragments](#templates-de-fichiers-et-fragments) 1. [Générateur Yeoman](#générateur-yeoman) 1. [Routage](#routage) 1. [Automatisation des Tâches](#automatisation-des-taches) 1. [Filtres](#filtres) - 1. [Documentation AngularJS](#documentation-angularjs) + 1. [Documentation Angular](#documentation-angular) 1. [Contribuer](#contribuer) 1. [License](#license) @@ -118,7 +119,7 @@ Alors que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'a ét ### Les Closures JavaScript ###### [Style [Y010](#style-y010)] - - Encapsuler les composants AngularJS dans une Immediately Invoked Function Expression (IIFE) ou Expression de Fonction Immédiatement Invoquée. + - Encapsuler les composants Angular dans une Immediately Invoked Function Expression (IIFE) ou Expression de Fonction Immédiatement Invoquée. *Pourquoi ?* : Une IIFE supprime les variables du scope global. Cela aide à éviter que les déclarations de variables et de fonctions ne vivent plus longtemps qu'attendu dans le scope global, ce qui aide aussi à éviter les collisions de variables. @@ -446,7 +447,7 @@ Alors que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'a ét } ``` - ![Les Controlleur Utilisant "Au dessus de la Réduction"](https://raw.githubusercontent.com/johnpapa/angularjs-styleguide/master/assets/above-the-fold-1.png) + ![Les Controlleur Utilisant "Au dessus de la Réduction"](https://raw.githubusercontent.com/johnpapa/angular-styleguide/master/assets/above-the-fold-1.png) Note : Si la fonction est un one-liner, considérez de la garder bien en haut, tant que la lisibilité n'est pas affectée. @@ -687,7 +688,7 @@ Alors que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'a ét - Les Services sont instanciés avec le mot clé `new`, utilisez `this` pour les méthodes publiques et les variables. Puisque ces derniers sont tellement similaires aux factories, utilisez à la place une factory pour la cohérence. - Note : [Tous les serices AngularJS services sont des singletons](https://docs.angularjs.org/guide/services). Celà signifie qu'il n'y a qu'une seule instance d'un service donné par injecteur. + Note : [Tous les serices Angular services sont des singletons](https://docs.angularjs.org/guide/services). Celà signifie qu'il n'y a qu'une seule instance d'un service donné par injecteur. ```javascript // service @@ -731,7 +732,7 @@ Alors que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'a ét - Les factories sont des singletons et renvoient un objet qui contient les membres du service. - Note : [Tous les services AngularJS sont des singletons](https://docs.angularjs.org/guide/services). + Note : [Tous les services Angular sont des singletons](https://docs.angularjs.org/guide/services). ### Membres Accessibles Tout en Haut ###### [Style [Y052](#style-y052)] @@ -788,7 +789,7 @@ Alors que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'a ét De cette façon, les bindings sont dupliqués à travers l'objet hôte, les valeurs primitives ne peuvant se mettre à jour toutes seules grâce au principe du module révélateur. - ![Factories Utilisants "Au dessus du Pliage"](https://raw.githubusercontent.com/johnpapa/angularjs-styleguide/master/assets/above-the-fold-2.png) + ![Factories Utilisants "Au dessus du Pliage"](https://raw.githubusercontent.com/johnpapa/angular-styleguide/master/assets/above-the-fold-2.png) ### Déclaration de Fonctions pour Cacher les Détails d'Implémentation ###### [Style [Y053](#style-y053)] @@ -1025,6 +1026,8 @@ Alors que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'a ét *Pourquoi ?* : Une directive par fichier est plus facilement maintenable. + > Note : "**Bonne pratique** : Les directives devraient pouvoir s'auto-nettoyer. Vous pouvez utiliser `element.on('$destroy', ...)` ou `scope.$on('$destroy', ...)` pour lancer une fonction de nettoyage quand une directive est enlevée" ... - Documentation d'Angular + ```javascript /* à éviter */ /* directives.js */ @@ -1121,7 +1124,7 @@ Alors que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'a ét *Pourquoi ?* : Le préfixe court et unique identifie le contexte et l'origine de la directive. Par exemple, un préfixe `cc-` peut indiquer que la directive fait partie de l'application CodeCamper alors que `acme-` peut indiquer une directive de la companie Acme. - Note : Evitez `ng-` car il est réservé pour les directives AngularJS. Cherchez les directives largement utilisées pour éviter les conflits de nom, tel que `ion-` pour le [Framework Ionic](http://ionicframework.com/). + Note : Evitez `ng-` car il est réservé pour les directives Angular. Cherchez les directives largement utilisées pour éviter les conflits de nom, tel que `ion-` pour le [Framework Ionic](http://ionicframework.com/). ### Restreindre aux Éléments et aux Attributs ###### [Style [Y074](#style-y074)] @@ -1132,7 +1135,7 @@ Alors que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'a ét *Pourquoi ?* : Même s'il est autorisé d'utiliser une directive en tant que classe, si la directive agit vraiement comme un élément, elle fait plus de sens en tant qu'élément ou au moins en tant qu'attribut. - Note : EA est la valeur par défaut avec AngularJS 1.3 + + Note : EA est la valeur par défaut avec Angular 1.3 + ```html @@ -1357,7 +1360,7 @@ Alors que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'a ét *Pourquoi ?* : Un controlleur pourrait avoir besoin de données avant qu'il se charge. Cette donnée pourrait venir d'une promesse via une factory personnalisée ou de [$http](https://docs.angularjs.org/api/ng/service/$http). Utiliser une [resolution de route](https://docs.angularjs.org/api/ngRoute/provider/$routeProvider) permet à la promesse de se résoudre avant que la logique du controlleur s'éxécute, ainsi on peut prendre des actions basées sur cette donnée à partir de la promesse. - *Pourquoi ?* : Le code s'éxécute après la route et dans la fonction activate du controlleur. La Vue commence à se charger tout de suite. Le data binding démarre quand la promesse d'activation se résoud. Une animation de "chargement" peut être affichée pendant que la vue opère la transition (via ng-view ou ui-view). + *Pourquoi ?* : Le code s'éxécute après la route et dans la fonction activate du controlleur. La Vue commence à se charger tout de suite. Le data binding démarre quand la promesse d'activation se résoud. Une animation de "chargement" peut être affichée pendant que la vue opère la transition (via `ng-view` ou `ui-view`). Note : Le code s'éxécute avant la route via une promesse. Le rejet de la promesse annule le routage. Sa résolution met la nouvelle vue en attente de la résolution du routage. Une animation de "chargement" peut être affichée avant la résolution et lorsque la vue entre en transition. Si vous voulez aller à la Vue plus vite et que vous n'avez pas besoin d'un point pour décider si vous voulez atteindre la Vue, il est conseillé d'utiliser la [technique de l'activation de controlleur](#style-y080) à la place. @@ -1460,7 +1463,7 @@ Alors que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'a ét - Eviter l'utilisation de la syntaxe raccourcie de déclaration des dépendances sans utiliser une approche sûre pour la minification. - *Pourquoi ?* : Les paramètres du composant (ex: controlleur, factory, etc.) seront converties en variables mutilées. Par exemple, ˋcommonˋet ˋdataserviceˋ deviendraient ˋaˋet ˋbˋ et ne seraient pas trouvées par AngularJS. + *Pourquoi ?* : Les paramètres du composant (ex: controlleur, factory, etc.) seront converties en variables mutilées. Par exemple, ˋcommonˋet ˋdataserviceˋ deviendraient ˋaˋet ˋbˋ et ne seraient pas trouvées par Angular. ```javascript /* à éviter - non sûr pour la minification */ @@ -1482,11 +1485,11 @@ Alors que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'a ét ### Identifier Manuellement les Dépendances ###### [Style [Y091](#style-y091)] - - Utilisez ˋ$injectˋpour identifier manuellement vos dépendances de composants AngularJS. + - Utilisez ˋ$injectˋpour identifier manuellement vos dépendances de composants Angular. *Pourquoi ? * : Cette technique est la même que celle utilisée par [`ng-annotate`](https://github.com/olov/ng-annotate), que je recommande pour automatiser la création de dépendances sûres pour la minification. Si ˋng-annotateˋ détecte que l'injection a déjà été faite, celà ne la dupliquera pas. - *Pourquoi ?* : Ca préserve vos dépendances d'être vulnérable aux problèmes de minification lorsque les paramètres sont mutilés. Par exemple, ˋcommonˋet ˋdataserviceˋpourraient devenir ˋaˋ et ˋbˋ et ne pas être trouvés par AngularJS. + *Pourquoi ?* : Ca préserve vos dépendances d'être vulnérable aux problèmes de minification lorsque les paramètres sont mutilés. Par exemple, ˋcommonˋet ˋdataserviceˋpourraient devenir ˋaˋ et ˋbˋ et ne pas être trouvés par Angular. *Pourquoi ?* : Eviter de créer en ligne une longue liste de dépendances peut rendre le tableau difficile à lire. De même, il peut entraîner une confusion dans la mesure où le tableau est une série de chaînes de caratères alors que le dernier élément est le nom de la fonction du composant. @@ -1523,40 +1526,43 @@ Alors que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'a ét } ``` - Note : Lorsque votre fonction est sous une instruction de return, le $inject peut ne pas être accessible (cela pourrait arriver dans une directive). Vous pouvez résoudre ça soit en déplaçant le $inject au dessus de l'instruction de return soit en utilisant la syntaxe d'injection avec le tableau. - - Note : [`ng-annotate 0.10.0`](https://github.com/olov/ng-annotate) a introduit une fonctionnalité où il déplace le ˋ$injectˋ là où il devient accessible. + Note : Lorsque votre fonction est sous une instruction de return, le $inject peut ne pas être accessible (cela pourrait arriver dans une directive). Vous pouvez vous en sortir en bougeant le controlleur en dehors de la directive. ```javascript + /* À éviter */ // à l'intérieur d'une définition de directive function outer() { - return { - controller: DashboardPanel, + var ddo = { + controller: DashboardPanelController, + controllerAs: 'vm' }; + return ddo - DashboardPanel.$inject = ['logger']; // Unreachable - function DashboardPanel(logger) { + DashboardPanelController.$inject = ['logger']; // Inatteignable + function DashboardPanelController(logger) { } } ``` ```javascript - // à l'intérieur d'une définition de directive. + /* recommandé */ + // A l'exterieur d'une définition de directive function outer() { - DashboardPanel.$inject = ['logger']; // reachable - return { - controller: DashboardPanel, + var ddo = { + controller: DashboardPanelController, + controllerAs: 'vm' }; - - function DashboardPanel(logger) { - } + return ddo; + } + DashboardPanelController.$inject = ['logger']; + function DashboardPanelController(logger) { } ``` ### Identifier Manuellement les Dépendances du Route Resolver ###### [Style [Y092](#style-y092)] - - Utilisez $inject pour identifier manuellement vos dépendances du route resolver pour les composants AngularJS. + - Utilisez `$inject pour identifier manuellement vos dépendances du route resolver pour les composants Angular. *Pourquoi ?* : Cette technique divise la fonction anonyme pour le route resolver, la rendant plsu facile à lire. @@ -1568,7 +1574,7 @@ Alors que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'a ét $routeProvider .when('/avengers', { templateUrl: 'avengers.html', - controller: 'Avengers', + controller: 'AvengersController', controllerAs: 'vm', resolve: { moviesPrepService: moviePrepService @@ -1660,7 +1666,7 @@ Alors que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'a ét } ``` - > Note : A partir d'AngularJS 1.3, utilisez le paramètre ˋngStrictDiˋ de la directive [`ngApp`](https://docs.angularjs.org/api/ng/directive/ngApp). Avec ce paramètre, l'injecteur sera créé en mode "strict-di" qui rendra fera échouer les invocations de fonctions de l'application qui n'utilisent pas explicitement les annotation de fonction (ceci peut ne pas être sûr à la minification). Débugger les informations qui seront logguées dans la console peut aider à débusquer le code à l'origine. + > Note : A partir d'Angular 1.3, utilisez le paramètre ˋngStrictDiˋ de la directive [`ngApp`](https://docs.angularjs.org/api/ng/directive/ngApp). Avec ce paramètre, l'injecteur sera créé en mode "strict-di" qui rendra fera échouer les invocations de fonctions de l'application qui n'utilisent pas explicitement les annotation de fonction (ceci peut ne pas être sûr à la minification). Débugger les informations qui seront logguées dans la console peut aider à débusquer le code à l'origine. `` ### Utilisation de Gulp ou Grunt pour ng-annotate @@ -1675,6 +1681,7 @@ Alors que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'a ét ```javascript gulp.task('js', ['jshint'], function() { var source = pkg.paths.js; + return gulp.src(source) .pipe(sourcemaps.init()) .pipe(concat('all.min.js', {newLine: ';'})) @@ -1702,7 +1709,7 @@ Alors que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'a ét - Utilisez un [decorateur](https://docs.angularjs.org/api/auto/service/$provide#decorator), au moment de la configuration en utilisant le service [`$provide`](https://docs.angularjs.org/api/auto/service/$provide), sur le service [`$exceptionHandler`](https://docs.angularjs.org/api/ng/service/$exceptionHandler) pour effecture des actions personnalisées lorsque des exceptions se produisent. - *Pourquoi ?* : Fournir un moyen cohérent pour gérer les exceptions non interceptées d'AngularJS pendant le développement ou à l'éxécution. + *Pourquoi ?* : Fournir un moyen cohérent pour gérer les exceptions non interceptées d'Angular pendant le développement ou à l'éxécution. Note : Une autre possibilité serait de surcharger le service au lieu d'utiliser un décorateur. C'est une bonne possibilité, mais si vou voulez garder le comportement par défaut et l'étendre, un décorateur est plus approprié. @@ -1872,7 +1879,7 @@ Alors que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'a ét avenger-profile.directive.spec.js ``` - Note : Une autre convention courante consiste à nommer les fichiers de controlleurs sans le mot `controller` dans le nom de fichier comme `avengers.js`au lieu de `avengers.controller.js`. Toutes les autres conventions étant maintenues avec un suffixe par type. Les controlleurs étant les les types de composant les plus courants, ça permet d'économiser la frappe au clavier tout en étant facilement identifiable. Je vous conseille de choisir une convention et de vous y tenir dans toute l'équipe. + Note : Une autre convention courante consiste à nommer les fichiers de controlleurs sans le mot `controller` dans le nom de fichier comme `avengers.js`au lieu de `avengers.controller.js`. Toutes les autres conventions étant maintenues avec un suffixe par type. Les controlleurs étant les les types de composant les plus courants, ça permet d'économiser la frappe au clavier tout en étant facilement identifiable. Je vous conseille de choisir une convention et de vous y tenir dans toute l'équipe. Ma préference est `avengers.controller.js`. ```javascript /** @@ -1919,36 +1926,21 @@ Alors que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'a ét // avengers.controller.js angular .module - .controller('HeroAvengers', HeroAvengers); + .controller('HeroAvengersController', HeroAvengersController); - function HeroAvengers(){ } + function HeroAvengersController() { } ``` ### Suffixe des Noms de Controlleurs ###### [Style [Y124](#style-y124)] - - Ajoutez au nom du controlleur le suffixe ˋControllerˋ ou pas de suffixe du tout. Choississez une des deux conventions, pas les deux à la fois. + - Ajoutez au nom du controlleur le suffixe ˋControllerˋ. *Pourquoi ?* : Le suffixe ˋControllerˋ est utilisé souvent et il est plus explicitement descriptif. - *Pourquoi ?* : Omettre le suffixe est plus succint et le controlleur est souvent facilement identifiable même sans le suffixe. - ```javascript /** - * recommandé: Option 1 - */ - - // avengers.controller.js - angular - .module - .controller('Avengers', Avengers); - - function Avengers(){ } - ``` - - ```javascript - /** - * recommandé: Option 2 + * recommandé */ // avengers.controller.js @@ -2126,7 +2118,6 @@ Alors que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'a ét app/ app.module.js app.config.js - app.routes.js components/ calendar.directive.js calendar.directive.html @@ -2140,6 +2131,7 @@ Alors que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'a ét people/ attendees.html attendees.controller.js + people.routes.js speakers.html speakers.controller.js speaker-detail.html @@ -2152,11 +2144,12 @@ Alors que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'a ét sessions/ sessions.html sessions.controller.js + sessions.routes.js session-detail.html session-detail.controller.js ``` - ![Structure d'une Appli Exemple](https://raw.githubusercontent.com/johnpapa/angularjs-styleguide/master/assets/modularity-2.png) + ![Structure d'une Appli Exemple](https://raw.githubusercontent.com/johnpapa/angular-styleguide/master/assets/modularity-2.png) Note : N'utilisez pas une structuration de répertoires-par-type. Cela requiert de se déplacer entre de multiples répertoires lorsqu'on travaille sur une fonctionnalité et cela devient rapidement difficile à manier lorsque l'application grossit à 5, 10 ou plus de 25 vues et controlleurs (et autres), ce qui complique la localisation par rapport à des répertoires-par-fonctionnalité. @@ -2215,7 +2208,7 @@ Alors que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'a ét - Créez un module racine pour l'application dont le rôle est d'assembler tous les modules et fonctionnalités de votre application. Nommez-le comme votre application. - *Pourquoi ?* : AngularJS encourage la modularité et la séparation des responsabilités. La création d'un module racine pour l'application dont le rôle est de lier ensemble les autres modules fournit un moyen très direct d'ajouter et de retirer des modules à votre application. + *Pourquoi ?* : Angular encourage la modularité et la séparation des responsabilités. La création d'un module racine pour l'application dont le rôle est de lier ensemble les autres modules fournit un moyen très direct d'ajouter et de retirer des modules à votre application. ### Garder le Module Applicatif Léger ###### [Style [Y162](#style-y162)] @@ -2249,7 +2242,7 @@ Alors que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'a ét - Le module racine de l'application dépend des modules des fonctionnalités spécifiques et de certains modules partagés et ré-utilisables. - ![Modularity and Dependencies](https://raw.githubusercontent.com/johnpapa/angularjs-styleguide/master/assets/modularity-1.png) + ![Modularity and Dependencies](https://raw.githubusercontent.com/johnpapa/angular-styleguide/master/assets/modularity-1.png) *Pourquoi?* : Le module principal de l'appli continent une déclaration rapidement identifible des fonctionnalités de l'application. @@ -2257,7 +2250,7 @@ Alors que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'a ét *Pourquoi ?* : Les fonctionalités propres à l'appli tels que les services de données partagées deviennent faciles à repérer et partager au sein d'un `app.core` (choisissez un nom de votre choix pour ce module. - Note : C'est un stratégie pour la cohérence. Il y a ici beaucoup de bons choix. Choisisez-en une qui soit cohérente, suivez les règles des dépendances d'AngularJS, et la maintenance et la montée en charge sera facilitée. + Note : C'est un stratégie pour la cohérence. Il y a ici beaucoup de bons choix. Choisisez-en une qui soit cohérente, suivez les règles des dépendances d'Angular, et la maintenance et la montée en charge sera facilitée. > Mes structures peuvent varier légèrement entre les projets mais elles suivent toutes ces règles pour la structure et la modularité. L'implémentation peut varier en fonction des fonctionnalités et de l'équipe. En d'autres termes, ne vous paralysez pas sur une structure exactement semblable mais soumettez votre structure aux critères de cohérence, maintenance, et efficacité. @@ -2335,7 +2328,7 @@ Alors que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'a ét - Utilisez [`$timeout`](https://docs.angularjs.org/api/ng/service/$timeout) et [`$interval`](https://docs.angularjs.org/api/ng/service/$interval) au lieu de `setTimeout` et `setInterval`. - *Pourquoi ?* : Ces services sont wrappés par Angular et plus facilement testables et gèrent le cycle de digest d'AngularJS conservant un data binding à jour. + *Pourquoi ?* : Ces services sont wrappés par Angular et plus facilement testables et gèrent le cycle de digest d'Angular conservant un data binding à jour. **[Retour en haut de page](#table-des-matières)** @@ -2374,9 +2367,9 @@ Les tests unitaires aident à maintenir un code propre, ainsi, j'ai inclu quelqu - Utilisez [Jasmine](http://jasmine.github.io/) or [Mocha](http://mochajs.org) pour les tests unitaires. - *Pourquoi ?* : Jasmine et Mocha sont toutes deux largement utilisées dans la communauté AngularJS. Toutes les deux stables, bien maintenues, et fournissant des fonctionnalités robustes de test. + *Pourquoi ?* : Jasmine et Mocha sont toutes deux largement utilisées dans la communauté Angular. Toutes les deux stables, bien maintenues, et fournissant des fonctionnalités robustes de test. - Note : Lorsque vous utilisez Mocha, utilisez aussi une librairie d'assertion telle que [Chai](http://chaijs.com). + Note : Lorsque vous utilisez Mocha, utilisez aussi une librairie d'assertion telle que [Chai](http://chaijs.com). Je prefère Mocha. ### Lanceur de Test ###### [Style [Y192](#style-y192)] @@ -2400,6 +2393,9 @@ Les tests unitaires aident à maintenir un code propre, ainsi, j'ai inclu quelqu *Pourquoi ?* : Sinon rend plus facile l'alternance entre Jasmine et Mocha, si vous voulez essayer les deux. + *Pourquoi ?* : Sinon a des messages descriptifs quand les tests ne valident pas les assertions. + + ### Navigateur sans Interface Graphique ###### [Style [Y194](#style-y194)] @@ -2419,15 +2415,22 @@ Les tests unitaires aident à maintenir un code propre, ainsi, j'ai inclu quelqu ### Atténuation des Règles JSHint avec les Golbales sur les Tests ###### [Style [Y196](#style-y196)] - - Relaxez les règles sur votre code de test afin de permettre l'usage des globales telles que `describe` et `expect`. + - Relaxez les règles sur votre code de test afin de permettre l'usage des globales telles que `describe` et `expect`. Relaxez les règles pour les expressions, de la même façon qu'avec Mocha. *Pourquoi ?* : Vos tests sont du code et requièrent à ce titre la même attention avec les mêmes règles de qualité de code que votre code de production. Cependant, les variables globales utilisées par les frameworks de test, par exemple, peuvent être relaxées en les incluants dans les spécifications de test. ```javascript - /* global sinon, describe, it, afterEach, beforeEach, expect, inject */ + /* jshint -W117, -W030 */ + ``` + Ou laors vous pouvez rajouter ça à votre fichier d'option JSHint. + + ```javascript + "jasmine": true, + "mocha": true, ``` - ![Outils de Test](https://raw.githubusercontent.com/johnpapa/angularjs-styleguide/master/assets/testing-tools.png) + + ![Outils de Test](https://raw.githubusercontent.com/johnpapa/angular-styleguide/master/assets/testing-tools.png) ### Organizing Tests ###### [Style [Y197](#style-y197)] @@ -2463,7 +2466,7 @@ Les tests unitaires aident à maintenir un code propre, ainsi, j'ai inclu quelqu ### Utilisation ###### [Style [Y210](#style-y210)] - - Utilisez de subtiles [animations avec AngularJS](https://docs.angularjs.org/guide/animations) pour la transition entre les états pour les vues et les éléments visuels premiers. Incluez le [module ngAnimate](https://docs.angularjs.org/api/ngAnimate). Les trois clés sont la subtilité, la fluidité, l'homogénéïté. + - Utilisez de subtiles [animations avec Angular](https://docs.angularjs.org/guide/animations) pour la transition entre les états pour les vues et les éléments visuels premiers. Incluez le [module ngAnimate](https://docs.angularjs.org/api/ngAnimate). Les trois clés sont la subtilité, la fluidité, l'homogénéïté. *Pourquoi ?* : Des animations subtiles peuvent améliorer l'Expérience Utilisateur lorsqu'elles sont utilisées de façon appropriéés. @@ -2487,7 +2490,7 @@ Les tests unitaires aident à maintenir un code propre, ainsi, j'ai inclu quelqu *Pourquoi ?* : animate.css est largement utilisée et testée. - Note : Voir ce [super post par Matias Niemelä sur les animations d'AngularJS](http://www.yearofmoo.com/2013/08/remastered-animation-in-angularjs-1-2.html) + Note : Voir ce [super post par Matias Niemelä sur les animations d'Angular](http://www.yearofmoo.com/2013/08/remastered-animation-in-angularjs-1-2.html) **[Retour en haut de page](#table-des-matières)** @@ -2620,12 +2623,99 @@ Les tests unitaires aident à maintenir un code propre, ainsi, j'ai inclu quelqu **[Retour en haut de page](#table-des-matières)** +## JSCS + +### Use an Options File +###### [Style [Y235](#style-y235)] + - Utilisez JSCS pour valider votre style de code pour votre JavaScript et pensez à personnaliser vos options pour JSCS et de l'inclure dans votre gestionnaire de versionning. Vous pouvez consulter la [documentation de JSCS](http://www.jscs.info) pour voir les détails et les options. + + *Pourquoi ?* : Fournit une premiere alerte avant de commiter sur votre gestionnaire de versionning. + + *Pourquoi ?* : Permet d'assurer une cohérence au sein de votre équipe. + + ```javascript + { + "excludeFiles": ["node_modules/**", "bower_components/**"], + + "requireCurlyBraces": [ + "if", + "else", + "for", + "while", + "do", + "try", + "catch" + ], + "requireOperatorBeforeLineBreak": true, + "requireCamelCaseOrUpperCaseIdentifiers": true, + "maximumLineLength": { + "value": 100, + "allowComments": true, + "allowRegex": true + }, + "validateIndentation": 4, + "validateQuoteMarks": "'", + + "disallowMultipleLineStrings": true, + "disallowMixedSpacesAndTabs": true, + "disallowTrailingWhitespace": true, + "disallowSpaceAfterPrefixUnaryOperators": true, + "disallowMultipleVarDecl": null, + + "requireSpaceAfterKeywords": [ + "if", + "else", + "for", + "while", + "do", + "switch", + "return", + "try", + "catch" + ], + "requireSpaceBeforeBinaryOperators": [ + "=", "+=", "-=", "*=", "/=", "%=", "<<=", ">>=", ">>>=", + "&=", "|=", "^=", "+=", + + "+", "-", "*", "/", "%", "<<", ">>", ">>>", "&", + "|", "^", "&&", "||", "===", "==", ">=", + "<=", "<", ">", "!=", "!==" + ], + "requireSpaceAfterBinaryOperators": true, + "requireSpacesInConditionalExpression": true, + "requireSpaceBeforeBlockStatements": true, + "requireLineFeedAtFileEnd": true, + "disallowSpacesInsideObjectBrackets": "all", + "disallowSpacesInsideArrayBrackets": "all", + "disallowSpacesInsideParentheses": true, + + "validateJSDoc": { + "checkParamNames": true, + "requireParamTypes": true + }, + + "disallowMultipleLineBreaks": true, + + "disallowCommaBeforeLineBreak": null, + "disallowDanglingUnderscores": null, + "disallowEmptyBlocks": null, + "disallowMultipleLineStrings": null, + "disallowTrailingComma": null, + "requireCommaBeforeLineBreak": null, + "requireDotNotation": null, + "requireMultipleVarDecl": null, + "requireParenthesesAroundIIFE": true + } + ``` + +**[Back to top](#table-of-contents)** + ## Constantes ### Globales des Librairies Externes ###### [Style [Y240](#style-y240)] - - Créez une Constante AngularJS pour les variables gobales des librairies externes. + - Créez une Constante Angular pour les variables gobales des librairies externes. *Pourquoi ?* : Fournit un moyen d'injecter des librairies tierces qui seraient sinon des globales. Cela améliore la testabilité du code en vous permettant de savoir plus facilement quelles sont les dépendances de vos composants évite les abstractions qui fuient). Ça vous permet aussi de mocker ces dépendances, là où cela fait sens. @@ -2676,7 +2766,7 @@ Utilisez des templates de fichier ou des fragments pour vous aider à suivre des ### Sublime Text ###### [Style [Y250](#style-y250)] - - Fragments AngularJS qui suivent ces styles et règles. + - Fragments Angular qui suivent ces styles et règles. - Téléchargez les [Fragments Angular pour Sublime](assets/sublime-angular-snippets.zip?raw=true) - Placez-les dans votre répertoire Package @@ -2702,9 +2792,9 @@ Utilisez des templates de fichier ou des fragments pour vous aider à suivre des ### WebStorm ###### [Style [Y252](#style-y252)] - - Les fragments AngularJS et templates de fichiers qui suivent le style et les règles. Vous pouvez les importer dans les paramètres de WebStorm : + - Les fragments Angular et templates de fichiers qui suivent le style et les règles. Vous pouvez les importer dans les paramètres de WebStorm : - - Téléchargez les [templates de fichier et fragments WebStorm pour AngularJS](assets/webstorm-angular-file-template.settings.jar?raw=true) + - Téléchargez les [templates de fichier et fragments WebStorm pour Angular](assets/webstorm-angular-file-template.settings.jar?raw=true) - Ouvrez WebStorm et allez dans le menu `File` - Choisissez le menu `Import Settings` - Sélectionnez le fichier et clickez sur `OK` @@ -2770,6 +2860,9 @@ Le routage côté client est important pour créer un flux de navigation entre l ## Automatisation des Tâches Utilisez [Gulp](http://gulpjs.com) ou [Grunt](http://gruntjs.com) pour créer des tâches automatisées. Gulp favorise le code plutôt que la configuration tandis que Grunt tend vers la configuration plutôt que le code. Je préfère personnellement Gulp car il me semble plus facile à lire et écrire, mais les deux sont excellents. +> Learn more about gulp and patterns for task automation in my [Gulp Pluralsight course(http://jpapa.me/gulpps) +> Vous pouvez en lire plus sur Gulp et ses patterns pour l'automatisation des taches dans mon cours sur [Pluralsight](http://jpapa.me/gulpps). + ###### [Style [Y400](#style-y400)] - Utilisez l'automatisation des tâches pour lister les fichiers de définition de module `*.module.js` avant tout autre fichier JavaScript de l'application. @@ -2800,7 +2893,7 @@ Utilisez [Gulp](http://gulpjs.com) ou [Grunt](http://gruntjs.com) pour créer de **[Back to top](#table-of-contents)** -## Documentation AngularJS +## Documentation Angular Pour tout le reste, la référence des API, allez voir la [documentation Angular](//docs.angularjs.org/api). ## Contribuer @@ -2818,10 +2911,11 @@ Créez d'abord un problème pour discuter de potentiels changements ou ajouts. S _tldr; Utilisez ce guide. Les attributions sont appréciées._ -### (The MIT License) +### Copyright -Copyright (c) 2014 [John Papa](http://johnpapa.net) +Copyright (c) 2014-2015 [John Papa](http://johnpapa.net) +### (The MIT License) 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 From e48385ea56b89f1aec8ac23679ec4ff84c402694 Mon Sep 17 00:00:00 2001 From: Ben Bodenmiller Date: Sat, 7 Mar 2015 23:15:36 -0800 Subject: [PATCH 226/567] dataservice.j -> dataservice.js Simple typo fix --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 9c6c9bdb..094b4465 100644 --- a/README.md +++ b/README.md @@ -2188,7 +2188,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see user-profile.directive.js user-profile.directive.html services/ - dataservice.j + dataservice.js localstorage.js logger.js spinner.js From 9894f21eb1516c72be4f1dd18062e509ec69f59f Mon Sep 17 00:00:00 2001 From: Aleksandar Bogatinov Date: Sun, 8 Mar 2015 16:29:52 +0100 Subject: [PATCH 227/567] Updated to latest version --- i18n/mk-MK.md | 304 +++++++++++++++++++++++++++++++++----------------- 1 file changed, 203 insertions(+), 101 deletions(-) diff --git a/i18n/mk-MK.md b/i18n/mk-MK.md index d08a5bfe..76cc547e 100644 --- a/i18n/mk-MK.md +++ b/i18n/mk-MK.md @@ -1,31 +1,31 @@ -# AngularJS водич на кодирање +# Angular водич на кодирање -*Своеволен AngularJS водич на кодирање за тимови од [@john_papa](//twitter.com/john_papa)* +*Своеволен Angular водич на кодирање за тимови од [@john_papa](//twitter.com/john_papa)* *Преведено од [Александар Богатинов](https://github.com/Bogatinov)* ->The [original English version](http://jpapa.me/ngstyles) is the source of truth, as it is maintained and updated first. +>[Оригиналната Англиска верзија](http://jpapa.me/ngstyles) е изворот на вистината, одржувана и ажурирана прва. -Доколку барате своеволен стил на кодирање за синтакса, конвенции и структурирање на AngularJS апликации, тогаш сте на правилното место. -Овие стилови се базирани на моето искуство во развој на [AngularJS](//angularjs.org), презентации, [Pluralsight тренинг курсеви](http://pluralsight.com/training/Authors/Details/john-papa) и работа во тимови. +Доколку барате своеволен стил на кодирање за синтакса, конвенции и структурирање на Angular апликации, тогаш сте на правилното место. +Овие стилови се базирани на моето искуство во развој на [Angular](//angular.org), презентации, [Pluralsight тренинг курсеви](http://pluralsight.com/training/Authors/Details/john-papa) и работа во тимови. -Целта на овој водич на кодирање е да овозможи насока во развој на AngularJS апликации преку конвенциите што јас ги користам, и уште поважно, зошто ги користам. +Целта на овој водич на кодирање е да овозможи насока во развој на Angular апликации преку конвенциите што јас ги користам, и уште поважно, зошто ги користам. ->Ако ви се допаѓа овој водич, тогаш проверете ми го курсот [AngularJS Patterns: Clean Code](http://jpapa.me/ngclean) на Pluralsight. +>Ако ви се допаѓа овој водич, тогаш проверете ми го курсот [Angular Patterns: Clean Code](http://jpapa.me/ngclean) на Pluralsight кој е придружник на овој водич. -[![AngularJs Шаблон: Чист Код](https://raw.githubusercontent.com/johnpapa/angularjs-styleguide/master/assets/ng-clean-code-banner.png)](http://jpapa.me/ngclean) +[![AngularJs Шаблон: Чист Код](https://raw.githubusercontent.com/johnpapa/angular-styleguide/master/assets/ng-clean-code-banner.png)](http://jpapa.me/ngclean) ## Величествена заедница и заслуга -Никогаш не работи во вакуум. Јас сметам дека AngularJS заедницата е неверојатна група кои се страсни за споделување искуство. Како резултат, јас и мојот пријател кој е AngularJS експерт, Todd Motto соработувавме со многу стилови и конвенции. Се согласуваме на повеќето, додека на останатите се разликуваме. Ве охрабрувам да ги погледнете на [Todd's guidelines](https://github.com/toddmotto/angularjs-styleguide) со цел да добиете осет за неговиот пристап и како се споредува. +Никогаш не работи во вакуум. Јас сметам дека Angular заедницата е неверојатна група кои се страсни за споделување искуство. Како резултат, јас и мојот пријател кој е Angular експерт, Todd Motto соработувавме со многу стилови и конвенции. Се согласуваме на повеќето, додека на останатите се разликуваме. Ве охрабрувам да ги погледнете на [Todd's guidelines](https://github.com/toddmotto/angular-styleguide) со цел да добиете осет за неговиот пристап и како се споредува. -Многу од моите водичи произлегоа од многу сесии во програмираење во пар со [Ward Bell](http://twitter.com/wardbell). Иако не се сложуваме секогаш, мојот пријател Ward секако влијаеше во последната еволуција на овој водич. +Многу од моите водичи произлегоа од многу сесии во програмирање во пар со [Ward Bell](http://twitter.com/wardbell). Mојот пријател Ward секако влијаеше во последната еволуција на овој водич. ## Погледнете ги водичите во пробната апликација Иако овој водич ги објаснува "што", "зошто" и "како", јас сметам дека е полезно да ги запазиме во практика. Овој водич е придружен од пробна апликација која ги следи овие стилови и модели. Можете да ја најдете [пробната апликација (наречена modular) тука](https://github.com/johnpapa/ng-demos) во папката 'modular'. Не се колебајте да ја земете, да ја клонирате и форкувате. [Инструкции за да ја започнете се во своете readme](https://github.com/johnpapa/ng-demos/tree/master/modular) ##Преводи -[Преводи од овој AngularJS водич на кодирање](https://github.com/johnpapa/angularjs-styleguide/tree/master/i18n) се одржувани од заедницата и можете да ги најдете тука. +[Преводи од овој Angular водич на кодирање](https://github.com/johnpapa/angular-styleguide/tree/master/i18n) се одржувани од заедницата и можете да ги најдете тука. ## Table of contents @@ -51,12 +51,14 @@ 1. [Animations](#animations) 1. [Comments](#comments) 1. [JSHint](#js-hint) + 1. [JSCS](#jscs) 1. [Constants](#constants) 1. [File Templates and Snippets](#file-templates-and-snippets) 1. [Yeoman Generator](#yeoman-generator) 1. [Routing](#routing) 1. [Task Automation](#task-automation) - 1. [AngularJS Docs](#angularjs-docs) + 1. [Filters](#filters) + 1. [Angular Docs](#angular-docs) 1. [Contributing](#contributing) 1. [License](#license) @@ -118,7 +120,7 @@ ## IIFE ### JavaScript Closures ###### [Style [Y010](#style-y010)] - - Вгнездете ги AngularJS компоненти во Immediately Invoked Function Expression (IIFE). + - Вгнездете ги Angular компоненти во Immediately Invoked Function Expression (IIFE). *Зошто?*: IIFE не ги покажува променливите на глобално ниво. Ова помага при спречување да променливите и декларациите на функциите да живеат подолго од очекуваното на глобалното ниво, што исто така помага во избегнување на судири на променливи со исто име. @@ -319,7 +321,7 @@ *Зошто?*: `controllerAs` е синтаксички поубав од `$scope`. Вие сеуште може да се поврзете со Прегледот и да ги пристапите `$scope` методите. - *Зошто?*: Ви помага да избегнете употреба на `$scope` методи во контролерот кога е подобро да ги избегнете или преместите во фабрика. `$scope` може да употребите во фабрика или во контролер само кога ви е потребен. На пример, кога објавувате/пријавувате настани со употреба на [`$emit`](https://docs.angularjs.org/api/ng/type/$rootScope.Scope#$emit), [`$broadcast`](https://docs.angularjs.org/api/ng/type/$rootScope.Scope#$broadcast), или [`$on`](https://docs.angularjs.org/api/ng/type/$rootScope.Scope#$on) подобро е да ги преместите во фабрика и да ја повикате неа во контролерот. + *Зошто?*: Ви помага да избегнете употреба на `$scope` методи во контролерот кога е подобро да ги избегнете или преместите во фабрика. `$scope` може да употребите во фабрика или во контролер само кога ви е потребен. На пример, кога објавувате/пријавувате настани со употреба на [`$emit`](https://docs.angular.org/api/ng/type/$rootScope.Scope#$emit), [`$broadcast`](https://docs.angular.org/api/ng/type/$rootScope.Scope#$broadcast), или [`$on`](https://docs.angular.org/api/ng/type/$rootScope.Scope#$on) подобро е да ги преместите во фабрика и да ја повикате неа во контролерот. ```javascript /* избегнувајте */ @@ -427,7 +429,7 @@ } ``` - ![Controller Using "Above the Fold"](https://raw.githubusercontent.com/johnpapa/angularjs-styleguide/master/assets/above-the-fold-1.png) + ![Controller Using "Above the Fold"](https://raw.githubusercontent.com/johnpapa/angular-styleguide/master/assets/above-the-fold-1.png) Забелешка: Ако функцијата е 1 линија код, можете да ја поставите горе се додека читливоста не се наруши. @@ -537,7 +539,7 @@ } ``` -### Одлагање Логика во Контролерот +### Одлагање Логика во Контролерот до Сервисите ###### [Style [Y035](#style-Y035)] - Одлагајте логика на во контролерот со делегирање до сервиси и фабрики. @@ -606,7 +608,7 @@ Забелешка: Доколку Прегледот е вчитан преку други начини наместо рути, тогаш искористете ја `ng-controller="Avengers as vm"` синтаксата. - *Зошто?*: Преку поставување на контролерот во пар во рутата се овозможува други рути да започнат други парови од контролери и прегледи. Кога контролерите се назначени со прегледот со [`ng-controller`](https://docs.angularjs.org/api/ng/directive/ngController), тогаш тој преглед е секогаш поврзан со истиот контролер. + *Зошто?*: Преку поставување на контролерот во пар во рутата се овозможува други рути да започнат други парови од контролери и прегледи. Кога контролерите се назначени со прегледот со [`ng-controller`](https://docs.angular.org/api/ng/directive/ngController), тогаш тој преглед е секогаш поврзан со истиот контролер. ```javascript /* избегнувајте - кога потребна е употреба на рути и динамички пар*/ @@ -662,7 +664,7 @@ ###### [Style [Y040](#style-Y040)] - Сервиси се инстанцирани со `new` зборот, и се употребуваат со `this` за јавни методи и променливи. Бидејќи се слични со фабрики, користете фабрика за конзистентност. - Забелешка: [Сите AngularJS сервиси се singletons](https://docs.angularjs.org/guide/services). Тоа значи дека има само една инстанца од сервис за injector. + Забелешка: [Сите Angular сервиси се singletons](https://docs.angular.org/guide/services). Тоа значи дека има само една инстанца од сервис за injector. ```javascript // сервис @@ -704,7 +706,7 @@ ###### [Style [Y051](#style-Y051)] - Фабрики се singletons и враќаат објект што ги содржини членовите од тој сервис. - Забелешка: [Сите AngularJS сервиси се singletons](https://docs.angularjs.org/guide/services). + Забелешка: [Сите Angular сервиси се singletons](https://docs.angular.org/guide/services). ### Членовите за пристап на почеток ###### [Style [Y052](#style-Y052)] @@ -760,7 +762,7 @@ На овој начин поврзувањата се пресликуваат низ објектот, примитивните вредности не можат да се ажурираат самостојно со употреба на Revealing шаблонот на модули. - ![Фабрики искористуваат "Above the Fold"](https://raw.githubusercontent.com/johnpapa/angularjs-styleguide/master/assets/above-the-fold-2.png) + ![Фабрики искористуваат "Above the Fold"](https://raw.githubusercontent.com/johnpapa/angular-styleguide/master/assets/above-the-fold-2.png) ### Декларации на функции ја кријат имплементацијата ###### [Style [Y053](#style-Y053)] @@ -940,7 +942,7 @@ ### Вратете Promise од податочни повици ###### [Style [Y061](#style-Y061)] - - Кога повикувате податочен сервис кој враќа promise како што е $http, вратете promise во вашата повикувачка функција. + - Кога повикувате податочен сервис кој враќа promise како што е `$http`, вратете promise во вашата повикувачка функција. *Зошто?*: Можете да врзете повеќе promise заедно со повеќе акции над податоците откако податочниот повик заврши и го прифати или одбие promise-от. @@ -1078,7 +1080,7 @@ ### Манипулирајте DOM во директивата ###### [Style [Y072](#style-Y072)] - - Кога манипулирате директно со DOM, употребете директива. Ако можат да се употребат други начини, како CSS за стилови или [анимациски сервиси](https://docs.angularjs.org/api/ngAnimate), Angular темплејти, [`ngShow`](https://docs.angularjs.org/api/ng/directive/ngShow) или [`ngHide`](https://docs.angularjs.org/api/ng/directive/ngHide), тогаш употребете ги тие. На пример, ако директивата само се појавува/исчезнува, тогаш употребете ngHide/ngShow. + - Кога манипулирате директно со DOM, употребете директива. Ако можат да се употребат други начини, како CSS за стилови или [анимациски сервиси](https://docs.angular.org/api/ngAnimate), Angular темплејти, [`ngShow`](https://docs.angular.org/api/ng/directive/ngShow) или [`ngHide`](https://docs.angular.org/api/ng/directive/ngHide), тогаш употребете ги тие. На пример, ако директивата само се појавува/исчезнува, тогаш употребете ngHide/ngShow. *Зошто?*: Манипулација на DOM е тешка да се тестира, дебагира и притоа постојат подобри начини. (на пример CSS, анимации, темплејти) @@ -1088,7 +1090,7 @@ *Зошто?*: Уникатниот краток префикс ја идентификува смислата на директивата и нејзиното потекло. На пример, префиксот `cc-` може да укажува дека директивата дел од CodeCamper апликацијата додека `acme-` може да укажува дека директивата е за компанијата Acme. - Забелешка: Избегнувајте `ng-` бидејќи тие се резервирани за директивите на AngularJS. Проучете најчесто употребувани директиви со цел да избегнувате судири со имињата, како `ion-` за [Ionic Framework](http://ionicframework.com/). + Забелешка: Избегнувајте `ng-` бидејќи тие се резервирани за директивите на Angular. Проучете најчесто употребувани директиви со цел да избегнувате судири со имињата, како `ion-` за [Ionic Framework](http://ionicframework.com/). ### Ограничете се на Елементи и Атрибути ###### [Style [Y074](#style-Y074)] @@ -1098,7 +1100,7 @@ *Зошто?*: Иако овозможуваме директивите да се користат како класи, доколку навистина директивата се употребува како елемент тогаш има повеќе смисла да се користи како елемент или во најмал случај, како атрибут. - Забелешка: EA е стандардно за AngularJS 1.3 + + Забелешка: EA е стандардно за Angular 1.3 + ```html @@ -1317,9 +1319,9 @@ - Употребете решавање на патеката кога сакате да ја прекинете патеката пред да преминете на Прегледот. - *Зошто?*: Контролерот може да зависи од податоци пред да се изврши. Овој податок може да дојде преку promise од сопствена фабрика или [$http](https://docs.angularjs.org/api/ng/service/$http). Со употреба на [route resolve](https://docs.angularjs.org/api/ngRoute/provider/$routeProvider) ќе овозможиме promise да се реши пред логиката на контролерот да биде извршена, така што може да зависи од акција во податокот. + *Зошто?*: Контролерот може да зависи од податоци пред да се изврши. Овој податок може да дојде преку promise од сопствена фабрика или [$http](https://docs.angular.org/api/ng/service/$http). Со употреба на [route resolve](https://docs.angular.org/api/ngRoute/provider/$routeProvider) ќе овозможиме promise да се реши пред логиката на контролерот да биде извршена, така што може да зависи од акција во податокот. - *Зошто?*: Кодот се извршува после патеката и во activate функцијата во контролерот. Прегледот започнува одма да се вчитува. Поврзување со податоците се вклучува кога ќе се реши promise-от во activate функцијата. "Зафатена" анимација ќе се појави додека преминувате на Прегледот. (со ng-view или ui-view) + *Зошто?*: Кодот се извршува после патеката и во activate функцијата во контролерот. Прегледот започнува одма да се вчитува. Поврзување со податоците се вклучува кога ќе се реши promise-от во activate функцијата. "Зафатена" анимација ќе се појави додека преминувате на Прегледот. (со `ng-view` или `ui-view`) Забелешка: Кодот се извршува пред патеката со promise. Со одбивање на promise се спречува патеката. Со решавање, се чека на новиот преглед да заврши. "Зафатена" анимација може да се прикаже пред да се реши патеката и во преминот на Прегледот. Доколку сакате побрзо да стигнете до Прегледот, а не ви е потребен checkpoint доколку сакате да стигнете до Прегледот, тогаш разгледајте го [controller `activate` technique](#style-y080). @@ -1422,7 +1424,7 @@ ###### [Style [Y090](#style-Y090)] - Избегнувајте употреба на кратенки за декларација на зависности без употреба на безбеден пристап за минификација. - *Зошто?*: Параметрите на компонентата (e.g. контролер, фабрика, итн) ќе бидат претворени во исчезнати променливи. На пример, `common` и `dataservice` може да постанат `a` или `b` и да не бидат најдени од AngularJS. + *Зошто?*: Параметрите на компонентата (e.g. контролер, фабрика, итн) ќе бидат претворени во исчезнати променливи. На пример, `common` и `dataservice` може да постанат `a` или `b` и да не бидат најдени од Angular. ```javascript /* избегнувајте - опасно за минифкација*/ @@ -1443,11 +1445,11 @@ ### Рачна идентификација на зависности ###### [Style [Y091](#style-Y091)] - - Употребете `$inject` за рачна идентификација на вашиоте зависности во AngularJS компонентите. + - Употребете `$inject` за рачна идентификација на вашиоте зависности во Angular компонентите. *Зошто?*: Оваа техника се користи во [`ng-annotate`](https://github.com/olov/ng-annotate), што ја препорачувам за автоматизација на создавање на безбедни зависности при минификација. Доколку `ng-annotate` забележи зависност доколку постои, нема да ја повтори. - *Зошто?*: Ова ги заштитува вашите зависности од можноста да бидат изгубени при минификација. На пример, `common` и `dataservice` можат да постанат `a` or `b` и да не можат да бидат најдени од AngularJS. + *Зошто?*: Ова ги заштитува вашите зависности од можноста да бидат изгубени при минификација. На пример, `common` и `dataservice` можат да постанат `a` or `b` и да не можат да бидат најдени од Angular. *Зошто?*: Избегнувајте вметнување зависности во иста линија се додека тешко се читаат во листата. Исто така може да биде збунувачко дека низата се повеќе зборови во иста линија додека крајниот член е функција. @@ -1484,39 +1486,43 @@ } ``` - Забелешка: Кога вашата фунјција е под return линијата, тогаш $inject функцијата може да биде недостижна (ова е возможно да се случи во директива). Можете да го решите со преместување на $inject над return линијата или со употребување на алтернативна низа од зависности. - - Забелешка: [`ng-annotate 0.10.0`](https://github.com/olov/ng-annotate) воведе својство каде кое го поставува `$inject` каде може да се достигне. + Забелешка: Кога вашата функција е под return линијата, тогаш `$inject` може да биде недостижна (ова е возможно да се случи во директива). Можете да го решите ова со преместување на Контролерот надвор од директивата. ```javascript + // избегнувајте // во дефиницијата на директивата function outer() { - return { - controller: DashboardPanel, - }; - - DashboardPanel.$inject = ['logger']; // Недостижно - function DashboardPanel(logger) { + var ddo = { + controller: DashboardPanelController, + controllerAs: 'vm' + }; + return ddo; + + DashboardPanelController.$inject = ['logger']; // Недостижно + function DashboardPanelController(logger) { } } ``` ```javascript - // inside a directive definition + /* препорачано */ + // надвор од дефиницијата на директивата function outer() { - DashboardPanel.$inject = ['logger']; // достижно - return { - controller: DashboardPanel, - }; + var ddo = { + controller: DashboardPanelController, + controllerAs: 'vm' + }; + return ddo; + } - function DashboardPanel(logger) { - } + DashboardPanelController.$inject = ['logger']; + function DashboardPanelController(logger) { } ``` ### Рачна идентификација на зависностите преку решавање на патеки ###### [Style [Y092](#style-Y092)] - - Употребете $inject за рачна идентификација на зависностите преку решавање на патеки во AngularJS компоненти. + - Употребете `$inject` за рачна идентификација на зависностите преку решавање на патеки во Angular компоненти. *Зошто?*: Оваа техника ги разделува анонимните функции за решавање на патеката, кое е полесно за читање. @@ -1528,7 +1534,7 @@ $routeProvider .when('/avengers', { templateUrl: 'avengers.html', - controller: 'Avengers', + controller: 'AvengersController', controllerAs: 'vm', resolve: { moviesPrepService: moviePrepService @@ -1619,7 +1625,7 @@ } ``` - > Забелешка: Со почеток на AngularJS 1.3 употребете го параметарот `ngStrictDi` на [`ngApp`](https://docs.angularjs.org/api/ng/directive/ngApp) директивата. Доколку е застапен, injector-от ќе биде создаден во "strict-di" мод оневозможувајќи ја апликацијата да започне и да ги повика функциите кои не користат експлицитна анотација. (овие не се безбедни од минификација). Со логирање на информациите во конзола од дебагирање ќе ви помогне да ги најдете тие функции. + > Забелешка: Со почеток на Angular 1.3 можете да го употребете параметарот `ngStrictDi` на [`ngApp`](https://docs.angular.org/api/ng/directive/ngApp) директивата да детектирате потенцијални недостатоци при минификација на зависностите. Доколку е достапен, injector-от ќе биде создаден во "strict-di" мод оневозможувајќи ја апликацијата да започне и да ги повика функциите кои не користат експлицитна анотација. (овие не се безбедни од минификација). Со логирање на информациите во конзола од дебагирање ќе ви помогне да ги најдете тие функции. Преферирам да го употребуваме `ng-strict-di` само за дебагирање. `` ### Употребете Gulp или Grunt за ng-annotate @@ -1657,9 +1663,9 @@ ### Декоратори ###### [Style [Y110](#style-Y110)] - - Употребете [decorator](https://docs.angularjs.org/api/auto/service/$provide#decorator), при конфигурација со употреба на [`$provide`](https://docs.angularjs.org/api/auto/service/$provide) сервис, на [`$exceptionHandler`](https://docs.angularjs.org/api/ng/service/$exceptionHandler) сервисот за да извршите лични акции кога ќе се случи исклучок. + - Употребете [decorator](https://docs.angular.org/api/auto/service/$provide#decorator), при конфигурација со употреба на [`$provide`](https://docs.angular.org/api/auto/service/$provide) сервис, на [`$exceptionHandler`](https://docs.angular.org/api/ng/service/$exceptionHandler) сервисот за да извршите лични акции кога ќе се случи исклучок. - *Зошто?*: Овозможува постојан начин да се справи со исклучоци кои AngularJS не може да ги фати во development-time или run-time. + *Зошто?*: Овозможува постојан начин да се справи со исклучоци кои Angular не може да ги фати во development-time или run-time. Забелешка: Друга опција е да се прескокне сервисот наместо да се користи декоратор. Ова е добра опција, но доколку сакате да го задржите стандардното однесување и проширите, тогаш препорачливо е да користите декоратор. @@ -1727,7 +1733,7 @@ ### Грешки при рутирање ###### [Style [Y112](#style-Y112)] - - Справете се и логирајте сите рутирачки грешки со употреба на [`$routeChangeError`](https://docs.angularjs.org/api/ngRoute/service/$route#$routeChangeError). + - Справете се и логирајте сите рутирачки грешки со употреба на [`$routeChangeError`](https://docs.angular.org/api/ngRoute/service/$route#$routeChangeError). *Зошто?*: Обезбедува постојан начин да се справи со сите рутирачки грешки. @@ -1836,7 +1842,7 @@ avenger-profile.directive.spec.js ``` - Забелешка: Други чести конвенции е именување на контролерот датотеките без зборот `controller` во датотеката како `avengers.js` наместо `avengers.controller.js`. Сите други конвенции покажуваат употреба на суфикс на типот. Контролерите се најчестиот тип компонента така што заштедува на пишување и сеуште лесно препознатливо. Препорачувам да се одлучите со 1 конвенција и бидете конзистентен со тимот. + Забелешка: Други чести конвенции е именување на контролерот датотеките без зборот `controller` во датотеката како `avengers.js` наместо `avengers.controller.js`. Сите други конвенции покажуваат употреба на суфикс на типот. Контролерите се најчестиот тип компонента така што заштедува на пишување и сеуште лесно препознатливо. Препорачувам да се одлучите со 1 конвенција и бидете конзистентен со тимот. Моја преференца е `avengers.controller.js`. ```javascript /** @@ -1881,35 +1887,20 @@ // avengers.controller.js angular .module - .controller('HeroAvengers', HeroAvengers); + .controller('HeroAvengersController', HeroAvengersController); - function HeroAvengers(){ } + function HeroAvengersController(){ } ``` ### Суфикс на името на контролерот ###### [Style [Y124](#style-Y124)] - - Додадете суфикс `Controller` на името или без него. Одберете едно, не двете. + - Додадете суфикс `Controller` на името на Контролерот. *Зошто?*: `Controller` суфиксот е почесто користен и експлицитно описен. - *Зошто?*: Без суфиксот е концизен и контролерот често може лесно да се пронајде без суфиксот. - ```javascript /** - * препорачано: Опција 1 - */ - - // avengers.controller.js - angular - .module - .controller('Avengers', Avengers); - - function Avengers(){ } - ``` - - ```javascript - /** - * препорачано: Опција 2 + * препорачано */ // avengers.controller.js @@ -2074,7 +2065,6 @@ app/ app.module.js app.config.js - app.routes.js components/ calendar.directive.js calendar.directive.html @@ -2088,6 +2078,7 @@ people/ attendees.html attendees.controller.js + people.routes.js speakers.html speakers.controller.js speaker-detail.html @@ -2100,11 +2091,12 @@ sessions/ sessions.html sessions.controller.js + sessions.routes.js session-detail.html session-detail.controller.js ``` - ![Пробна апликација пример](https://raw.githubusercontent.com/johnpapa/angularjs-styleguide/master/assets/modularity-2.png) + ![Пробна апликација пример](https://raw.githubusercontent.com/johnpapa/angular-styleguide/master/assets/modularity-2.png) Забелешка: Не употребувајте структура со папка-по-тип. Со ова ќе се движите низ повеќе папки кога работите на функционалност што станува потешко како што апликацијата има повеќе од 5, 10 или 25 прегледи и контролери (за други функционалности), а со тоа и потешко за лоцирање на датотеките на таа функционалност. @@ -2161,7 +2153,7 @@ ###### [Style [Y161](#style-Y161)] - Создадете корен модул за апликацијата која улога е да ги содржи сите модули и функционалности на вашата апликација. Именувајте го според вашето име на апликација. - *Зошто?*: AngularJS охрабруба модуларност и поделба на грижи. Со создавање на корен модул на вашата апликација чија улога е да се поврзе со другите модули овозможува јасен начин за вклучување и исклучување модули од вашата апликација. + *Зошто?*: Angular охрабруба модуларност и поделба на грижи. Со создавање на корен модул на вашата апликација чија улога е да се поврзе со другите модули овозможува јасен начин за вклучување и исклучување модули од вашата апликација. ### Нека апликацискиот модул остане лесен ###### [Style [Y162](#style-Y162)] @@ -2191,7 +2183,7 @@ ###### [Style [Y165](#style-Y165)] - Корен модулот на апликацијата зависи од функционалните модули на апликацијата како и било кои заеднички или реискористливи модули. - ![Модуларност и Зависности](https://raw.githubusercontent.com/johnpapa/angularjs-styleguide/master/assets/modularity-1.png) + ![Модуларност и Зависности](https://raw.githubusercontent.com/johnpapa/angular-styleguide/master/assets/modularity-1.png) *Зошто?*: Главниот модул на апликацијата содржи манифест од брзо идентифицирани функционалности на апликацијата. @@ -2199,7 +2191,7 @@ *Зошто?*: Интра-Апликациски функционалности како податочни сервиси кои се споделени се лесни за лоцирање и споделување во `app.core` (изберете го вашето омилено име за овој модул). - Забелешка: Ова е стратегија за конзистентност. Постојат многу добри опции. Одберете една што е конзистентна, што ги следи AngularJS правилата за зависности, а лесно за одржување и скалабилност. + Забелешка: Ова е стратегија за конзистентност. Постојат многу добри опции. Одберете една што е конзистентна, што ги следи Angular правилата за зависности, а лесно за одржување и скалабилност. > Моите структури се разликуваат малку низ проекти, но сите ги запазуваат правилата за структура и модуларност. Имплементацијата може да се разликува во зависност од функционалностите и тимот. Со други зборови, не се засегајте на буквалната структура се додека ја оправдува вашата структура за конзистентност, одржливост и ефикасност. @@ -2211,7 +2203,7 @@ ### Конфигурација ###### [Style [Y170](#style-Y170)] - - Внесете го кодот во [конфигурацијата на модулот](https://docs.angularjs.org/guide/module#module-loading-dependencies) што мора да биде извршен пред почетокот на апликацијата. Идеални кандидати се провајдери и константи. + - Внесете го кодот во [конфигурацијата на модулот](https://docs.angular.org/guide/module#module-loading-dependencies) што мора да биде извршен пред почетокот на апликацијата. Идеални кандидати се провајдери и константи. *Зошто?*: Имаме помалку места за конфигурација на апликацијата. @@ -2242,7 +2234,7 @@ ### Извршувачки блокови ###### [Style [Y171](#style-Y171)] - - Било каков код што треба да се изврши кога ќе започне апликацијата треба да биде поставен во фабрика, изложен преку функција или вгнезден во [извршувачки блок](https://docs.angularjs.org/guide/module#module-loading-dependencies). + - Било каков код што треба да се изврши кога ќе започне апликацијата треба да биде поставен во фабрика, изложен преку функција или вгнезден во [извршувачки блок](https://docs.angular.org/guide/module#module-loading-dependencies). *Зошто?*: Код во извршувачки блок е тежок за тестирање. Поставување на истиот во фабрика е полесен за абстракција и лажење во тестирање. @@ -2265,15 +2257,15 @@ ### $document и $window ###### [Style [Y180](#style-Y180)] - - Употребете [`$document`](https://docs.angularjs.org/api/ng/service/$document) и [`$window`](https://docs.angularjs.org/api/ng/service/$window) наместо `document` и `window`. + - Употребете [`$document`](https://docs.angular.org/api/ng/service/$document) и [`$window`](https://docs.angular.org/api/ng/service/$window) наместо `document` и `window`. *Зошто?*: Овие сервиси се завиткани од Angular и полесни за тестирање него со употреба на document и window во тестовите. Ова помага да се излажат document и window во самите тестови. ### $timeout и $interval ###### [Style [Y181](#style-Y181)] - - Употребете [`$timeout`](https://docs.angularjs.org/api/ng/service/$timeout) и [`$interval`](https://docs.angularjs.org/api/ng/service/$interval) наместо `setTimeout` и `setInterval` . + - Употребете [`$timeout`](https://docs.angular.org/api/ng/service/$timeout) и [`$interval`](https://docs.angular.org/api/ng/service/$interval) наместо `setTimeout` и `setInterval` . - *Зошто?*: Овие сервиси се завиткани од Angular и полесни се за тестирање. Исто така се ракува со AngularJS digest циклусот што овозможува полесно ажурирање на поврзаните податоци. + *Зошто?*: Овие сервиси се завиткани од Angular и полесни се за тестирање. Исто така се ракува со Angular digest циклусот што овозможува полесно ажурирање на поврзаните податоци. **[Назад кон содржината](#table-of-contents)** @@ -2310,9 +2302,9 @@ ###### [Style [Y191](#style-Y191)] - Употребете [Jasmine](http://jasmine.github.io/) или [Mocha](http://mochajs.org) за тестирање на единки. - *Зошто?*: И Jasmine и Mocha се широко употребувани во AngularJS заедницата. И двете се стабилни, добро одржувани и овозможуваат робустни функции за тестирање. + *Зошто?*: И Jasmine и Mocha се широко употребувани во Angular заедницата. И двете се стабилни, добро одржувани и овозможуваат робустни функции за тестирање. - Забелешка: Кога користите Mocha, исто така не заборавајте да употребите assert библиотека како што е [Chai](http://chaijs.com). + Забелешка: Кога користите Mocha, исто така не заборавајте да употребите assert библиотека како што е [Chai](http://chaijs.com). Јас преферирам Mocha. ### Извршувач на тестови ###### [Style [Y192](#style-Y192)] @@ -2334,6 +2326,8 @@ *Зошто?*: Sinon овозможува полесно менување меѓу Jasmine и Mocha, доколку сакате да ги пробате двете. + *Зошто?*: Sinon има описни пораки кога тестовите ќе паднат на проверка. + ### Без Пребарувач ###### [Style [Y194](#style-Y194)] - Употребете [PhantomJS](http://phantomjs.org/) за да ги извршувате тестовите на вашиот сервер. @@ -2350,15 +2344,21 @@ ### Изменете ги променливите на JSHint за правила на тестови ###### [Style [Y196](#style-Y196)] - - Олабавете ги правилата за вашиот тест код со цел да ви дозволи да користите глобални променливи како `describe` и `expect`. + - Олабавете ги правилата за вашиот тест код со цел да ви дозволи да користите глобални променливи како `describe` и `expect`. Релаксирајте ги правилата за expressions. бидејќи Mocha ги користи овие. *Зошто?*: Вашите тестови се код и им е потребно истото внимание како вашиот продукциски код. Сепак, глобални променливи, како тие подоле, кои се користат од фрејмворкот за тестирање можат да бидат исклучени да не се проверуваат во вашите тестови. ```javascript - /* global sinon, describe, it, afterEach, beforeEach, expect, inject */ + /* jshint -W117, -W030 */ ``` + Или можете да го додадете следното во вашата JSHint датотека за опции - ![Алатки за тестирање](https://raw.githubusercontent.com/johnpapa/angularjs-styleguide/master/assets/testing-tools.png) + ```javascript + "jasmine": true, + "mocha": true, + ``` + + ![Алатки за тестирање](https://raw.githubusercontent.com/johnpapa/angular-styleguide/master/assets/testing-tools.png) ### Организирање на тестови ###### [Style [Y197](#style-y197)] @@ -2391,7 +2391,7 @@ ### Употреба ###### [Style [Y210](#style-Y210)] - - Употребете суптилни [анимации со AngularJS](https://docs.angularjs.org/guide/animations) да преминете низ состојбите на прегледите и главните визуелни елементи. Вклучете го [ngAnimate модулот](https://docs.angularjs.org/api/ngAnimate). Трите главни точки се суптилност, глаткост и беспрекорност. + - Употребете суптилни [анимации со Angular](https://docs.angular.org/guide/animations) да преминете низ состојбите на прегледите и главните визуелни елементи. Вклучете го [ngAnimate модулот](https://docs.angular.org/api/ngAnimate). Трите главни точки се суптилност, глаткост и беспрекорност. *Зошто?*: Суптилни анимации го подобруваат искуството на корисникот кога се употребуваат правилно. @@ -2413,7 +2413,7 @@ *Зошто?*: animate.css се широко употребувани и тестирани. - Забелешка: Проверете те го [овој одличчен пост од Matias Niemelä за AngularJS анимации](http://www.yearofmoo.com/2013/08/remastered-animation-in-angularjs-1-2.html) + Забелешка: Проверете те го [овој одличчен пост од Matias Niemelä за Angular анимации](http://www.yearofmoo.com/2013/08/remastered-animation-in-angular-1-2.html) **[Назад кон содржината](#table-of-contents)** @@ -2544,11 +2544,99 @@ **[Назад кон содржината](#table-of-contents)** +## JSCS + +### Употребете датотека за опциите +###### [Style [Y235](#style-y235)] + + - Употребете JSCS за проверка на вашиот кодерски стил во JavaScript и бидете сигурни да ја прилагодите JSCS датотеката за опции и да ја вклучите во контролата на изворниот код. Погледнете ја [JSCS документација](http://www.jscs.info) за детали околу опциите. + + *Зошто?*: Обезбедува прво предупредување пред да го пратите кодот до управувачот на изворниот код. + + *Зошто?*: Обезбедува конзистентност во вашиот тим. + + ```javascript + { + "excludeFiles": ["node_modules/**", "bower_components/**"], + + "requireCurlyBraces": [ + "if", + "else", + "for", + "while", + "do", + "try", + "catch" + ], + "requireOperatorBeforeLineBreak": true, + "requireCamelCaseOrUpperCaseIdentifiers": true, + "maximumLineLength": { + "value": 100, + "allowComments": true, + "allowRegex": true + }, + "validateIndentation": 4, + "validateQuoteMarks": "'", + + "disallowMultipleLineStrings": true, + "disallowMixedSpacesAndTabs": true, + "disallowTrailingWhitespace": true, + "disallowSpaceAfterPrefixUnaryOperators": true, + "disallowMultipleVarDecl": null, + + "requireSpaceAfterKeywords": [ + "if", + "else", + "for", + "while", + "do", + "switch", + "return", + "try", + "catch" + ], + "requireSpaceBeforeBinaryOperators": [ + "=", "+=", "-=", "*=", "/=", "%=", "<<=", ">>=", ">>>=", + "&=", "|=", "^=", "+=", + + "+", "-", "*", "/", "%", "<<", ">>", ">>>", "&", + "|", "^", "&&", "||", "===", "==", ">=", + "<=", "<", ">", "!=", "!==" + ], + "requireSpaceAfterBinaryOperators": true, + "requireSpacesInConditionalExpression": true, + "requireSpaceBeforeBlockStatements": true, + "requireLineFeedAtFileEnd": true, + "disallowSpacesInsideObjectBrackets": "all", + "disallowSpacesInsideArrayBrackets": "all", + "disallowSpacesInsideParentheses": true, + + "validateJSDoc": { + "checkParamNames": true, + "requireParamTypes": true + }, + + "disallowMultipleLineBreaks": true, + + "disallowCommaBeforeLineBreak": null, + "disallowDanglingUnderscores": null, + "disallowEmptyBlocks": null, + "disallowMultipleLineStrings": null, + "disallowTrailingComma": null, + "requireCommaBeforeLineBreak": null, + "requireDotNotation": null, + "requireMultipleVarDecl": null, + "requireParenthesesAroundIIFE": true + } + ``` + +*[Назад кон содржината](#table-of-contents)** + ## Constants ### Глобални од продавачот ###### [Style [Y240](#style-Y240)] - - Создадете AngularJS константа за глобалните променливи од библиотеки кои не се ваши. + - Создадете Angular константа за глобалните променливи од библиотеки кои не се ваши. *Зошто?*: Обезбедува начин да ги внесете библиотеките кои се глобални. Ова го подобрува тестирањето на кодот што овозможува лесно да забележите кои зависности се во вашите компоненти (се справува со протекување на абстракции). Исто така овозможува да ги излажирате овие зависности, каде има смисла да направите. @@ -2597,7 +2685,7 @@ angular ### Sublime Text ###### [Style [Y250](#style-Y250)] - - AngularJS кратки кодови кои ги следат овие водичи и стилови на код. + - Angular кратки кодови кои ги следат овие водичи и стилови на код. - Симнете ги [Sublime Angular кратки кодови](assets/sublime-angular-snippets.zip?raw=true) - Поставете ги во вашата Packages папка @@ -2613,7 +2701,7 @@ angular ### Visual Studio ###### [Style [Y251](#style-Y251)] - - AngularJS датотечни шаблони што ги следат овие стилови и водичи на код можат да бидат најдени на [SideWaffle](http://www.sidewaffle.com) + - Angular датотечни шаблони што ги следат овие стилови и водичи на код можат да бидат најдени на [SideWaffle](http://www.sidewaffle.com) - Симнете ја [SideWaffle](http://www.sidewaffle.com) Visual Studio екстензија (vsix file) - Извршете ја vsix датотека @@ -2621,9 +2709,9 @@ angular ### WebStorm ###### [Style [Y252](#style-Y252)] - - AngularJS кратки кодови и датотечни шаблони кои ги следат овие стилови и водичи на код. Можете да ги внесете во вашите WebStorm подесувања: + - Angular кратки кодови и датотечни шаблони кои ги следат овие стилови и водичи на код. Можете да ги внесете во вашите WebStorm подесувања: - - Симнете ги [WebStorm AngularJS датотечни шаблони и кратки кодови](../assets/webstorm-angular-file-template.settings.jar?raw=true) + - Симнете ги [WebStorm Angular датотечни шаблони и кратки кодови](../assets/webstorm-angular-file-template.settings.jar?raw=true) - Отворете го WebStorm и одберете го `File` менито - Одберете го `Import Settings` - Одберете ја датотеката и кликнете `OK` @@ -2640,13 +2728,13 @@ angular +### Atom ###### [Style [Y253](#style-y253)] - - AngularJS кратки кодови кои ги следат овие стилови и водичи на код. + - Angular кратки кодови кои ги следат овие стилови и водичи на код. ``` - apm install angularjs-styleguide-snippets + apm install angular-styleguide-snippets ``` или - Отворете го Atom, потоа отворете го Package Manager (Packages -> Settings View -> Install Packages/Themes) - - Побарајте го пакетот 'angularjs-styleguide-snippets' + - Побарајте го пакетот 'angular-styleguide-snippets' - Кликнете на 'Install' за да го инсталирате пакетот - Во JavaScript датотека напишете ги следните команди и потоа кликнете `TAB` @@ -2710,7 +2798,11 @@ angular **[Назад кон содржината](#table-of-contents)** ## Task Automation -Употребете [Gulp](http://gulpjs.com) or [Grunt](http://gruntjs.com) за создавање автоматизирани задачи. Gulp се приклонува кон код наместо подесување додека Grunt се приклонува кон конфигурација наместо код. Јас лично преферирам Gulp бидејќи сметам е полесно за читање и пишување, но и двата се одлични. +Употребете [Gulp](http://gulpjs.com) or [Grunt](http://gruntjs.com) за создавање автоматизирани задачи. + +> Gulp се потпира на код наместо конфигурација додека Grunt се потпира на конфигурација наместо код. Јас лично преферирам Gulp бидејќи чувствувам е полесно да се пишува и чита, но и двата се одлични. + +> Научете повеќе за gulp и шаблони при task automation во мојот [Gulp Pluralsight курс](http://jpapa.me/gulpps) ###### [Style [Y400](#style-y400)] @@ -2732,8 +2824,18 @@ angular **[Назад кон содржината](#table-of-contents)** -## AngularJS Docs -За се останато, референцирајте се до неговото API во [Angular документацијата](//docs.angularjs.org/api). +## Filters + +###### [Style [Y420](#style-y420)] + + - Избегнувајте употреба на филтери за скенирање на сите својства на комплексен објект граф. Употребувајте филтери за селекција на својства. + + *Зошто?*: Филтерите можат лесно да бидат злоупотребени и да имаат негативен ефект на перформанси ако не се употребени мудро, на пример кога филтер удира на голем и длабок објект граф. + +**[Назад кон содржината](#table-of-contents)** + +## Angular Docs +За се останато, референцирајте се до неговото API во [Angular документацијата](//docs.angular.org/api). ## Contributing @@ -2750,9 +2852,9 @@ angular _tldr; Use this guide. Attributions are appreciated._ -### (The MIT License) +### Copyright -Copyright (c) 2014 [John Papa](http://johnpapa.net) +Copyright (c) 2014-2015 [John Papa](http://johnpapa.net) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the From 281234bfa11217c7cd4830f5e5342faafc5ca271 Mon Sep 17 00:00:00 2001 From: angelochiello Date: Mon, 9 Mar 2015 08:58:07 +0100 Subject: [PATCH 228/567] [it-IT] PR #300 Updated as: PR #300: Added reference to the JSHint Jasmine and Mocha confs --- i18n/it-IT.md | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/i18n/it-IT.md b/i18n/it-IT.md index 027c0eb2..b06b326f 100644 --- a/i18n/it-IT.md +++ b/i18n/it-IT.md @@ -2436,9 +2436,15 @@ Gli unit test aiutano a mantenere il codice più chiaro, perciò ho incluso alcu *Perché?*: I tuoi test sono codice e richiedono al medesima attenzione e regole per la qualità del codice come tutto il resto del codice di produzione. Comunque, variabili globali usate dai framework di test, per esempio, possono essere rilassate includendole nelle specifiche dei test. ```javascript - /* global sinon, describe, it, afterEach, beforeEach, expect, inject */ + /* jshint -W117, -W030 */ ``` - + Oppure puoi aggiungere le righe che seguono al tuo file JSHint Options. + + ```javascript + "jasmine": true, + "mocha": true, + ``` + ![Strumenti per i test](https://raw.githubusercontent.com/johnpapa/angularjs-styleguide/master/assets/testing-tools.png) ### Organizzazione dei test From 10bac922f34c87c63cf56e85bb06e5ea2cd8aa4c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=B5=B5=E5=8F=AF?= Date: Mon, 9 Mar 2015 21:09:18 +0800 Subject: [PATCH 229/567] update tranzations --- i18n/zh-CN.md | 259 +++++++++++++++++++++++++++++++++++--------------- 1 file changed, 181 insertions(+), 78 deletions(-) diff --git a/i18n/zh-CN.md b/i18n/zh-CN.md index f4ba4ac2..86d380f3 100644 --- a/i18n/zh-CN.md +++ b/i18n/zh-CN.md @@ -1,29 +1,29 @@ -# AngularJS风格指南 +# Angular风格指南 -*AngularJS风格指南[@john_papa](//twitter.com/john_papa)* +*Angular风格指南[@john_papa](//twitter.com/john_papa)* *由[kerncink](https://github.com/natee)翻译* >The [original English version](http://jpapa.me/ngstyles) is the source of truth, as it is maintained and updated first. -如果你正在寻找一些关于语法、约定和结构化的AngularJS应用的一个有建设性的风格指南,这个repo正适合你。这里所包含的风格是基于我在团队中使用[AngularJS](//angularjs.org)的一些经验、一些演讲和[Pluralsight培训课程](http://pluralsight.com/training/Authors/Details/john-papa)。 +如果你正在寻找一些关于语法、约定和结构化的Angular应用的一个有建设性的风格指南,这个repo正适合你。这里所包含的风格是基于我在团队中使用[Angular](//angularjs.org)的一些经验、一些演讲和[Pluralsight培训课程](http://pluralsight.com/training/Authors/Details/john-papa)。 -这个风格指南的目的是为构建AngularJS应用提供指导,当然更加重要的是让大家知道我为什么要选择它们。 +这个风格指南的目的是为构建Angular应用提供指导,当然更加重要的是让大家知道我为什么要选择它们。 ->如果你喜欢这个指南,请在Pluralsight上检出我的[AngularJS Patterns: Clean Code](http://jpapa.me/ngclean)。 +>如果你喜欢这个指南,请在Pluralsight上检出我的[Angular Patterns: Clean Code](http://jpapa.me/ngclean)。 - [![AngularJs Patterns: Clean Code](https://raw.githubusercontent.com/johnpapa/angularjs-styleguide/master/assets/ng-clean-code-banner.png)](http://jpapa.me/ngclean) + [![Angular Patterns: Clean Code](https://raw.githubusercontent.com/johnpapa/angular-styleguide/master/assets/ng-clean-code-banner.png)](http://jpapa.me/ngclean) ## Community Awesomeness and Credit -我发现AngularJS社区是一个热衷于分享经验的令人难以置信的社区,尽管Todd Motto(他是我的一个朋友,也是AngularJS专家)和我合作了多种风格和惯例,但是我们也存在着一些分歧。我鼓励你去看看[Todd的指南](https://github.com/toddmotto/angularjs-styleguide),从其中了解他的做法和它们是如何比较的。 +我发现Angular社区是一个热衷于分享经验的令人难以置信的社区,尽管Todd Motto(他是我的一个朋友,也是Angular专家)和我合作了多种风格和惯例,但是我们也存在着一些分歧。我鼓励你去看看[Todd的指南](https://github.com/toddmotto/angularjs-styleguide),从其中了解他的做法和它们是如何比较的。 -我的许多风格都是从大量的程序会话[Ward Bell](http://twitter.com/wardbell)和我所拥有的而来的,虽然我们并不总是能达成一致,但是Ward确实影响了本指南的最终演变。 +我的许多风格都是从大量的程序会话[Ward Bell](http://twitter.com/wardbell)和我所拥有的而来的,我的好友Ward也影响了本指南的最终演变。 ## 在示例App中了解这些风格 看示例代码有助于你更好地理解,你可以在`modular`文件夹下找到[命名为modular的示例应用程序](https://github.com/johnpapa/ng-demos),随便克隆。 ##翻译 -[AngularJS风格指南翻译版本](https://github.com/johnpapa/angularjs-styleguide/tree/master/i18n)。 +[Angular风格指南翻译版本](https://github.com/johnpapa/angular-styleguide/tree/master/i18n)。 ##目录 @@ -49,12 +49,14 @@ 1. [动画](#动画) 1. [注释](#注释) 1. [JSHint](#js-hint) + 1. [JSCS](#jscs) 1. [常量](#常量) 1. [文件模板和片段](#文件模板和片段) 1. [Yeoman Generator](#yeoman-generator) 1. [路由](#路由) 1. [任务自动化](#任务自动化) - 1. [AngularJS文档](#angularjs文档) + 1. [Filters](#filters) + 1. [Angular文档](#angularjs文档) 1. [贡献](#贡献) 1. [许可](#许可) @@ -117,7 +119,7 @@ ### JavaScript闭包 ###### [Style [Y010](#style-y010)] - - 把AngularJS组件包装到一个立即调用函数表达式中(IIFE)。 + - 把Angular组件包装到一个立即调用函数表达式中(IIFE)。 *为什么?*:把变量从全局作用域中删除了,这有助于防止变量和函数声明比预期在全局作用域中有更长的生命周期,也有助于避免变量冲突。 @@ -443,7 +445,7 @@ } ``` - ![Controller Using "Above the Fold"](https://raw.githubusercontent.com/johnpapa/angularjs-styleguide/master/assets/above-the-fold-1.png) + ![Controller Using "Above the Fold"](https://raw.githubusercontent.com/johnpapa/angular-styleguide/master/assets/above-the-fold-1.png) 注:如果一个函数就是一行,那么只要不影响可读性就把它放到顶部。 @@ -555,7 +557,7 @@ } ``` -###推迟Controller中的逻辑 +###把Controller中的逻辑推迟到Service中 ###### [Style [Y035](#style-y035)] - 通过委派到service和factory中来推迟controller中的逻辑。 @@ -564,6 +566,8 @@ *为什么?*:把逻辑放到service中将会使单元测试的时候更加容易地把它们分离,相反,如果在controller中调用逻辑就显得很二了。 + *为什么?*:保持controller的简洁。 + *为什么?*:从controller中删除依赖关系并且隐藏实现细节。 ```javascript @@ -684,7 +688,7 @@ - 用`new`实例化service,用`this`实例化公共方法和变量,由于这和facotry是类似的,所以推荐用facotry来代替。 - 注意:[所有的AngularJS services都是单例](https://docs.angularjs.org/guide/services),这意味着每个injector都只有一个实例化的service。 + 注意:[所有的Angular services都是单例](https://docs.angularjs.org/guide/services),这意味着每个injector都只有一个实例化的service。 ```javascript // service @@ -728,7 +732,7 @@ - facotry是一个单例,它返回一个包含service成员的对象。 - 注:[所有的AngularJS services都是单例](https://docs.angularjs.org/guide/services),这意味着每个injector都只有一个实例化的service。 + 注:[所有的Angular services都是单例](https://docs.angularjs.org/guide/services),这意味着每个injector都只有一个实例化的service。 ###可访问的成员放到顶部### ###### [Style [Y052](#style-y052)] @@ -784,7 +788,7 @@ 这种绑定方式复制了宿主对象,原始值不会随着暴露模块模式的使用而更新。 - ![Factories Using "Above the Fold"](https://raw.githubusercontent.com/johnpapa/angularjs-styleguide/master/assets/above-the-fold-2.png) + ![Factories Using "Above the Fold"](https://raw.githubusercontent.com/johnpapa/angular-styleguide/master/assets/above-the-fold-2.png) ###函数声明隐藏实现细节 ###### [Style [Y053](#style-y053)] @@ -966,7 +970,7 @@ ###从Data调用那里返回一个Promise ###### [Style [Y061](#style-y061)] - - 就像$http一样,当调用data service时返回一个promise,在你的调用函数中也返回一个promise。 + - 就像`$http`一样,当调用data service时返回一个promise,在你的调用函数中也返回一个promise。 *为什么?*:你可以把promise链接到一起,在数据调用完成并且resolve或是reject这个promise后采取进一步的行为。 @@ -1127,7 +1131,7 @@ *为什么?*:虽然我们允许directive被当作一个class来使用,但如果这个directive的行为确实像一个元素的话,那么把directive当作元素或者属性是更有意义的。 - 注:AngularJS 1.3 +默认使用EA。 + 注:Angular 1.3 +默认使用EA。 ```html @@ -1355,7 +1359,7 @@ *为什么?*:controller在加载前可能需要一些数据,这些数据可能是从一个通过自定义factory或是[$http](https://docs.angularjs.org/api/ng/service/$http)的promise而来的。[route resolve](https://docs.angularjs.org/api/ngRoute/provider/$routeProvider)允许promise在controller的逻辑执行之前解决,因此它可能对从promise中来的数据做一些处理。 - *为什么?*:这段代码将在路由后的controller的激活函数中执行,视图立即加载,数据绑定将在promise resolve之后,可以(通过ng-view或ui-view)在视图的过渡之间可以加个loading状态的动画。 + *为什么?*:这段代码将在路由后的controller的激活函数中执行,视图立即加载,数据绑定将在promise resolve之后,可以(通过`ng-view`或`ui-view`)在视图的过渡之间可以加个loading状态的动画。 注意:这段代码将在路由之前通过一个promise来执行,拒绝了承诺就会取消路由,接受了就会等待路由跳转到新视图。如果你想更快地进入视图,并且无需验证是否可以进入视图,你可以考虑用[控制器 `activate` 技术](#style-y080)代替。 @@ -1459,7 +1463,7 @@ - 声明依赖时避免使用不安全缩写方法的缩写语法。 - *为什么?*:组件的参数(例如controller、factory等等)将会被转换成各种乱七八糟错误的变量。例如,`common`和`dataservice`可能会变成`a`或者`b`,但是这些转换后的变量在AngularJS中是找不到的。 + *为什么?*:组件的参数(例如controller、factory等等)将会被转换成各种乱七八糟错误的变量。例如,`common`和`dataservice`可能会变成`a`或者`b`,但是这些转换后的变量在Angular中是找不到的。 ```javascript /* avoid - not minification-safe*/ @@ -1481,11 +1485,11 @@ ###手动添加依赖 ###### [Style [Y091](#style-y091)] - - 用`$inject`手动添加AngularJS组件所需的依赖。 + - 用`$inject`手动添加Angular组件所需的依赖。 *为什么?*:这种技术反映了使用[`ng-annotate`](https://github.com/olov/ng-annotate)的技术,这就是我推荐的对依赖关系进行自动化创建安全压缩的方式,如果`ng-annotate`检测到已经有了注入,那么它就不会再次重复执行。 - *为什么?*:可以避免依赖变成其它AngularJS找不到的变量,例如,`common`和`dataservice`可能会变成`a`或者`b`。 + *为什么?*:可以避免依赖变成其它Angular找不到的变量,例如,`common`和`dataservice`可能会变成`a`或者`b`。 *为什么?*:避免创建内嵌的依赖,因为一个数组中很长的列表是很难阅读的,此外,内嵌的方式也会让人感到困惑,比如数组是一系列的字符串,但是最后一个却是组件的function。 @@ -1523,40 +1527,44 @@ } ``` - 注意:当你的函数处于一个return语句下,那么$inject可能无法访问(这回在directive中发生),你可以通过把$inject移到return语句上面或是用数组语法来解决这个问题。 - - 注意: [`ng-annotate 0.10.0`](https://github.com/olov/ng-annotate)介绍了一个特点,就是把`$inject`放到它可以被访问到的地方。 + 注意:当你的函数处于一个return语句下,那么`$inject`可能无法访问(这会在directive中发生),你可以通过把Controller移到directive外面来解决这个问题。 ```javascript + /* avoid */ // inside a directive definition function outer() { - return { - controller: DashboardPanel, + var ddo = { + controller: DashboardPanelController, + controllerAs: 'vm' }; + return ddo; - DashboardPanel.$inject = ['logger']; // Unreachable - function DashboardPanel(logger) { + DashboardPanelController.$inject = ['logger']; // Unreachable + function DashboardPanelController(logger) { } } ``` ```javascript - // inside a directive definition + /* recommended */ + // outside a directive definition function outer() { - DashboardPanel.$inject = ['logger']; // reachable - return { - controller: DashboardPanel, + var ddo = { + controller: DashboardPanelController, + controllerAs: 'vm' }; + return ddo; + } - function DashboardPanel(logger) { - } + DashboardPanelController.$inject = ['logger']; + function DashboardPanelController(logger) { } ``` ###手动确定路由解析器依赖 ###### [Style [Y092](#style-y092)] - - 用$inject手动给AngularJS组件添加路由解析器依赖。 + - 用`$inject`手动给Angular组件添加路由解析器依赖。 *为什么?*:这种技术打破了路由解析的匿名函数的形式,易读。 @@ -1568,7 +1576,7 @@ $routeProvider .when('/avengers', { templateUrl: 'avengers.html', - controller: 'Avengers', + controller: 'AvengersController', controllerAs: 'vm', resolve: { moviesPrepService: moviePrepService @@ -1643,7 +1651,8 @@ 注意:如果`ng-annotate`检测到已经有注入了(例如发现了`@ngInject`),就不会重复生成`$inject`代码了。 - > 注意:从AngularJS 1.3 开始用[`ngApp`](https://docs.angularjs.org/api/ng/directive/ngApp)指令的 `ngStrictDi`参数,当以“strict-di”模式创建injector时,会导致应用程序无法调用不使用显示函数注释的函数(这也许无法安全压缩)。记录在控制台的调试信息可以帮助追踪出问题的代码。 + > 注意:从Angular 1.3开始,你就可以用[`ngApp`](https://docs.angularjs.org/api/ng/directive/ngApp)指令的 `ngStrictDi`参数来检测任何可能失去依赖的地方,当以“strict-di”模式创建injector时,会导致应用程序无法调用不使用显示函数注释的函数(这也许无法安全压缩)。记录在控制台的调试信息可以帮助追踪出问题的代码。我只在需要调试的时候才会用到`ng-strict-di`。 + `` ###使用Gulp或Grunt结合ng-annotate @@ -1685,7 +1694,7 @@ - 使用一个[decorator](https://docs.angularjs.org/api/auto/service/$provide#decorator),在配置的时候用[`$provide`](https://docs.angularjs.org/api/auto/service/$provide)服务,当发生异常时,在[`$exceptionHandler`](https://docs.angularjs.org/api/ng/service/$exceptionHandler)服务中执行自定义的处理方法。 - *为什么?*:在开发时和运行时提供了一种统一的方式来处理未被捕获的AngularJS异常。 + *为什么?*:在开发时和运行时提供了一种统一的方式来处理未被捕获的Angular异常。 注:另一个选项是用来覆盖service的,这个可以代替decorator,这是一个非常nice的选项,但是如果你想保持默认行为,那么推荐你拓展一个decorator。 @@ -1868,7 +1877,7 @@ avenger-profile.directive.spec.js ``` - 注意:另外一种常见的约定就是不要用`controller`这个词来给controller文件命名,例如不要用`avengers.controller.js`,而是用`avengers.js`。所有其它的约定都坚持使用类型作为后缀,但是controller是组件中最为常用的类型,因此这种做法的好处貌似仅仅是节省了打字,但是仍然很容易识别。我建议你为你的团队选择一种约定,并且要保持统一性。 + 注意:另外一种常见的约定就是不要用`controller`这个词来给controller文件命名,例如不要用`avengers.controller.js`,而是用`avengers.js`。所有其它的约定都坚持使用类型作为后缀,但是controller是组件中最为常用的类型,因此这种做法的好处貌似仅仅是节省了打字,但是仍然很容易识别。我建议你为你的团队选择一种约定,并且要保持统一性。我喜欢的命名方式是`avengers.controller.js`。 ```javascript /** @@ -1915,7 +1924,7 @@ // avengers.controller.js angular .module - .controller('HeroAvengers', HeroAvengers); + .controller('HeroAvengersController', HeroAvengersController); function HeroAvengers(){ } ``` @@ -1923,28 +1932,13 @@ ###Controller命名后缀 ###### [Style [Y124](#style-y124)] - - 使用`Controller`后缀或者不加后缀。 + - 使用`Controller`。 *为什么?*:`Controller`使用更广泛、更明确、更具有描述性。 - *为什么?*:省略后缀则更简洁,但这样就不太好识别了。 - ```javascript /** - * recommended: Option 1 - */ - - // avengers.controller.js - angular - .module - .controller('Avengers', Avengers); - - function Avengers(){ } - ``` - - ```javascript - /** - * recommended: Option 2 + * recommended */ // avengers.controller.js @@ -2123,7 +2117,6 @@ app/ app.module.js app.config.js - app.routes.js directives/ calendar.directive.js calendar.directive.html @@ -2141,7 +2134,8 @@ topnav.controller.js people/ attendees.html - attendees.controller.js + attendees.controller.js + people.routes.js speakers.html speakers.controller.js speaker-detail.html @@ -2149,6 +2143,7 @@ sessions/ sessions.html sessions.controller.js + sessions.routes.js session-detail.html session-detail.controller.js ``` @@ -2207,7 +2202,7 @@ - 创建一个应用程序的根模块,它的职责是把应用程序中所有的模块和功能都放到一起。 - *为什么?*:AngularJS鼓励模块化和分离模式。创建根模块的作用是把其它模块都绑定到一起,这为增加或是删除一个模块提供了非常简单的方法。 + *为什么?*:Angular鼓励模块化和分离模式。创建根模块的作用是把其它模块都绑定到一起,这为增加或是删除一个模块提供了非常简单的方法。 *为什么?*:应用程序模块变成了一个描述哪些模块有助于定义应用程序的清单。 @@ -2241,7 +2236,7 @@ - 应用程序根模块依赖于应用程序特定的功能模块、共享的和可复用的模块。 - ![模块化和依赖](https://raw.githubusercontent.com/johnpapa/angularjs-styleguide/master/assets/modularity-1.png) + ![模块化和依赖](https://raw.githubusercontent.com/johnpapa/angular-styleguide/master/assets/modularity-1.png) *为什么?*:主程序模块包含一个能快速识别应用程序功能的清单。 @@ -2249,7 +2244,7 @@ *为什么?*:程序内部的功能,如共享数据的服务变得容易定位,并且从`app.core`中共享。 - 注意:这是保持一致性的一种策略,这里有很多不错的选择,选择一种统一的,遵循AngularJS依赖规则,这将易于维护和扩展。 + 注意:这是保持一致性的一种策略,这里有很多不错的选择,选择一种统一的,遵循Angular依赖规则,这将易于维护和扩展。 > 我的不同项目间的结构略有不同,但是它们都遵循了这些结构和模块化的准则,具体的实施方案会根据功能和团队发生变化。也就是说,不要在一棵树上吊死,但是心中一定要记得保持一致性、可维护性和效率。 @@ -2326,7 +2321,7 @@ - 用[`$timeout`](https://docs.angularjs.org/api/ng/service/$timeout)和[`$interval`](https://docs.angularjs.org/api/ng/service/$interval)代替`setTimeout`和`setInterval` 。 - *为什么?*:易于测试,处理AngularJS消化周期从而保证数据的同步绑定。 + *为什么?*:易于测试,处理Angular消化周期从而保证数据的同步绑定。 **[返回顶部](#目录)** @@ -2366,7 +2361,7 @@ - 用[Jasmine](http://jasmine.github.io/)或者[Mocha](http://mochajs.org)进行单元测试。 - *为什么?*:AngularJS社区中Jasmine和Mocha都用的很广,两者都很稳定,可维护性好,提供强大的测试功能。 + *为什么?*:Angular社区中Jasmine和Mocha都用的很广,两者都很稳定,可维护性好,提供强大的测试功能。 注意:使用Mocha时你可以考虑选择一个类似[Chai](http://chaijs.com)的提示库。 @@ -2390,7 +2385,9 @@ *为什么?*:Sinon可以和Jasmine和Mocha合作良好,并且可以扩展它们提供的stubbing和spying。 - *为什么?*:如果你想试试Jasmine和Mocha,用Sinon在它们中间来回切换是很方便的。 + *为什么?*:如果你想试试Jasmine和Mocha,用Sinon在它们中间来回切换是很方便的。我更喜欢Mocha。 + + *为什么?*:测试失败Sinon有一个具有描述性的信息。 ###Headless Browser ###### [Style [Y194](#style-y194)] @@ -2411,15 +2408,21 @@ ###对测试降低全局JSHint规则 ###### [Style [Y196](#style-y196) - - 对你的测试代码放松规则,这样可以允许使用`describe`和`expect`等类似通用的全局方法。 + - 对你的测试代码放宽规则,这样可以允许使用`describe`和`expect`等类似通用的全局方法。对表达式放宽规则,就行Mocha一样。 *为什么?*:测试也是代码,因此要和对待其它生产代码一样重视测试代码的质量。然而,测试框架中允许使用全局变量,例如,在你的测试单例中允许使用this。 ```javascript - /*global sinon, describe, it, afterEach, beforeEach, expect, inject */ + /* jshint -W117, -W030 */ + ``` + 或者你也可以把下面的这几行加入到你的JSHint Options文件中。 + + ```javascript + "jasmine": true, + "mocha": true, ``` - ![测试工具](https://raw.githubusercontent.com/johnpapa/angularjs-styleguide/master/assets/testing-tools.png) + ![测试工具](https://raw.githubusercontent.com/johnpapa/angular-styleguide/master/assets/testing-tools.png) ### 组织测试 ###### [Style [Y197](#style-y197)] @@ -2456,7 +2459,7 @@ ###用法 ###### [Style [Y210](#style-y210)] - - 在view和主要的视觉元素上使用细微的[AngularJS动画](https://docs.angularjs.org/guide/animations)进行过渡,包括[ngAnimate模块](https://docs.angularjs.org/api/ngAnimate)。三个关键点是细微、平滑、无缝。 + - 在view和主要的视觉元素上使用细微的[Angular动画](https://docs.angularjs.org/guide/animations)进行过渡,包括[ngAnimate模块](https://docs.angularjs.org/api/ngAnimate)。三个关键点是细微、平滑、无缝。 *为什么?*:使用得当的话能够提高用户体验。 @@ -2480,7 +2483,7 @@ *为什么?*:animate.css被广泛使用和测试。 - 注意:参阅[Matias Niemelä的关于AngularJS动画的文章](http://www.yearofmoo.com/2013/08/remastered-animation-in-angularjs-1-2.html) + 注意:参阅[Matias Niemelä的关于Angular动画的文章](http://www.yearofmoo.com/2013/08/remastered-animation-in-angularjs-1-2.html) **[返回顶部](#目录)** @@ -2615,12 +2618,100 @@ **[返回顶部](#目录)** +## JSCS + +### 用一个Options文件 +###### [Style [Y235](#style-y235)] + + - 使用JSCS检查代码风格,确保你的代码控制中有定制的JSCS options文件,在这里[JSCS docs](http://www.jscs.info)查看更多信息。 + + *为什么?*:提交代码前第一时间提供一个预警。 + + *为什么?*:保持团队的一致性。 + + ```javascript + { + "excludeFiles": ["node_modules/**", "bower_components/**"], + + "requireCurlyBraces": [ + "if", + "else", + "for", + "while", + "do", + "try", + "catch" + ], + "requireOperatorBeforeLineBreak": true, + "requireCamelCaseOrUpperCaseIdentifiers": true, + "maximumLineLength": { + "value": 100, + "allowComments": true, + "allowRegex": true + }, + "validateIndentation": 4, + "validateQuoteMarks": "'", + + "disallowMultipleLineStrings": true, + "disallowMixedSpacesAndTabs": true, + "disallowTrailingWhitespace": true, + "disallowSpaceAfterPrefixUnaryOperators": true, + "disallowMultipleVarDecl": null, + + "requireSpaceAfterKeywords": [ + "if", + "else", + "for", + "while", + "do", + "switch", + "return", + "try", + "catch" + ], + "requireSpaceBeforeBinaryOperators": [ + "=", "+=", "-=", "*=", "/=", "%=", "<<=", ">>=", ">>>=", + "&=", "|=", "^=", "+=", + + "+", "-", "*", "/", "%", "<<", ">>", ">>>", "&", + "|", "^", "&&", "||", "===", "==", ">=", + "<=", "<", ">", "!=", "!==" + ], + "requireSpaceAfterBinaryOperators": true, + "requireSpacesInConditionalExpression": true, + "requireSpaceBeforeBlockStatements": true, + "requireLineFeedAtFileEnd": true, + "disallowSpacesInsideObjectBrackets": "all", + "disallowSpacesInsideArrayBrackets": "all", + "disallowSpacesInsideParentheses": true, + + "validateJSDoc": { + "checkParamNames": true, + "requireParamTypes": true + }, + + "disallowMultipleLineBreaks": true, + + "disallowCommaBeforeLineBreak": null, + "disallowDanglingUnderscores": null, + "disallowEmptyBlocks": null, + "disallowMultipleLineStrings": null, + "disallowTrailingComma": null, + "requireCommaBeforeLineBreak": null, + "requireDotNotation": null, + "requireMultipleVarDecl": null, + "requireParenthesesAroundIIFE": true + } + ``` + +**[返回顶部](#目录)** + ## 常量 ###供应全局变量 ###### [Style [Y240](#style-y240)] - - 为供应库中的全局变量创建一个AngularJS常量。 + - 为供应库中的全局变量创建一个Angular常量。 *为什么?*:提供一种注入到供应库的方法,否则就是全局变量。通过让你更容易地了解你的组件之间的依赖关系来提高代码的可测试性。这还允许你模拟这些依赖关系,这是很有意义的。 @@ -2671,7 +2762,7 @@ ###Sublime Text ###### [Style [Y250](#style-y250)] - - AngularJS片段遵循这些风格指南。 + - Angular片段遵循这些风格指南。 - 下载[Sublime Angular snippets](assets/sublime-angular-snippets.zip?raw=true) - 把它放到Packages文件夹中 @@ -2697,7 +2788,7 @@ - 你可以把它们导入到WebStorm设置中: - - 下载[WebStorm AngularJS file templates and snippets](assets/webstorm-angular-file-template.settings.jar?raw=true) + - 下载[WebStorm Angular file templates and snippets](assets/webstorm-angular-file-template.settings.jar?raw=true) - 打开WebStorm点击`File`菜单 - 选择`Import Settings`菜单选项 - 选择文件点击`OK` @@ -2712,7 +2803,7 @@ ### Atom ###### [Style [Y253](#style-y253)] - - AngularJS snippets that follow these styles and guidelines. + - Angular snippets that follow these styles and guidelines. ``` apm install angularjs-styleguide-snippets ``` @@ -2782,6 +2873,8 @@ ## 任务自动化 用[Gulp](http://gulpjs.com)或者[Grunt](http://gruntjs.com)来创建自动化任务。Gulp偏向于代码在配置之上,Grunt更倾向于配置高于代码。我更倾向于使用gulp,因为gulp写起来比较简单。 +> 可以在我的[Gulp Pluralsight course](http://jpapa.me/gulpps)了解更多gulp和自动化任务的信息 + ###### [Style [Y400](#style-y400)] - 用任务自动化在其它JavaScript文件之前列出所有模块的定义文件`*.module.js`。 @@ -2802,7 +2895,17 @@ **[返回顶部](#目录)** -## AngularJS文档 +## Filters + +###### [Style [Y420](#style-y420)] + + - 避免使用filters扫描一个复杂对象的所有属性,应该用filters来筛选选择的属性。 + + *为什么?*:不恰当的使用会造成滥用并且会带来糟糕的性能问题,例如对一个复杂的对象使用过滤器。 + +**[返回顶部](#目录)** + +## Angular文档 [Angular文档](//docs.angularjs.org/api)。 ## 贡献 @@ -2821,9 +2924,9 @@ - **tldr;** 如果可以的话,使用本指南的时候还是指明归属吧。 -### (MIT许可证) +### Copyright -Copyright (c) 2014 [John Papa](http://johnpapa.net) +Copyright (c) 2014-2015 [John Papa](http://johnpapa.net) **[返回顶部](#目录)** From 35f38920ac514d8e12f41937eb849c2fb5ae2853 Mon Sep 17 00:00:00 2001 From: David Drabik Date: Mon, 9 Mar 2015 20:04:29 -0700 Subject: [PATCH 230/567] fixes typo in @desc --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 094b4465..04cb1797 100644 --- a/README.md +++ b/README.md @@ -1075,7 +1075,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see /* customerInfo.directive.js */ /** - * @desc spinner directive that can be used anywhere across the sales app at a company named Acme + * @desc sales directive that can be used anywhere across the sales app at a company named Acme * @example
*/ angular From 2456cd3f343e5f86492454469ce08a6541d6eaab Mon Sep 17 00:00:00 2001 From: David Drabik Date: Mon, 9 Mar 2015 22:22:03 -0700 Subject: [PATCH 231/567] adds link to mentioned naming section --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 04cb1797..6c783380 100644 --- a/README.md +++ b/README.md @@ -1104,7 +1104,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see } ``` - Note: There are many naming options for directives, especially since they can be used in narrow or wide scopes. Choose one that makes the directive and its file name distinct and clear. Some examples are below, but see the naming section for more recommendations. + Note: There are many naming options for directives, especially since they can be used in narrow or wide scopes. Choose one that makes the directive and its file name distinct and clear. Some examples are below, but see the [Naming](#naming) section for more recommendations. ### Manipulate DOM in a Directive ###### [Style [Y072](#style-y072)] From c7aaf7ea4e24cf0fc7d3d94e6fe0da501c3950dc Mon Sep 17 00:00:00 2001 From: angelochiello Date: Tue, 10 Mar 2015 08:38:52 +0100 Subject: [PATCH 232/567] [it-IT] Updated as #314 Updated as PR: #314: fixes typo --- i18n/it-IT.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/i18n/it-IT.md b/i18n/it-IT.md index b06b326f..e204610a 100644 --- a/i18n/it-IT.md +++ b/i18n/it-IT.md @@ -1074,7 +1074,7 @@ Nonostante questa guida spieghi i *cosa*, *come* e *perché*, trovo che sia di a /* customerInfo.directive.js */ /** - * @desc directive dello spinner che può essere usato dovunque nella applicazione di vendita di una azienda di nome Acme + * @desc directive delle vendite che può essere usato dovunque nella applicazione di vendita di una azienda di nome Acme * @example
*/ angular From 29ebbb3532b822fadf6b844fd1551eacdcb96f86 Mon Sep 17 00:00:00 2001 From: angelochiello Date: Wed, 11 Mar 2015 08:39:04 +0100 Subject: [PATCH 233/567] [it-IT] PR #315 Updated as PR: #315 adds link to naming section --- i18n/it-IT.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/i18n/it-IT.md b/i18n/it-IT.md index e204610a..a9bf8b43 100644 --- a/i18n/it-IT.md +++ b/i18n/it-IT.md @@ -1103,7 +1103,7 @@ Nonostante questa guida spieghi i *cosa*, *come* e *perché*, trovo che sia di a } ``` - Nota: Ci sono molte opzioni per i nomi delle directive, in particolare dal momento che possono essere usate in ambiti stretti o larghi. Scegline uno che sia chiaro e distino che dia senso alla directive e il suo nome del file. Alcuni esempi sono sotto ma vedi la sezione sulla nomenclatura per maggiori raccomandazioni. + Nota: Ci sono molte opzioni per i nomi delle directive, in particolare dal momento che possono essere usate in ambiti stretti o larghi. Scegline uno che sia chiaro e distino che dia senso alla directive e il suo nome del file. Alcuni esempi sono sotto ma vedi la sezione sulla [Nomenclatura](#nomenclatura) per maggiori raccomandazioni. ### Manipolare il DOM in una Directive ###### [Stile [Y072](#stile-y072)] From 39d99ef3413619cde751da41a58313baefd962f7 Mon Sep 17 00:00:00 2001 From: "Ademir Mazer Jr [ Nuno ]" Date: Wed, 11 Mar 2015 15:20:12 -0300 Subject: [PATCH 234/567] Update PT-BR.md --- i18n/PT-BR.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/i18n/PT-BR.md b/i18n/PT-BR.md index e8c577a9..467b5ebc 100644 --- a/i18n/PT-BR.md +++ b/i18n/PT-BR.md @@ -6,7 +6,7 @@ >The [original English version](http://jpapa.me/ngstyles) is the source of truth, as it is maintained and updated first. -Se você procura por um guia de estilo opinativo para sintaxe, convenções e estruturação de aplicações AngularJS, então siga em frente! Estes estilos são baseados em minha experiência com desenvolvimento com [AngularJS](//angularjs.org), apresentações, [cursos de treinamento na Pluralsight](http://pluralsight.com/training/Authors/Details/john-papa) e trabalhando em equipes. +Se você procura por um guia de estilo opinativo para sintaxe, convenções e estruturação de aplicações AngularJS, então siga em frente! Estes estilos são baseados em minha experiência com desenvolvimento com [AngularJS](//angularjs.org), apresentações, [cursos de treinamento na Pluralsight](http://pluralsight.com/training/Authors/Details/john-papa) e trabalhando em equipe. > Se você gostar deste estilo, confira meu curso [AngularJS Patterns: Clean Code](http://jpapa.me/ngclean) na Pluralsight. @@ -14,9 +14,9 @@ A proposta deste guia de estilo é fornecer uma direção na construção de apl ## A Importância da Comunidade e Créditos -Nunca trabalhe sozinho. Acho que a comunidade AngularJS é um grupo incrível que é apaixonado em compartilhar experiências. Dessa forma, Todd Motto, um amigo e expert em AngularJS e eu temos colaborado com vários estilos e convenções. Nós concordamos na maioria deles, e discordamos em alguns. Eu encorajo você a conferir o [guia do Todd](https://github.com/toddmotto/angularjs-styleguide) para ter uma noção sobre sua abordagem e como ela se compara a esta. +Nunca trabalhe sozinho. Acho que a comunidade AngularJS é um grupo incrível, apaixonado em compartilhar experiências. Dessa forma, Todd Motto, um amigo e expert em AngularJS e eu temos colaborado com vários estilos e convenções. Nós concordamos na maioria deles, e discordamos em alguns. Eu encorajo você a conferir o [guia do Todd](https://github.com/toddmotto/angularjs-styleguide) para ter uma noção sobre sua abordagem e como ela se compara a esta. -Vários de meus estilos vieram de várias sessões de pair-programming que [Ward Bell](http://twitter.com/wardbell) e eu tivemos. Embora não corcordemos sempre, meu amigo Ward certamente me ajudou influenciando na última evolução deste guia. +Vários de meus estilos vieram de várias sessões de pair-programming (programação em pares) que [Ward Bell](http://twitter.com/wardbell) e eu tivemos. Embora não concordemos sempre, meu amigo Ward certamente me ajudou influenciando na última evolução deste guia. ## Veja os estilos em um aplicativo de exemplo From 7c154c36371aaea390a3e92b56a9c10b15835069 Mon Sep 17 00:00:00 2001 From: Emmanuel DEMEY Date: Thu, 12 Mar 2015 09:20:13 +0100 Subject: [PATCH 235/567] Move Sublime snippets for ZIP archive into a new folder --- assets/sublime-angular-snippets.zip | Bin 2782 -> 0 bytes .../angular.controller.sublime-snippet | 24 +++++++++++++++ .../angular.directive.sublime-snippet | 28 ++++++++++++++++++ .../angular.factory.sublime-snippet | 25 ++++++++++++++++ .../angular.module.sublime-snippet | 13 ++++++++ 5 files changed, 90 insertions(+) delete mode 100644 assets/sublime-angular-snippets.zip create mode 100644 assets/sublime-angular-snippets/angular.controller.sublime-snippet create mode 100644 assets/sublime-angular-snippets/angular.directive.sublime-snippet create mode 100644 assets/sublime-angular-snippets/angular.factory.sublime-snippet create mode 100644 assets/sublime-angular-snippets/angular.module.sublime-snippet diff --git a/assets/sublime-angular-snippets.zip b/assets/sublime-angular-snippets.zip deleted file mode 100644 index adf5457805e5c3a941fcc7503a5c854f4a44dbd8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2782 zcmWIWW@h1H0DWPzMHm8r8bug5 zfDm1y2&zUsm*Du|lKi4nbQ9jru;x2tAmEbT%k6EVr+K%4Auqx8B1$Y5eWr{*!;KF+;v0Ar4)z+`O}Zi0vd-+BVvB%NM{V-Dk~?M6P93sF z^Z8rXl@v?QXSXU#Hi~`WWxjo5`~u~*e3y{y*Ilf3<-(vy{i3%V_q=u~h1}Mo$7d15`=B1bBBo^r<=jW9a<>%z2 z7U>n2Cgo)2rs@{wWfl~qmVlCpIJ;yB2!le)H*jNKvw^_fpIqTxEH0ue-nzwH(TLrZ z-fa|6tm^ix=Z&%Vk^SP21$G>)s(SzPPt9@NQ~TJpl+8rNr8p;e{VTGpl|O&n`_uD) z30Gz;d1F_dl-?L=6ckX?k+$m4v6ZLJ+z7w+@|LE@qq~3Ca#ZwO4*j-XVy%coex<%& z$`y(Io7DZ}dq3O$KJ<(|THwgHpJ#L%!^$`9t`{-=(qOt^Lc(#?>=zer&2~w0UYg=- zp2_WY?BJ#I*8?QYO5RMa{JG&$tlK0JpF?WTm2dy~sChC#P~~M?4O`4r-#La{&u9Gd zzMg&ZbLxvk){wvRdUK=qmfPt+K4e;C`-~46+p1q&7ZB_<3wRUa0 ztKsZ?H}(6wkgpROyDtScf4a#1Xg|Nx&soo!pW5uVxm}p#yJ_7;6}b|zbWur_$w&N` zA9k)aQ24dWKQys?SlTEqVp0(lSTcKPorv&eC7@16U1CsWPkJ#LoQJS>CM0=Fl>_S0<9 z*X8OFJ7H8ApuzL1{&M-k1TB_)?yL8_JnbibKFAeru_ug0CpCE4-D=~55w4p*B|p2` zvsdSOWN0!&#G|#*K@5i^mQFvs_1=T%`Q`fMcIt%|c_la23*L8E?PdyfIvQfYC;r2s zWT{YW&=G0hqMcv!(1;c z^LcpSc}2srztJ}x*l#ctG2Zg+w0*Z#N$N^$fx_+9cN4$8U%I{IsgFE!-sc5eJ)ssi zdwx0{tDj-rz2xEz@jkuDM_0!@Dze)1vu0g{VXor4BUgX{eM>B)_3aPaH4!TceTr{7 zE?pWbb1nRAmxc=S%&nXru7=*!v zi~ngZVBxaoxpt6%&_a#37uy=P%zxl(b7KduW|?y3oFnz?O*Q5oHaf$1xaUL0GR`KI zlGXq*=7b54uH2I^4c`7oG>|oU;`5SwHab-c>?{^D?VjlSD)9Kma_RpIf80>)I}m9W zzv_s1*|N8ZH;Oj>jN&z5ipo4n{w^wPeC^=9WXc>Nany&7o;R;)*FcN=l0sQ!KgPIwEK`$nt)mbHJt@A%f@qYQ zgaclU2Y7=FLDVD2RhtL{!jL76mZ*jxRVC=AVXxOXkxcvRXbX%_cr6zi!NCBl+8_?X zZUnM}{yLT*8-eCMRMQaNL$0snksP$7aT^ZPP%2GypF#`k6vM!RrTN>SgWdxGz zh^hQI;FTY8^nl8EB#hRVWSgpZR;&U*-N_=EnK!q4`rqe>P#f}xLEjWub4hC3} shHM8Y`y!`gO%yv;uwk_WS7zp5fMw + + ngcontroller + source.js + diff --git a/assets/sublime-angular-snippets/angular.directive.sublime-snippet b/assets/sublime-angular-snippets/angular.directive.sublime-snippet new file mode 100644 index 00000000..32983540 --- /dev/null +++ b/assets/sublime-angular-snippets/angular.directive.sublime-snippet @@ -0,0 +1,28 @@ + + + ngdirective + source.js + diff --git a/assets/sublime-angular-snippets/angular.factory.sublime-snippet b/assets/sublime-angular-snippets/angular.factory.sublime-snippet new file mode 100644 index 00000000..17da8d00 --- /dev/null +++ b/assets/sublime-angular-snippets/angular.factory.sublime-snippet @@ -0,0 +1,25 @@ + + + ngfactory + source.js + diff --git a/assets/sublime-angular-snippets/angular.module.sublime-snippet b/assets/sublime-angular-snippets/angular.module.sublime-snippet new file mode 100644 index 00000000..663b8666 --- /dev/null +++ b/assets/sublime-angular-snippets/angular.module.sublime-snippet @@ -0,0 +1,13 @@ + + + ngmodule + source.js + From 309ecd568a8379c58c540ed112533053844dca48 Mon Sep 17 00:00:00 2001 From: John Papa Date: Thu, 12 Mar 2015 07:04:56 -0400 Subject: [PATCH 236/567] period --- README.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 8d104a18..6c9f3e85 100644 --- a/README.md +++ b/README.md @@ -783,7 +783,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see } ``` - This way bindings are mirrored across the host object, primitive values cannot update alone using the revealing module pattern + This way bindings are mirrored across the host object, primitive values cannot update alone using the revealing module pattern. ![Factories Using "Above the Fold"](https://raw.githubusercontent.com/johnpapa/angular-styleguide/master/assets/above-the-fold-2.png) @@ -1678,7 +1678,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see ```javascript gulp.task('js', ['jshint'], function() { var source = pkg.paths.js; - + return gulp.src(source) .pipe(sourcemaps.init()) .pipe(concat('all.min.js', {newLine: ';'})) @@ -2808,7 +2808,7 @@ Use file templates or snippets to help follow consistent styles and patterns. He ng-f // creates an Angular factory ng-m // creates an Angular module ``` - + ### Atom ###### [Style [Y253](#style-y253)] @@ -2820,7 +2820,7 @@ Use file templates or snippets to help follow consistent styles and patterns. He - Open Atom, then open the Package Manager (Packages -> Settings View -> Install Packages/Themes) - Search for the package 'angularjs-styleguide-snippets' - Click 'Install' to install the package - + - In a JavaScript file type these commands followed by a `TAB` ```javascript @@ -2912,7 +2912,7 @@ Use [Gulp](http://gulpjs.com) or [Grunt](http://gruntjs.com) for creating automa - Avoid using filters for scanning all properties of a complex object graph. Use filters for select properties. - *Why?*: Filters can easily be abused and negatively effect performance if not used wisely, for example when a filter hits a large and deep object graph. + *Why?*: Filters can easily be abused and negatively effect performance if not used wisely, for example when a filter hits a large and deep object graph. **[Back to top](#table-of-contents)** From 620ffc5dadf0b275f28c85e0489838897876eb75 Mon Sep 17 00:00:00 2001 From: John Papa Date: Thu, 12 Mar 2015 07:06:01 -0400 Subject: [PATCH 237/567] point sublime snippets to folder, not zip --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 6c9f3e85..e5e93ba7 100644 --- a/README.md +++ b/README.md @@ -2771,7 +2771,7 @@ Use file templates or snippets to help follow consistent styles and patterns. He - Angular snippets that follow these styles and guidelines. - - Download the [Sublime Angular snippets](assets/sublime-angular-snippets.zip?raw=true) + - Download the [Sublime Angular snippets](assets/sublime-angular-snippets?raw=true) - Place it in your Packages folder - Restart Sublime - In a JavaScript file type these commands followed by a `TAB` From 4bd21ee3411f119b938f8de2c603aa761367f691 Mon Sep 17 00:00:00 2001 From: John Papa Date: Thu, 12 Mar 2015 07:06:49 -0400 Subject: [PATCH 238/567] comments for ngservice for sublime --- README.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index e5e93ba7..7313b6da 100644 --- a/README.md +++ b/README.md @@ -2778,9 +2778,10 @@ Use file templates or snippets to help follow consistent styles and patterns. He ```javascript ngcontroller // creates an Angular controller - ngdirective // creates an Angular directive - ngfactory // creates an Angular factory - ngmodule // creates an Angular module + ngdirective // creates an Angular directive + ngfactory // creates an Angular factory + ngmodule // creates an Angular module + ngservice // creates an Angular service ``` ### Visual Studio From 5a35ada46779eccd07a7a61c51fc86f21267196f Mon Sep 17 00:00:00 2001 From: John Papa Date: Thu, 12 Mar 2015 07:11:28 -0400 Subject: [PATCH 239/567] revised sublime snippets with service --- assets/sublime-angular-snippets.zip | Bin 2782 -> 0 bytes .../angular.controller.sublime-snippet | 25 ++++++++++++ .../angular.directive.sublime-snippet | 37 ++++++++++++++++++ .../angular.factory.sublime-snippet | 25 ++++++++++++ .../angular.module.sublime-snippet | 13 ++++++ .../angular.service.sublime-snippet | 22 +++++++++++ 6 files changed, 122 insertions(+) delete mode 100644 assets/sublime-angular-snippets.zip create mode 100644 assets/sublime-angular-snippets/angular.controller.sublime-snippet create mode 100644 assets/sublime-angular-snippets/angular.directive.sublime-snippet create mode 100644 assets/sublime-angular-snippets/angular.factory.sublime-snippet create mode 100644 assets/sublime-angular-snippets/angular.module.sublime-snippet create mode 100644 assets/sublime-angular-snippets/angular.service.sublime-snippet diff --git a/assets/sublime-angular-snippets.zip b/assets/sublime-angular-snippets.zip deleted file mode 100644 index adf5457805e5c3a941fcc7503a5c854f4a44dbd8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2782 zcmWIWW@h1H0DWPzMHm8r8bug5 zfDm1y2&zUsm*Du|lKi4nbQ9jru;x2tAmEbT%k6EVr+K%4Auqx8B1$Y5eWr{*!;KF+;v0Ar4)z+`O}Zi0vd-+BVvB%NM{V-Dk~?M6P93sF z^Z8rXl@v?QXSXU#Hi~`WWxjo5`~u~*e3y{y*Ilf3<-(vy{i3%V_q=u~h1}Mo$7d15`=B1bBBo^r<=jW9a<>%z2 z7U>n2Cgo)2rs@{wWfl~qmVlCpIJ;yB2!le)H*jNKvw^_fpIqTxEH0ue-nzwH(TLrZ z-fa|6tm^ix=Z&%Vk^SP21$G>)s(SzPPt9@NQ~TJpl+8rNr8p;e{VTGpl|O&n`_uD) z30Gz;d1F_dl-?L=6ckX?k+$m4v6ZLJ+z7w+@|LE@qq~3Ca#ZwO4*j-XVy%coex<%& z$`y(Io7DZ}dq3O$KJ<(|THwgHpJ#L%!^$`9t`{-=(qOt^Lc(#?>=zer&2~w0UYg=- zp2_WY?BJ#I*8?QYO5RMa{JG&$tlK0JpF?WTm2dy~sChC#P~~M?4O`4r-#La{&u9Gd zzMg&ZbLxvk){wvRdUK=qmfPt+K4e;C`-~46+p1q&7ZB_<3wRUa0 ztKsZ?H}(6wkgpROyDtScf4a#1Xg|Nx&soo!pW5uVxm}p#yJ_7;6}b|zbWur_$w&N` zA9k)aQ24dWKQys?SlTEqVp0(lSTcKPorv&eC7@16U1CsWPkJ#LoQJS>CM0=Fl>_S0<9 z*X8OFJ7H8ApuzL1{&M-k1TB_)?yL8_JnbibKFAeru_ug0CpCE4-D=~55w4p*B|p2` zvsdSOWN0!&#G|#*K@5i^mQFvs_1=T%`Q`fMcIt%|c_la23*L8E?PdyfIvQfYC;r2s zWT{YW&=G0hqMcv!(1;c z^LcpSc}2srztJ}x*l#ctG2Zg+w0*Z#N$N^$fx_+9cN4$8U%I{IsgFE!-sc5eJ)ssi zdwx0{tDj-rz2xEz@jkuDM_0!@Dze)1vu0g{VXor4BUgX{eM>B)_3aPaH4!TceTr{7 zE?pWbb1nRAmxc=S%&nXru7=*!v zi~ngZVBxaoxpt6%&_a#37uy=P%zxl(b7KduW|?y3oFnz?O*Q5oHaf$1xaUL0GR`KI zlGXq*=7b54uH2I^4c`7oG>|oU;`5SwHab-c>?{^D?VjlSD)9Kma_RpIf80>)I}m9W zzv_s1*|N8ZH;Oj>jN&z5ipo4n{w^wPeC^=9WXc>Nany&7o;R;)*FcN=l0sQ!KgPIwEK`$nt)mbHJt@A%f@qYQ zgaclU2Y7=FLDVD2RhtL{!jL76mZ*jxRVC=AVXxOXkxcvRXbX%_cr6zi!NCBl+8_?X zZUnM}{yLT*8-eCMRMQaNL$0snksP$7aT^ZPP%2GypF#`k6vM!RrTN>SgWdxGz zh^hQI;FTY8^nl8EB#hRVWSgpZR;&U*-N_=EnK!q4`rqe>P#f}xLEjWub4hC3} shHM8Y`y!`gO%yv;uwk_WS7zp5fMw + + ngcontroller + source.js + diff --git a/assets/sublime-angular-snippets/angular.directive.sublime-snippet b/assets/sublime-angular-snippets/angular.directive.sublime-snippet new file mode 100644 index 00000000..e1aae15e --- /dev/null +++ b/assets/sublime-angular-snippets/angular.directive.sublime-snippet @@ -0,0 +1,37 @@ + + + ngdirective + source.js + diff --git a/assets/sublime-angular-snippets/angular.factory.sublime-snippet b/assets/sublime-angular-snippets/angular.factory.sublime-snippet new file mode 100644 index 00000000..17da8d00 --- /dev/null +++ b/assets/sublime-angular-snippets/angular.factory.sublime-snippet @@ -0,0 +1,25 @@ + + + ngfactory + source.js + diff --git a/assets/sublime-angular-snippets/angular.module.sublime-snippet b/assets/sublime-angular-snippets/angular.module.sublime-snippet new file mode 100644 index 00000000..663b8666 --- /dev/null +++ b/assets/sublime-angular-snippets/angular.module.sublime-snippet @@ -0,0 +1,13 @@ + + + ngmodule + source.js + diff --git a/assets/sublime-angular-snippets/angular.service.sublime-snippet b/assets/sublime-angular-snippets/angular.service.sublime-snippet new file mode 100644 index 00000000..aa2bc250 --- /dev/null +++ b/assets/sublime-angular-snippets/angular.service.sublime-snippet @@ -0,0 +1,22 @@ + + + ngservice + source.js + From 87e140061c8fcbd7b31f7ad4cf7d62cc76c061ae Mon Sep 17 00:00:00 2001 From: John Papa Date: Thu, 12 Mar 2015 07:20:52 -0400 Subject: [PATCH 240/567] fixing merges. ugh --- .../angular.controller.sublime-snippet | 20 ++++++++----------- .../angular.directive.sublime-snippet | 9 +-------- 2 files changed, 9 insertions(+), 20 deletions(-) diff --git a/assets/sublime-angular-snippets/angular.controller.sublime-snippet b/assets/sublime-angular-snippets/angular.controller.sublime-snippet index a5f82025..2e9079e2 100644 --- a/assets/sublime-angular-snippets/angular.controller.sublime-snippet +++ b/assets/sublime-angular-snippets/angular.controller.sublime-snippet @@ -4,7 +4,6 @@ angular .module('${1:module}') -<<<<<<< HEAD .controller('${2:Controller}', ${2:Controller}); /* @ngInject */ @@ -16,19 +15,16 @@ //////////////// -======= - .controller('${2:Ctrl}', ${2:Ctrl}); + /* @ngInject */ + function ${2:Ctrl}(${3:dependencies}) { + /*jshint validthis: true */ + var vm = this; + vm.title = '${2:Ctrl}'; - /* @ngInject */ - function ${2:Ctrl}(${3:dependencies}) { - /*jshint validthis: true */ - var vm = this; - vm.title = '${2:Ctrl}'; - - activate(); + activate(); ->>>>>>> 93eb74f33dd1304fdc4ab48fd47166055650a1ff - function activate() { + function activate() { + } } } })(); diff --git a/assets/sublime-angular-snippets/angular.directive.sublime-snippet b/assets/sublime-angular-snippets/angular.directive.sublime-snippet index 28b9f031..62a9e127 100644 --- a/assets/sublime-angular-snippets/angular.directive.sublime-snippet +++ b/assets/sublime-angular-snippets/angular.directive.sublime-snippet @@ -13,31 +13,24 @@ // Creates: // var directive = { -<<<<<<< HEAD + bindToController: true, controller: ${4:Controller}, controllerAs: '${5:vm}', link: link, restrict: 'A', scope: { } -======= - link: link, - restrict: 'A' ->>>>>>> 93eb74f33dd1304fdc4ab48fd47166055650a1ff }; return directive; function link(scope, element, attrs) { } } -<<<<<<< HEAD /* @ngInject */ function ${4:Controller} () { } -======= ->>>>>>> 93eb74f33dd1304fdc4ab48fd47166055650a1ff })(); ]]> ngdirective From 9cb9b9a445b073465cd9018fdcaf035c826cdff2 Mon Sep 17 00:00:00 2001 From: Oscar Bolmsten Date: Thu, 12 Mar 2015 13:43:24 +0100 Subject: [PATCH 241/567] Fix merge conflict in Sublime snippet --- .../angular.controller.sublime-snippet | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/assets/sublime-angular-snippets/angular.controller.sublime-snippet b/assets/sublime-angular-snippets/angular.controller.sublime-snippet index 2e9079e2..de0a18ca 100644 --- a/assets/sublime-angular-snippets/angular.controller.sublime-snippet +++ b/assets/sublime-angular-snippets/angular.controller.sublime-snippet @@ -15,16 +15,7 @@ //////////////// - /* @ngInject */ - function ${2:Ctrl}(${3:dependencies}) { - /*jshint validthis: true */ - var vm = this; - vm.title = '${2:Ctrl}'; - - activate(); - - function activate() { - } + function activate() { } } })(); From eddcf0871544c98384b1df7be4828a8c5dd577e3 Mon Sep 17 00:00:00 2001 From: Ewerton Date: Thu, 12 Mar 2015 13:56:01 -0300 Subject: [PATCH 242/567] Minor fixes in translation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Minor fixes in translation - en Pequenas correções na tradução - pt-br --- i18n/PT-BR.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/i18n/PT-BR.md b/i18n/PT-BR.md index 467b5ebc..fbb661d6 100644 --- a/i18n/PT-BR.md +++ b/i18n/PT-BR.md @@ -8,7 +8,7 @@ Se você procura por um guia de estilo opinativo para sintaxe, convenções e estruturação de aplicações AngularJS, então siga em frente! Estes estilos são baseados em minha experiência com desenvolvimento com [AngularJS](//angularjs.org), apresentações, [cursos de treinamento na Pluralsight](http://pluralsight.com/training/Authors/Details/john-papa) e trabalhando em equipe. -> Se você gostar deste estilo, confira meu curso [AngularJS Patterns: Clean Code](http://jpapa.me/ngclean) na Pluralsight. +> Se você gostar deste guia, confira meu curso [AngularJS Patterns: Clean Code](http://jpapa.me/ngclean) na Pluralsight. A proposta deste guia de estilo é fornecer uma direção na construção de aplicações AngularJS mostrando convenções que eu uso, e o mais importante, porque eu as escolhi. @@ -16,7 +16,7 @@ A proposta deste guia de estilo é fornecer uma direção na construção de apl Nunca trabalhe sozinho. Acho que a comunidade AngularJS é um grupo incrível, apaixonado em compartilhar experiências. Dessa forma, Todd Motto, um amigo e expert em AngularJS e eu temos colaborado com vários estilos e convenções. Nós concordamos na maioria deles, e discordamos em alguns. Eu encorajo você a conferir o [guia do Todd](https://github.com/toddmotto/angularjs-styleguide) para ter uma noção sobre sua abordagem e como ela se compara a esta. -Vários de meus estilos vieram de várias sessões de pair-programming (programação em pares) que [Ward Bell](http://twitter.com/wardbell) e eu tivemos. Embora não concordemos sempre, meu amigo Ward certamente me ajudou influenciando na última evolução deste guia. +Vários de meus estilos vieram de várias sessões de pair-programming (programação pareada) que [Ward Bell](http://twitter.com/wardbell) e eu tivemos. Embora não concordemos sempre, meu amigo Ward certamente me ajudou influenciando na última evolução deste guia. ## Veja os estilos em um aplicativo de exemplo From def49f6fb94cd1f97b853433b126715dd20a9730 Mon Sep 17 00:00:00 2001 From: leolower Date: Thu, 12 Mar 2015 15:06:30 -0300 Subject: [PATCH 243/567] New sublime snippet for filters. --- .../angular.filter.sublime-snippet | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 assets/sublime-angular-snippets/angular.filter.sublime-snippet diff --git a/assets/sublime-angular-snippets/angular.filter.sublime-snippet b/assets/sublime-angular-snippets/angular.filter.sublime-snippet new file mode 100644 index 00000000..dba88bb1 --- /dev/null +++ b/assets/sublime-angular-snippets/angular.filter.sublime-snippet @@ -0,0 +1,22 @@ + + + ngfilter + source.js + From 52d3fbed9dfd79cb04bf386c39717e5ca3b315e2 Mon Sep 17 00:00:00 2001 From: "T. Zengerink" Date: Fri, 13 Mar 2015 09:49:12 +0100 Subject: [PATCH 244/567] fixed indentation of code sample --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index e8dae3e9..a26aa086 100644 --- a/README.md +++ b/README.md @@ -607,7 +607,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see function checkCredit() { return creditService.isOrderTotalOk(vm.total) - .then(function(isOk) { vm.isCreditOk = isOk; }) + .then(function(isOk) { vm.isCreditOk = isOk; }) .catch(showServiceError); }; } From 2b9f252e4bbe129a0e24c110682f4b6f021eca96 Mon Sep 17 00:00:00 2001 From: "T. Zengerink" Date: Fri, 13 Mar 2015 10:19:18 +0100 Subject: [PATCH 245/567] fixed indentation for a code example --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index e8dae3e9..8f235a8e 100644 --- a/README.md +++ b/README.md @@ -1215,9 +1215,9 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see }, link: linkFunc, controller: ExampleController, - controllerAs: 'vm', - bindToController: true // because the scope is isolated - }; + controllerAs: 'vm', + bindToController: true // because the scope is isolated + }; return directive; From 8b3da1cebcd24e5a5b958350987e7f3f453986e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=B5=B5=E5=8F=AF?= Date: Fri, 13 Mar 2015 18:39:14 +0800 Subject: [PATCH 246/567] update to latest --- i18n/zh-CN.md | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/i18n/zh-CN.md b/i18n/zh-CN.md index 86d380f3..39b41dbe 100644 --- a/i18n/zh-CN.md +++ b/i18n/zh-CN.md @@ -557,10 +557,10 @@ } ``` -###把Controller中的逻辑推迟到Service中 +###把Controller中的逻辑延迟到Service中 ###### [Style [Y035](#style-y035)] - - 通过委派到service和factory中来推迟controller中的逻辑。 + - 通过委派到service和factory中来延迟controller中的逻辑。 *为什么?*:把逻辑放到service中,并通过一个function暴露,就可以被多个controller重用。 @@ -1075,7 +1075,7 @@ /* customerInfo.directive.js */ /** - * @desc spinner directive that can be used anywhere across the sales app at a company named Acme + * @desc sales directive that can be used anywhere across the sales app at a company named Acme * @example
*/ angular @@ -1104,7 +1104,7 @@ } ``` - 注:directive有很多命名选项,特别是从它们能够在一个狭隘的或者广泛的作用域中使用时。选择一个让directive和它的文件名都清楚分明的名字。下面有一些例子,不过更多的建议去看命名章节。 + 注:directive有很多命名选项,特别是从它们能够在一个狭隘的或者广泛的作用域中使用时。选择一个让directive和它的文件名都清楚分明的名字。下面有一些例子,不过更多的建议去看[命名](#命名)章节。 ###在directive中操作DOM ###### [Style [Y072](#style-y072)] @@ -1667,6 +1667,7 @@ ```javascript gulp.task('js', ['jshint'], function() { var source = pkg.paths.js; + return gulp.src(source) .pipe(sourcemaps.init()) .pipe(concat('all.min.js', {newLine: ';'})) @@ -2764,16 +2765,16 @@ - Angular片段遵循这些风格指南。 - - 下载[Sublime Angular snippets](assets/sublime-angular-snippets.zip?raw=true) + - 下载[Sublime Angular snippets](assets/sublime-angular-snippets?raw=true) - 把它放到Packages文件夹中 - 重启Sublime - 在JavaScript文件中输入下面的命令然后按下`TAB`键即可: ```javascript ngcontroller // creates an Angular controller - ngdirective // creates an Angular directive - ngfactory // creates an Angular factory - ngmodule // creates an Angular module + ngdirective // creates an Angular directive + ngfactory // creates an Angular factory + ngmodule // creates an Angular module ``` ###Visual Studio @@ -2799,7 +2800,7 @@ ng-f // creates an Angular factory ng-m // creates an Angular module ``` - + ### Atom ###### [Style [Y253](#style-y253)] @@ -2811,7 +2812,7 @@ - Open Atom, then open the Package Manager (Packages -> Settings View -> Install Packages/Themes) - Search for the package 'angularjs-styleguide-snippets' - Click 'Install' to install the package - + - In a JavaScript file type these commands followed by a `TAB` ```javascript From 5a142c97856414a5bcb383a9b518eee5c7358008 Mon Sep 17 00:00:00 2001 From: angelochiello Date: Fri, 13 Mar 2015 12:38:43 +0100 Subject: [PATCH 247/567] [it-IT] PR #331 Updated as PR: #331 --- i18n/it-IT.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/i18n/it-IT.md b/i18n/it-IT.md index a9bf8b43..f36cf18b 100644 --- a/i18n/it-IT.md +++ b/i18n/it-IT.md @@ -605,7 +605,7 @@ Nonostante questa guida spieghi i *cosa*, *come* e *perché*, trovo che sia di a function checkCredit() { return creditService.isOrderTotalOk(vm.total) - .then(function(isOk) { vm.isCreditOk = isOk; }) + .then(function(isOk) { vm.isCreditOk = isOk; }) .catch(showServiceError); }; } From 0142f1c35c0b405c48621e1e7c775a46495b86c9 Mon Sep 17 00:00:00 2001 From: leolower Date: Fri, 13 Mar 2015 16:41:42 -0300 Subject: [PATCH 248/567] Updated Readme with sublime snippet for filters. --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index e8dae3e9..02828c7b 100644 --- a/README.md +++ b/README.md @@ -2788,6 +2788,7 @@ Use file templates or snippets to help follow consistent styles and patterns. He ngfactory // creates an Angular factory ngmodule // creates an Angular module ngservice // creates an Angular service + ngfilter // creates an Angular filter ``` ### Visual Studio From 7b6d0b06c87fab1f28be613649eee3317710554b Mon Sep 17 00:00:00 2001 From: John Papa Date: Sat, 14 Mar 2015 20:34:57 -0400 Subject: [PATCH 249/567] brackets snippets as per style guide --- assets/brackets-angular-snippets.yaml | 199 ++++++++++++++++++++++++++ 1 file changed, 199 insertions(+) create mode 100644 assets/brackets-angular-snippets.yaml diff --git a/assets/brackets-angular-snippets.yaml b/assets/brackets-angular-snippets.yaml new file mode 100644 index 00000000..9cd1b38e --- /dev/null +++ b/assets/brackets-angular-snippets.yaml @@ -0,0 +1,199 @@ +- trigger: ngfilter + description: Angular filter using John Papa's Angular style guide + scope: javascript + text: | + (function () { + 'use strict'; + angular + .module('${1:module}') + .filter('${2:filter}', ${2:filter}); + + + function ${2:filter}() { + return ${2:filter}Filter; + //////////////// + + function ${2:filter}Filter(${3:parameters}) { + return ${3:parameters}; + }; + } + })(); + +- trigger: ngservice + description: Angular service using John Papa's Angular style guide + scope: javascript + text: | + (function () { + 'use strict'; + angular + .module('${1:module}') + .service('${2:Service}', ${2:Service}); + + ${2:Service}.$inject = ['${3:dependencies}']; + + /* @ngInject */ + function ${2:Service}(${3:dependencies}) { + this.${4:func} = ${4:func}; + + //////////////// + + function ${4:func}() { + + } + } + })(); + +- trigger: ngapp + description: Angular module app definition using John Papa's Angular style guide + scope: javascript + text: | + (function () { + 'use strict'; + + angular + .module('${1:module}', [ + '${2:dependencies}' + ]); + + })(); + +- trigger: ngfactory + description: Angular factory using John Papa's Angular style guide + scope: javascript + text: | + (function () { + 'use strict'; + angular + .module('${1:module}') + .factory('${2:factory}', ${2:factory}); + + ${2:factory}.$inject = ['${3:dependencies}']; + + /* @ngInject */ + function ${2: Factory}(${3:dependencies}){ + var exports = { + ${4:func}: ${4:func} + }; + + return exports; + + //////////////// + function ${4:func}() { + + } + } + })(); + +- trigger: ngdirective + description: Angular directive using John Papa's Angular style guide + scope: javascript + text: | + (function () { + 'use strict'; + + + angular + .module('${1:module}') + .directive('${2:directive}', ${2:directive}); + + ${2:directive}.$inject = ['${3:dependencies}']; + + /* @ngInject */ + function ${2: directive}(${3:dependencies}) { + // Usage: + // + // Creates: + // + var directive = { + bindToController: true, + controller: ${4:Controller}, + controllerAs: '${5:vm}', + link: link, + restrict: 'A', + scope: {} + }; + return directive; + + function link(scope, element, attrs, controller) {} + } + + ${4:Controller}.$inject = ['${6:dependencies}']; + + /* @ngInject */ + function ${4:Controller}(${6:dependencies}) { + + } + + })(); + +- trigger: ngcontroller + description: Angular controller using John Papa's Angular style guide + scope: javascript + text: | + (function() { + 'use strict'; + + angular + .module('${1:module}') + .controller('${2:Controller}', ${2:Controller}); + + ${2:Controller}.$inject = ['${3:dependencies}']; + + /* @ngInject */ + function ${2:Controller}(${3:dependencies}){ + var vm = this; + vm.${4:property} = '${2:Controller}'; + + activate(); + + //////////////// + + function activate() { + } + } + })(); + +- trigger: ngstate + description: Angular UI-Router state using John Papa's Angular style guide + scope: javascript + text: | + state('${1:state}', { + url: '${2:/url}' + templateUrl: '${3:template}.html', + controller: '${4:Controller}' + controllerAs: '${5:vm}' + }) + + +- trigger: ngmodule + description: Angular module getter using John Papa's Angular style guide + scope: javascript + text: | + angular + .module('${1:module}') + +- trigger: ngconfig + description: Angular config phase function using John Papa's Angular style guide + scope: javascript + text: | + .config(${1:configuration}) + + ${1:configuration}.$inject = ['${2:dependencies}']; + + /* @ngInject */ + function ${1:configuration} (${2:dependencies}) { + + } + +- trigger: ngrun + description: Angular run phase function using John Papa's Angular style guide + scope: javascript + text: | + .run(${1:runFn}) + + ${1:runFn}.$inject = ['${2:dependencies}']; + + /* @ngInject */ + function ${1:runFn} (${2:dependencies}) { + + } From cb9172b11e55aaa6b17c3a330dd30e2a941f4045 Mon Sep 17 00:00:00 2001 From: John Papa Date: Sat, 14 Mar 2015 20:44:07 -0400 Subject: [PATCH 250/567] added brackets snippets instructions --- README.md | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/README.md b/README.md index 6b421b84..fa07fd05 100644 --- a/README.md +++ b/README.md @@ -2838,6 +2838,36 @@ Use file templates or snippets to help follow consistent styles and patterns. He ngmodule // creates an Angular module ``` +### Brackets +###### [Style [Y254](#style-y254)] + + - Angular snippets that follow these styles and guidelines. + + - Brackets Extension manager ( File > Extension manager ) + - Install 'Brackets Snippets (by edc)' + - Click the light bulb in brackets' right gutter + - Click `Settings` and then `Import` + - Choose the file and select to skip or override + - Click `Start Import` + + - In a JavaScript file type these commands followed by a `TAB` + + ```javascript + // These are full file snippets containing an IIFE + ngcontroller // creates an Angular controller + ngdirective // creates an Angular directive + ngfactory // creates an Angular factory + ngapp // creates an Angular module setter + ngservice // creates an Angular service + ngfilter // creates an Angular filter + + // These are partial snippets intended to chained + ngmodule // creates an Angular module getter + ngstate // creates an Angular UI Router state defintion + ngconfig // defines a configuration phase function + ngrun // defines a run phase function + ``` + **[Back to top](#table-of-contents)** ## Yeoman Generator From f430bdbbd36b70e88ef62f74d9a865617d7eef49 Mon Sep 17 00:00:00 2001 From: John Papa Date: Sat, 14 Mar 2015 20:44:49 -0400 Subject: [PATCH 251/567] added brackets snippets instructions --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index fa07fd05..ef414154 100644 --- a/README.md +++ b/README.md @@ -2844,7 +2844,7 @@ Use file templates or snippets to help follow consistent styles and patterns. He - Angular snippets that follow these styles and guidelines. - Brackets Extension manager ( File > Extension manager ) - - Install 'Brackets Snippets (by edc)' + - Install ['Brackets Snippets (by edc)'](https://github.com/chuyik/brackets-snippets) - Click the light bulb in brackets' right gutter - Click `Settings` and then `Import` - Choose the file and select to skip or override From c2e29db3d4e3e9482622cf9b05dc13114f0115b7 Mon Sep 17 00:00:00 2001 From: Jeff Balboni Date: Sun, 15 Mar 2015 00:02:19 -0400 Subject: [PATCH 252/567] Added text about avoiding $ in service names --- README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index ef414154..3d081fdc 100644 --- a/README.md +++ b/README.md @@ -1964,9 +1964,11 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see ### Factory Names ###### [Style [Y125](#style-y125)] - - Use consistent names for all factories named after their feature. Use camel-casing for services and factories. + - Use consistent names for all factories named after their feature. Use camel-casing for services and factories. Avoid prefixing factories and services with `$`. *Why?*: Provides a consistent way to quickly identify and reference factories. + + *Why?*: Avoids name collisions with built-in factories and services that use the `$` prefix. ```javascript /** From 0ec87f5483fea33136a2abe1cbb78c96032dca6f Mon Sep 17 00:00:00 2001 From: sanjeya Date: Sun, 15 Mar 2015 11:52:49 +0100 Subject: [PATCH 253/567] added ngroute and ngwhen --- README.md | 2 + assets/brackets-angular-snippets.yaml | 102 +++++++++++++++++--------- 2 files changed, 69 insertions(+), 35 deletions(-) diff --git a/README.md b/README.md index ef414154..3ffe510e 100644 --- a/README.md +++ b/README.md @@ -2860,12 +2860,14 @@ Use file templates or snippets to help follow consistent styles and patterns. He ngapp // creates an Angular module setter ngservice // creates an Angular service ngfilter // creates an Angular filter + ngroute // creates an Angular routeProvider // These are partial snippets intended to chained ngmodule // creates an Angular module getter ngstate // creates an Angular UI Router state defintion ngconfig // defines a configuration phase function ngrun // defines a run phase function + ngwhen // defines a route for the routeProvider ``` **[Back to top](#table-of-contents)** diff --git a/assets/brackets-angular-snippets.yaml b/assets/brackets-angular-snippets.yaml index 9cd1b38e..7839a74d 100644 --- a/assets/brackets-angular-snippets.yaml +++ b/assets/brackets-angular-snippets.yaml @@ -1,5 +1,5 @@ - trigger: ngfilter - description: Angular filter using John Papa's Angular style guide + description: "Angular filter using John Papa's Angular style guide" scope: javascript text: | (function () { @@ -20,7 +20,7 @@ })(); - trigger: ngservice - description: Angular service using John Papa's Angular style guide + description: "Angular service using John Papa's Angular style guide" scope: javascript text: | (function () { @@ -34,17 +34,17 @@ /* @ngInject */ function ${2:Service}(${3:dependencies}) { this.${4:func} = ${4:func}; - + //////////////// - + function ${4:func}() { - + } } })(); - trigger: ngapp - description: Angular module app definition using John Papa's Angular style guide + description: "Angular module app definition using John Papa's Angular style guide" scope: javascript text: | (function () { @@ -58,7 +58,7 @@ })(); - trigger: ngfactory - description: Angular factory using John Papa's Angular style guide + description: "Angular factory using John Papa's Angular style guide" scope: javascript text: | (function () { @@ -85,7 +85,7 @@ })(); - trigger: ngdirective - description: Angular directive using John Papa's Angular style guide + description: "Angular directive using John Papa's Angular style guide" scope: javascript text: | (function () { @@ -127,7 +127,7 @@ })(); - trigger: ngcontroller - description: Angular controller using John Papa's Angular style guide + description: "Angular controller using John Papa's Angular style guide" scope: javascript text: | (function() { @@ -154,46 +154,78 @@ })(); - trigger: ngstate - description: Angular UI-Router state using John Papa's Angular style guide + description: "Angular UI-Router state using John Papa's Angular style guide" scope: javascript text: | - state('${1:state}', { - url: '${2:/url}' - templateUrl: '${3:template}.html', - controller: '${4:Controller}' - controllerAs: '${5:vm}' - }) - + state('${1:state}', { + url: '${2:/url}' + templateUrl: '${3:template}.html', + controller: '${4:Controller}' + controllerAs: '${5:vm}' + }) - trigger: ngmodule - description: Angular module getter using John Papa's Angular style guide + description: "Angular module getter using John Papa's Angular style guide" scope: javascript text: | - angular - .module('${1:module}') + angular + .module('${1:module}') - trigger: ngconfig - description: Angular config phase function using John Papa's Angular style guide + description: "Angular config phase function using John Papa's Angular style guide" scope: javascript text: | - .config(${1:configuration}) - - ${1:configuration}.$inject = ['${2:dependencies}']; - - /* @ngInject */ - function ${1:configuration} (${2:dependencies}) { - - } + .config(${1:configuration}) + + ${1:configuration}.$inject = ['${2:dependencies}']; + + /* @ngInject */ + function ${1:configuration} (${2:dependencies}) { + + } - trigger: ngrun - description: Angular run phase function using John Papa's Angular style guide + description: "Angular run phase function using John Papa's Angular style guide" scope: javascript text: | - .run(${1:runFn}) + .run(${1:runFn}) + + ${1:runFn}.$inject = ['${2:dependencies}']; + + /* @ngInject */ + function ${1:runFn} (${2:dependencies}) { + + } - ${1:runFn}.$inject = ['${2:dependencies}']; +- trigger: ngroute + description: "Angular routeProvider using John Papa's Angular style guide" + scope: javascript + mTime: 1426416190583 + text: | + (function() { + 'use strict'; + + angular + .module( '${1:app}' ) + .config( function( $routeProvider ) { + $routeProvider + .when( '/', { + templateUrl: '${2:home}.html', + controller: '${3:Home}', + controllerAs: 'vm' + }) + + }); + })(); - /* @ngInject */ - function ${1:runFn} (${2:dependencies}) { +- trigger: ngwhen + description: "Defines a route for routeProvider using John Papa's style guide" + scope: javascript + mTime: 1426416499728 + text: | + .when( '/${1:home}', { + templateUrl: '${1:home}.html', + controller: '${2:Home}', + controllerAs: '${3:vm}' + }) - } From 958133cae76b73e3ab48194c820436df5240ced6 Mon Sep 17 00:00:00 2001 From: noritamago Date: Sun, 15 Mar 2015 20:22:28 +0900 Subject: [PATCH 254/567] follow latest master branch change in ja-JP fix duplicated line and line break --- i18n/ja-JP.md | 325 +++++++++++++++++++++++++++++++++++--------------- 1 file changed, 232 insertions(+), 93 deletions(-) diff --git a/i18n/ja-JP.md b/i18n/ja-JP.md index 48856048..3ad709cf 100644 --- a/i18n/ja-JP.md +++ b/i18n/ja-JP.md @@ -1,19 +1,19 @@ -# AngularJS スタイルガイド +# Angular スタイルガイド -*[@john_papa](//twitter.com/john_papa)によるチームのための頑固なAngularJSスタイルガイド* +*[@john_papa](//twitter.com/john_papa)によるチームのための頑固なAngularスタイルガイド* *Translation by [@noritamago](https://github.com/noritamago)* >The [original English version](http://jpapa.me/ngstyles) is the source of truth, as it is maintained and updated first. -もしあなたがAngularJSのシンタックス、規約、そしてアプリケーション構成のための頑固なスタイルガイドを探しているなら、どうぞいらっしゃい!本スタイルは、[AngularJS](//angularjs.org)を用いた私の開発経験やプレゼンテーション、[Pluralsight training courses](http://pluralsight.com/training/Authors/Details/john-papa) 、そしてチームでの作業に基づいたものです。 +もしあなたがAngularのシンタックス、規約、そしてアプリケーション構成のための頑固なスタイルガイドを探しているなら、どうぞいらっしゃい!本スタイルは、[Angular](//angularjs.org)を用いた私の開発経験やプレゼンテーション、[Pluralsight training courses](http://pluralsight.com/training/Authors/Details/john-papa) 、そしてチームでの作業に基づいたものです。 -このスタイルガイドの目的は、私が実践している規約だけでなく、私がそれを行う理由を示すことによって、AngularJSアプリケーションを構築する手引きとなることです。 +このスタイルガイドの目的は、私が実践している規約だけでなく、私がそれを行う理由を示すことによって、Angularアプリケーションを構築する手引きとなることです。 ->もしあなたがこのガイドを気に入ったのなら、Pluralsightにある [AngularJS Patterns: Clean Code](http://jpapa.me/ngclean) の私のコースもチェックして下さい。 +>もしあなたがこのガイドを気に入ったのなら、Pluralsightにある [Angular Patterns: Clean Code](http://jpapa.me/ngclean) の私のコースもチェックして下さい。 ## Community Awesomeness and Credit -あなたは決して1人でありません!AngularJSのコミュニティは、自身の経験を共有することに情熱的な素晴らしい集団です。実際、友人でありAngularJSのエキスパートでもある Todd Motto と私は、共同で多くのスタイルや規約をまとめました。一部意見が分かれましたが、概ね合意できるものでした。彼のアプローチと本スタイルとの比較のため、是非 [Todd's guidelines](https://github.com/toddmotto/angularjs-styleguide) をチェックすることをお勧めします。 +あなたは決して1人でありません!Angularのコミュニティは、自身の経験を共有することに情熱的な素晴らしい集団です。実際、友人でありAngularのエキスパートでもある Todd Motto と私は、共同で多くのスタイルや規約をまとめました。一部意見が分かれましたが、概ね合意できるものでした。彼のアプローチと本スタイルとの比較のため、是非 [Todd's guidelines](https://github.com/toddmotto/angularjs-styleguide) をチェックすることをお勧めします。 ここで紹介する多くのスタイルは、数多くのペアプログラミングのセッション [Ward Bell](http://twitter.com/wardbell) および私自身が既に持っていたアイデアによるものです。いつも意見が一致した訳ではないですが、友人のWardはこのガイドの最終的な発展に大きく貢献してくれました。 @@ -21,7 +21,7 @@ このガイドは"何を"、"なぜ"、"どのように"行えば良いかという説明をしますが、合わせて実践的に見ていくことが理解に役立つはずです。本ガイドは、スタイルやパターンに沿ったサンプルアプリケーションを [`modular`のディレクトリ](https://github.com/johnpapa/ng-demos) に用意しています。ここから自由に取得しcloneやforkをしてもらって構いません。また [readmeに実行のためのインストラクション](https://github.com/johnpapa/ng-demos/tree/master/modular) もあります。 ## Translations -[Translations of this Angular style guide](https://github.com/johnpapa/angularjs-styleguide/tree/master/i18n) がコミュニティによってメンテナンスされており、そこで翻訳を参照することができます。 +[Translations of this Angular style guide](https://github.com/johnpapa/angular-styleguide/tree/master/i18n) がコミュニティによってメンテナンスされており、そこで翻訳を参照することができます。 ## Table of Contents @@ -47,12 +47,14 @@ 1. [Animations](#animations) 1. [Comments](#comments) 1. [JSHint](#js-hint) + 1. [JSCS](#jscs) 1. [Constants](#constants) 1. [File Templates and Snippets](#file-templates-and-snippets) 1. [Yeoman Generator](#yeoman-generator) 1. [Routing](#routing) 1. [Task Automation](#task-automation) - 1. [AngularJS Docs](#angularjs-docs) + 1. [Filters](#filters) + 1. [Angular Docs](#angular-docs) 1. [Contributing](#contributing) 1. [License](#license) @@ -115,7 +117,7 @@ ### JavaScript Closures ###### [Style [Y010](#style-y010)] - - AngularJSのコンポーネントを即時関数式(Immediately Invoked Function Expression:IIFE)で包んで下さい。 + - Angularのコンポーネントを即時関数式(Immediately Invoked Function Expression:IIFE)で包んで下さい。 *なぜ ?*: IIFEを用いると変数はグローバルスコープになりません。それにより、変数がグローバルスコープの中で期待以上に長く生存してしまうことを防ぐことがでます。また変数同士の衝突も避けることができます。 @@ -172,7 +174,7 @@ - Note: 簡潔にするため, 以下に続くコードの例ではIIFEのシンタックスを省略させて下さい。 - - Note: テストコードは正規表現や単体テスト向けに有効なヘルバー関数のようになプライベートなメンバにしばしばアクセスしますが、IIFEはそのアクセスへの妨げとなります。しかしながら、アクセス可能なメンバを通してテストをすることや独立したコンポーネント経由でこれらを公開してしまうことでテストが可能になります。例えば、ヘルバー関数、正規表現、もしくは定数をAngularJSのファクトリや定数として用意してしまう方法があります。 + - Note: テストコードは正規表現や単体テスト向けに有効なヘルバー関数のようになプライベートなメンバにしばしばアクセスしますが、IIFEはそのアクセスへの妨げとなります。しかしながら、アクセス可能なメンバを通してテストをすることや独立したコンポーネント経由でこれらを公開してしまうことでテストが可能になります。例えば、ヘルバー関数、正規表現、もしくは定数をAngularのファクトリや定数として用意してしまう方法があります。 **[Back to top](#table-of-contents)** @@ -442,7 +444,7 @@ } ``` - ![Controller Using "Above the Fold"](https://raw.githubusercontent.com/johnpapa/angularjs-styleguide/master/assets/above-the-fold-1.png) + ![Controller Using "Above the Fold"](https://raw.githubusercontent.com/johnpapa/angular-styleguide/master/assets/above-the-fold-1.png) Note: もし関数がワンライナーであれば、可読性に影響が無い限り上に置いたままにすることを検討して下さい。 @@ -553,7 +555,7 @@ } ``` -### Defer Controller Logic +### Defer Controller Logic to Services ###### [Style [Y035](#style-y035)] - サービスやファクトリに委譲することで、コントローラの中のロジックを遅延させて下さい。 @@ -564,6 +566,8 @@ *なぜ ?*: 依存性を取り除きコントローラから実装の詳細を隠すことができます。 + *なぜ ?*: コントローラをスリムに整えて、そしてフォーカスさせて下さい。 + ```javascript /* avoid */ @@ -605,7 +609,7 @@ function checkCredit() { return creditService.isOrderTotalOk(vm.total) - .then(function(isOk) { vm.isCreditOk = isOk; }) + .then(function(isOk) { vm.isCreditOk = isOk; }) .catch(showServiceError); }; } @@ -682,7 +686,7 @@ - サービスは`new`キーワードでインスタンス化されます。パブリックメソッドや変数には`this`を使って下さい。これらはファクトリも同様ですが、一貫性のためにはサービスの代わりにファクトリを用いて下さい。 - Note: [全てのAngularJSのサービスはシングルトンです](https://docs.angularjs.org/guide/services)。 これはつまり、作成されたサービスはインジェクター毎に単一インスタンスしか存在しないことを意味しています。 + Note: [全てのAngularのサービスはシングルトンです](https://docs.angularjs.org/guide/services)。 これはつまり、作成されたサービスはインジェクター毎に単一インスタンスしか存在しないことを意味しています。 ```javascript // service @@ -726,7 +730,7 @@ - ファクトリはシングルトンであり、そのサービスのメンバを含むオブジェクトを返して下さい。 - Note: [全てのAngularJSのサービスはシングルトンです](https://docs.angularjs.org/guide/services)。 + Note: [全てのAngularのサービスはシングルトンです](https://docs.angularjs.org/guide/services)。 ### Accessible Members Up Top ###### [Style [Y052](#style-y052)] @@ -964,7 +968,7 @@ ### Return a Promise from Data Calls ###### [Style [Y061](#style-y061)] - - $httpのようなpromiseを返すデータサービスを呼び出すときは、それを呼び出す関数も同様にpromiseを返して下さい。 + - `$http`のようなpromiseを返すデータサービスを呼び出すときは、それを呼び出す関数も同様にpromiseを返して下さい。 *なぜ ?*: promiseを一緒にチェーンすることで、データの呼び出しが完了した後にさらなるアクションを行い、そのpromiseをresolveもしくはrejectすることができます。 @@ -1018,6 +1022,10 @@ *なぜ ?*: ファイル毎に一つのディレクティブにすることで、メンテナンスが容易になります。 + Note: "**Best Practice**: Directives should clean up after themselves. You can use `element.on('$destroy', ...)` or `scope.$on('$destroy', ...)` to run a clean-up function when the directive is removed" ... from the Angular documentation + Note: "**Best Practice**: ディレクティブは自身でクリーンナップされるべきです。ディレクティブが削除されたときにクリーンナップの関数を実行するために、`element.on('$destroy', ...)` や `scope.$on('$destroy', ...)`" ... Angularのドキュメンテーションより + + ```javascript /* avoid */ /* directives.js */ @@ -1069,7 +1077,7 @@ /* customerInfo.directive.js */ /** - * @desc spinner directive that can be used anywhere across the sales app at a company named Acme + * @desc sales directive that can be used anywhere across the sales app at a company named Acme * @example
*/ angular @@ -1098,7 +1106,7 @@ } ``` - Note: スコープが狭いか広いかに応じて、ディレクティブには多くの命名オプションがあります。ディレクティブだと理解され、そのファイル名の区別がつきやすく内容が明解であるような名前を一つ選んで下さい。いくつかの例が下記に登場しますが、より推奨される名前に関しては命名のセクションを参照して下さい。 + Note: スコープが狭いか広いかに応じて、ディレクティブには多くの命名オプションがあります。ディレクティブだと理解され、そのファイル名の区別がつきやすく内容が明解であるような名前を一つ選んで下さい。いくつかの例が下記に登場しますが、より推奨される名前に関しては[Naming](#naming)のセクションを参照して下さい。 ### Manipulate DOM in a Directive ###### [Style [Y072](#style-y072)] @@ -1114,7 +1122,7 @@ *なぜ ?*: ユニークで簡潔なプリフィックスは、ディレクティブのコンテキストと由来を特定します。例えば、`cc-` というプリフィックスは、CodeCamperアプリを示し、`acme-` は Acme companyのためのディレクティブであることを示します。 - Note: `ng-` のようなAngularJSのdirectivesのためにリザーブされているものは避けて下さい。 名前の衝突を避けるため、[Ionic Framework](http://ionicframework.com/)の`ion-`のように、幅広く利用されているディレクティブを調査して下さい。 + Note: `ng-` のようなAngularのdirectivesのためにリザーブされているものは避けて下さい。 名前の衝突を避けるため、[Ionic Framework](http://ionicframework.com/)の`ion-`のように、幅広く利用されているディレクティブを調査して下さい。 ### Restrict to Elements and Attributes ###### [Style [Y074](#style-y074)] @@ -1125,7 +1133,7 @@ *なぜ ?*: 私たちはディレクティブをクラスとして使うことを許していますが、もしディレクティブが要素として働いているのであれば、要素の方がより理にかなっていますし、また少なくとも属性としても理にかなうはずです。 - Note: AngularJS 1.3 +では、EAがデフォルトです。 + Note: Angular 1.3 +では、EAがデフォルトです。 ```html @@ -1209,8 +1217,8 @@ }, link: linkFunc, controller: ExampleController, - controllerAs: 'vm', - bindToController: true // because the scope is isolated + controllerAs: 'vm', + bindToController: true // because the scope is isolated }; return directive; @@ -1350,7 +1358,7 @@ *なぜ ?*: コントローラが読み込まれる前にデータが必要となるかもしれません。そのデータはカスタムのファクトリや[$http](https://docs.angularjs.org/api/ng/service/$http)から返るpromiseから取得するかもしれません。[route resolve](https://docs.angularjs.org/api/ngRoute/provider/$routeProvider) を使うと、コントローラがロジックを実行する前にpromiseを解決することができるため、 promiseから取得したデータに基づいてアクションを取ることができます。 - *なぜ ?*: ルーティングとコントローラのactivate関数の後にコードが実行されて、ビューが直ちにロードされます。アクティベイトされたpromiseがresolveされるとデータバインディングがキックされます。ビューが遷移している間(ng-viewやui-viewで)"busy"なアニメーションが表示されます。 + *なぜ ?*: ルーティングとコントローラのactivate関数の後にコードが実行されて、ビューが直ちにロードされます。アクティベイトされたpromiseがresolveされるとデータバインディングがキックされます。ビューが遷移している間(`ng-view`や`ui-view`で)"busy"なアニメーションが表示されます。 Note: promiseの後に、ルーティングが行われる前にコードが実行されます。もしそのpromiseがrejectされるとルーティングはキャンセルされます。resolveによって新しいビューはルーティングが解決されるのを待ちます。resolve及びビューの遷移が終わるまで"busy" なアニメーションが表示されます。より早くビューを表示したい場合で、かつビューを表示するかどうかのチェックポイントが不要な場合は、代わりに [controller `activate` technique](#style-y080) を用いることを検討して下さい。 @@ -1454,7 +1462,7 @@ - minificationセーフなアプローチを用いずにショートカットで依存を宣言するシンタックスは避けて下さい。 - *なぜ ?*: コンポーネント(つまり、コントローラやファクトリなど)に対するパラメータはマングル化された変数に変換されます。例えば、`common` や `dataservice`は、`a` もしくは `b` になるかもしれず、AngularJSが見つけられないかもしれません。 + *なぜ ?*: コンポーネント(つまり、コントローラやファクトリなど)に対するパラメータはマングル化された変数に変換されます。例えば、`common` や `dataservice`は、`a` もしくは `b` になるかもしれず、Angularが見つけられないかもしれません。 ```javascript /* avoid - not minification-safe*/ @@ -1476,11 +1484,11 @@ ### Manually Identify Dependencies ###### [Style [Y091](#style-y091)] - - AngularJSコンポーネントの依存を手動で特定するために`$inject`を使って下さい。 + - Angularコンポーネントの依存を手動で特定するために`$inject`を使って下さい。 *なぜ ?*: このテクニックは[`ng-annotate`](https://github.com/olov/ng-annotate)で用いられており、そしてそれは自動でminificationセーフな依存を生成することを勧めています。もし`ng-annotate` が注入がすでに行われたことを検出すると再生成をスキップします。 - *なぜ ?*: このテクニックは、パラメータがマングルされたときにminificationの問題に対して脆弱であることから依存性を守ります。例えば、`common` や `dataservice` が `a` や `b` になるかもしれず、AngularJSが見つけられないかもしれません。 + *なぜ ?*: このテクニックは、パラメータがマングルされたときにminificationの問題に対して脆弱であることから依存性を守ります。例えば、`common` や `dataservice` が `a` や `b` になるかもしれず、Angularが見つけられないかもしれません。 *なぜ ?*: 配列で読むのが難しいほと長いリストになる場合には、インラインで依存性を生成することを避けて下さい。さらに依存のリストは配列が文字列の連続からなる一方で、最後の要素がコンポーネントの関数となり紛らわしいです。 @@ -1517,40 +1525,43 @@ } ``` - Note: 関数がreturn文の下にあるとき、$injectが到達可能になるかもしれません(これはディレクティブで起こるかもしれません)。$injectをreturn文の上に移動するか、もしくは交互の配列によって注入するシンタックスを使うことで回避することができます。 - - Note: [`ng-annotate 0.10.0`](https://github.com/olov/ng-annotate) は'$inject'を到達可能なところに移動する機能を導入しました。 + Note: 関数がreturn文の下にあるとき、`$inject`が到達可能になるかもしれません(これはディレクティブで起こるかもしれません)。これはコントローラをディレクティブの外側へ移動することによって解決できます。 ```javascript // inside a directive definition function outer() { - return { - controller: DashboardPanel, + var ddo = { + controller: DashboardPanelController, + controllerAs: 'vm' }; + return ddo; - DashboardPanel.$inject = ['logger']; // Unreachable - function DashboardPanel(logger) { + DashboardPanelController.$inject = ['logger']; // Unreachable + function DashboardPanelController(logger) { } } ``` ```javascript - // inside a directive definition + /* recommended */ + // outside a directive definition function outer() { - DashboardPanel.$inject = ['logger']; // reachable - return { - controller: DashboardPanel, + var ddo = { + controller: DashboardPanelController, + controllerAs: 'vm' }; + return ddo; + } - function DashboardPanel(logger) { - } + DashboardPanelController.$inject = ['logger']; + function DashboardPanelController(logger) { } ``` ### Manually Identify Route Resolver Dependencies ###### [Style [Y092](#style-y092)] - - AngularJSのコンポーネントのroute resolverの依存性を手動で特定するために$injectを使って下さい。 + - Angularのコンポーネントのroute resolverの依存性を手動で特定するために`$inject`を使って下さい。 *なぜ ?*: このテクニックは、route resolverを無名関数として外に出すことで可読性を上げることができます。 @@ -1562,7 +1573,7 @@ $routeProvider .when('/avengers', { templateUrl: 'avengers.html', - controller: 'Avengers', + controller: 'AvengersController', controllerAs: 'vm', resolve: { moviesPrepService: moviePrepService @@ -1654,7 +1665,8 @@ } ``` - > Note: AngularJS 1.3から導入された、[`ngApp`](https://docs.angularjs.org/api/ng/directive/ngApp)のディレクティブの`ngStrictDi`パラメータを使って下さい。 現在のinjectorが"strict-di"モードで生成されたとき、アプリケーションが明示的にアノテーションの付いていない関数(これらはminificationセーフではありません)の呼び出しは失敗します。デバッグ情報がログとしてconsoleに出力されるので、問題のあるコードを見つけ出すのに役立ちます。 + > Note: 潜在的にminificationセーフでない依存性を検出するためにAngular 1.3から導入された、[`ngApp`](https://docs.angularjs.org/api/ng/directive/ngApp)のディレクティブの`ngStrictDi`パラメータを用いることができます。現在のinjectorが"strict-di"モードで生成されたとき、アプリケーションが明示的にアノテーションの付いていない関数(これらはminificationセーフではありません)の呼び出しは失敗します。デバッグ情報がログとしてconsoleに出力されるので、問題のあるコードを見つけ出すのに役立ちます。私は、`ng-strict-di`をデバッグ用途でのみ利用することを好みます。 + `` ### Use Gulp or Grunt for ng-annotate @@ -1669,6 +1681,7 @@ ```javascript gulp.task('js', ['jshint'], function() { var source = pkg.paths.js; + return gulp.src(source) .pipe(sourcemaps.init()) .pipe(concat('all.min.js', {newLine: ';'})) @@ -1696,7 +1709,7 @@ - 例外が発生したときに[`$exceptionHandler`](https://docs.angularjs.org/api/ng/service/$exceptionHandler)サービスを上書きし、カスタムのアクションを実行するために、configの呼び出し時に[`$provide`](https://docs.angularjs.org/api/auto/service/$provide) サービスの[decorator](https://docs.angularjs.org/api/auto/service/$provide#decorator)を使って下さい。 - *なぜ ?*: 開発時や実行時に捕捉されていないAngularJSの例外をハンドルする一貫した方法を与えます。 + *なぜ ?*: 開発時や実行時に捕捉されていないAngularの例外をハンドルする一貫した方法を与えます。 Note: もう一つのオプションは、decoratorを使う代わりにサービスをオーバーライドすることです。これも有効なオプションですが、もしデフォルトの動作をキープしたい場合または拡張したい場合はdecoratorがお勧めです。 @@ -1789,7 +1802,6 @@ var destination = (current && (current.title || current.name || current.loadedTemplateUrl)) || 'unknown target'; - var msg = 'Error routing to ' + destination + '. ' + (rejection.msg || ''); var msg = 'Error routing to ' + destination + '. ' + (rejection.msg || ''); @@ -1880,7 +1892,7 @@ avenger-profile.directive.spec.js ``` - Note: 別の命名規則は `avengers.controller.js` というファイル名から`controller`を取り除いて命名することです。 その他の全ての規則はサフィックスを使い続けるものです。コントローラは最も共通なコンポーネントであり、タイピングの量を減らしながらも依然として特定しやすいままになります。どれか一つを選びチーム内で一つの命名規則に統一することを勧めます。 + Note: 別の命名規則は `avengers.controller.js` というファイル名から`controller`を取り除いて命名することです。 その他の全ての規則はサフィックスを使い続けるものです。コントローラは最も共通なコンポーネントであり、タイピングの量を減らしながらも依然として特定しやすいままになります。どれか一つを選びチーム内で一つの命名規則に統一することを勧めます。私の好みは`avengers.controller.js`です。 ```javascript /** @@ -1927,36 +1939,21 @@ // avengers.controller.js angular .module - .controller('HeroAvengers', HeroAvengers); + .controller('HeroAvengersController', HeroAvengersController); - function HeroAvengers() { } + function HeroAvengersController() { } ``` ### Controller Name Suffix ###### [Style [Y124](#style-y124)] - - コントローラに`Controller`という名前を挿入するか、もしくはしないかどちらか一つを選択せよ。 両方を混ぜてはいけません。 + - コントローラに`Controller`という名前を挿入して下さい。 *なぜ ?*: `Controller`のサフィックスは、広く使われており明らかに直接内容を説明している。 - *なぜ ?*: サフィックスを省略することは効率的であり、コントローラはサフィックスが無くても簡単に特定が可能です。 - - ```javascript - /** - * recommended: Option 1 - */ - - // avengers.controller.js - angular - .module - .controller('Avengers', Avengers); - - function Avengers() { } - ``` - ```javascript /** - * recommended: Option 2 + * recommended */ // avengers.controller.js @@ -2134,7 +2131,6 @@ app/ app.module.js app.config.js - app.routes.js components/ calendar.directive.js calendar.directive.html @@ -2148,6 +2144,7 @@ people/ attendees.html attendees.controller.js + people.routes.js speakers.html speakers.controller.js speaker-detail.html @@ -2160,11 +2157,12 @@ sessions/ sessions.html sessions.controller.js + sessions.routes.js session-detail.html session-detail.controller.js ``` - ![Sample App Structure](https://raw.githubusercontent.com/johnpapa/angularjs-styleguide/master/assets/modularity-2.png) + ![Sample App Structure](https://raw.githubusercontent.com/johnpapa/angular-styleguide/master/assets/modularity-2.png) Note: folders-by-typeを使って構造化をしてはいけません。一つの機能が、5、10、25以上のビューやコントローラ(また他の機能)からなるときにアプリが肥大化してきます。そのとき複数のフォルダに移動する必要がありますが、ファイルを配置するのはfolder-by-featureよりも難しいでしょう。 @@ -2193,7 +2191,7 @@ user-profile.directive.js user-profile.directive.html services/ - dataservice.j + dataservice.js localstorage.js logger.js spinner.js @@ -2223,7 +2221,7 @@ - 全てのモジュールと機能を統合することを担うアプリケーションのルートなるモジュールを作って下さい。これにアプリケーション名をつけて下さい。 - *なぜ ?*: AngularJSはモジュール化と分割のパターンを推奨しています。他のモジュールを結びつけるアプリケーションのルートモジュールを作ることは、 モジュールの追加や削除を行う簡単な方法を与えます。 + *なぜ ?*: Angularはモジュール化と分割のパターンを推奨しています。他のモジュールを結びつけるアプリケーションのルートモジュールを作ることは、 モジュールの追加や削除を行う簡単な方法を与えます。 ### Keep the App Module Thin ###### [Style [Y162](#style-y162)] @@ -2257,7 +2255,7 @@ - ルートのモジュールは、アプリケーションスペシフィックなモジュールや共有または再利用されるモジュールに依存します。 - ![Modularity and Dependencies](https://raw.githubusercontent.com/johnpapa/angularjs-styleguide/master/assets/modularity-1.png) + ![Modularity and Dependencies](https://raw.githubusercontent.com/johnpapa/angular-styleguide/master/assets/modularity-1.png) *なぜ ?*: メインのアプリケーションのモジュールは、アプリケーションの機能を素早く特定可能なマニュフェストを含みます。 @@ -2265,7 +2263,7 @@ *なぜ ?*: データを共有するサービスのようなアプリ内の機能は、`app.core`(このモジュールは好きな名前を選んで下さい)のようにまとめることで、簡単に位置を特定または共有することが可能です。 - Note: これは一貫性のためのストラテジーです。ここには多くの良いオプションがあります。AngularJSの依存のルールに沿って一貫性をとるためにその一つを選ぶことで メンテナンスしスケールさせることが容易になります。 + Note: これは一貫性のためのストラテジーです。ここには多くの良いオプションがあります。Angularの依存のルールに沿って一貫性をとるためにその一つを選ぶことで メンテナンスしスケールさせることが容易になります。 >  私のストラクチャはプロジェクト間で少しだけ変わっていますが、ストラクチャやモジュール化に関してはこのガイドラインに沿っています。実装は、機能やチームに依存して変わるかもしれません。言い換えれば、同等のストラクチャにこだわってるのではなく、一貫性やメンテナンス性、効率性を念頭に置いて正しいことを行うということです。 @@ -2343,7 +2341,7 @@ - `setTimeout` と `setInterval`の代わりに[`$timeout`](https://docs.angularjs.org/api/ng/service/$timeout)と[`$interval`](https://docs.angularjs.org/api/ng/service/$interval)を使って下さい。 - *なぜ ?*: これらのサービスはAngularによってラップされているのでよりテスタブルになります。またAngularJSのdigestのサイクルでハンドルされるので、データバインディングが同期され続けます。 + *なぜ ?*: これらのサービスはAngularによってラップされているのでよりテスタブルになります。またAngularのdigestのサイクルでハンドルされるので、データバインディングが同期され続けます。 **[Back to top](#table-of-contents)** @@ -2382,9 +2380,9 @@ - 単体テストには [Jasmine](http://jasmine.github.io/) もしくは [Mocha](http://mochajs.org) を使って下さい。 - *なぜ ?*: Jasmine と Mocha はAngularJSのコミュニティで幅広く使われています。双方とも安定しており、十分メンテされており、ロバストなテスト機能が与えられます。 + *なぜ ?*: Jasmine と Mocha はAngularのコミュニティで幅広く使われています。双方とも安定しており、十分メンテされており、ロバストなテスト機能が与えられます。 - Note: Mochaを用いるときは、合わせて[Chai](http://chaijs.com)といったアサートのライブラリを選ぶことを検討して下さい。 + Note: Mochaを用いるときは、合わせて[Chai](http://chaijs.com)といったアサートのライブラリを選ぶことを検討して下さい。私はMochaを好みます。 ### Test Runner ###### [Style [Y192](#style-y192)] @@ -2406,7 +2404,9 @@ *なぜ ?*: SinonはJasminとMochaと一緒に正しく動作し、スタブやスパイの機能を拡張します。 - *Why?*: もしJasmineとMochaの両方を試したければ、Sinonはそれらを簡単に切り替えることができます。 + *なぜ ?*: もしJasmineとMochaの両方を試したければ、Sinonはそれらを簡単に切り替えることができます。 + + *なぜ ?*: テストがアサーションに失敗したときにSinonは叙述的なメッセージとなります。 ### Headless Browser ###### [Style [Y194](#style-y194)] @@ -2429,13 +2429,19 @@ -  テストコードでは、`describe`や`expect`といった共通のグローバルな変数を許すようにルールを緩めて下さい。 - *なぜ ?*: テストもコードであり、プロダクションのコードと同様に注意が払われ、コードの品質のルールが必要となります。しかしながら、テストのフレームワークで用いられるグローバル変数は、例えば、テストのスペックに以下を含むことによって緩められます。 + *なぜ ?*: テストもコードであり、プロダクションのコードと同様に注意が払われ、コードの品質のルールが必要となります。しかしながら、テストのフレームワークで用いられるグローバル変数は、例えば、テストのスペックに以下を含むことによって緩められます。 Mochaが行っているように式にもルールを緩めて下さい。 + + ```javascript + /* jshint -W117, -W030 */ + ``` + Or you can add the following to your JSHint Options file. ```javascript - /* global sinon, describe, it, afterEach, beforeEach, expect, inject */ + "jasmine": true, + "mocha": true, ``` - ![Testing Tools](https://raw.githubusercontent.com/johnpapa/angularjs-styleguide/master/assets/testing-tools.png) + ![Testing Tools](https://raw.githubusercontent.com/johnpapa/angular-styleguide/master/assets/testing-tools.png) ### Organizing Tests ###### [Style [Y197](#style-y197)] @@ -2471,7 +2477,7 @@ ### Usage ###### [Style [Y210](#style-y210)] - - ビューや主要なビュジアルの要素で、ステート間を遷移するために、さりげない[animations with AngularJS](https://docs.angularjs.org/guide/animations)を使って下さい。[ngAnimate module](https://docs.angularjs.org/api/ngAnimate)を含めて下さい。三つの鍵はさりげなさ、スムーズさ、そしてシームレスです。 + - ビューや主要なビュジアルの要素で、ステート間を遷移するために、さりげない[animations with Angular](https://docs.angularjs.org/guide/animations)を使って下さい。[ngAnimate module](https://docs.angularjs.org/api/ngAnimate)を含めて下さい。三つの鍵はさりげなさ、スムーズさ、そしてシームレスです。 *なぜ ?*: さりげないアニメーションは、適切に使われることでユーザエクスペリエンスを改善します。 @@ -2495,7 +2501,7 @@ *なぜ ?*: animate.cssは広く利用されておりテストされています。 - Note: この[Matias NiemeläによるAngularJSのアニメーションの素晴らしいポスト](http://www.yearofmoo.com/2013/08/remastered-animation-in-angularjs-1-2.html)を見て下さい。 + Note: この[Matias NiemeläによるAngularのアニメーションの素晴らしいポスト](http://www.yearofmoo.com/2013/08/remastered-animation-in-angularjs-1-2.html)を見て下さい。 **[Back to top](#table-of-contents)** @@ -2628,12 +2634,100 @@ **[Back to top](#table-of-contents)** +## JSCS + +### Use an Options File +###### [Style [Y235](#style-y235)] + + - コーディングスタイルをチェックするためにJSCSを使って下さい。 JSCSのオプションファイルを必ずカスタマイズし、ソースファイル管理に含めるようにして下さい。詳細なオプションは、[JSCS docs](http://www.jscs.info)を参照して下さい。 + + *なぜ ?*: ソースコード管理にファイルを込みとする前に最初のアラートが上がるようになります + + *なぜ ?*: あなたのチームに一貫性が生まれます。 + + ```javascript + { + "excludeFiles": ["node_modules/**", "bower_components/**"], + + "requireCurlyBraces": [ + "if", + "else", + "for", + "while", + "do", + "try", + "catch" + ], + "requireOperatorBeforeLineBreak": true, + "requireCamelCaseOrUpperCaseIdentifiers": true, + "maximumLineLength": { + "value": 100, + "allowComments": true, + "allowRegex": true + }, + "validateIndentation": 4, + "validateQuoteMarks": "'", + + "disallowMultipleLineStrings": true, + "disallowMixedSpacesAndTabs": true, + "disallowTrailingWhitespace": true, + "disallowSpaceAfterPrefixUnaryOperators": true, + "disallowMultipleVarDecl": null, + + "requireSpaceAfterKeywords": [ + "if", + "else", + "for", + "while", + "do", + "switch", + "return", + "try", + "catch" + ], + "requireSpaceBeforeBinaryOperators": [ + "=", "+=", "-=", "*=", "/=", "%=", "<<=", ">>=", ">>>=", + "&=", "|=", "^=", "+=", + + "+", "-", "*", "/", "%", "<<", ">>", ">>>", "&", + "|", "^", "&&", "||", "===", "==", ">=", + "<=", "<", ">", "!=", "!==" + ], + "requireSpaceAfterBinaryOperators": true, + "requireSpacesInConditionalExpression": true, + "requireSpaceBeforeBlockStatements": true, + "requireLineFeedAtFileEnd": true, + "disallowSpacesInsideObjectBrackets": "all", + "disallowSpacesInsideArrayBrackets": "all", + "disallowSpacesInsideParentheses": true, + + "validateJSDoc": { + "checkParamNames": true, + "requireParamTypes": true + }, + + "disallowMultipleLineBreaks": true, + + "disallowCommaBeforeLineBreak": null, + "disallowDanglingUnderscores": null, + "disallowEmptyBlocks": null, + "disallowMultipleLineStrings": null, + "disallowTrailingComma": null, + "requireCommaBeforeLineBreak": null, + "requireDotNotation": null, + "requireMultipleVarDecl": null, + "requireParenthesesAroundIIFE": true + } + ``` + +**[Back to top](#table-of-contents)** + ## Constants ### Vendor Globals ###### [Style [Y240](#style-y240)] - - vendorのライブラリのグローバル変数のためにAngularJSの定数を作って下さい。 + - vendorのライブラリのグローバル変数のためにAngularの定数を作って下さい。 *なぜ ?*: グローバルになってしまうvendorのライブラリを注入するための方法を与えます。 これによりコンポーネントが持っている依存性をより簡単に把握することで(抽象性の破綻を避け)、コードのテスタビリティが改善されます。さらに理にかなうように、これらのコンポーネントをモックでテストできるようになります。 @@ -2685,24 +2779,26 @@ ### Sublime Text ###### [Style [Y250](#style-y250)] - - 本スタイルやガイドラインに沿ったAngularJSのスニペット + - 本スタイルやガイドラインに沿ったAngularのスニペット - - [Sublime Angular snippets](assets/sublime-angular-snippets.zip?raw=true)をダウンロード + - [Sublime Angular snippets](assets/sublime-angular-snippets?raw=true)をダウンロード - Packagesフォルダに置く - Sublimeを再起動 - JavaScriptのファイルのタイプで`TAB`に続いて下記のコマンドを打ちます。 ```javascript ngcontroller // creates an Angular controller - ngdirective // creates an Angular directive - ngfactory // creates an Angular factory - ngmodule // creates an Angular module + ngdirective // creates an Angular directive + ngfactory // creates an Angular factory + ngmodule // creates an Angular module + ngservice // creates an Angular service + ngfilter // creates an Angular filter ``` ### Visual Studio ###### [Style [Y251](#style-y251)] - - 本スタイルやガイドラインに沿ったAngularJSのファイルのテンプレートが[SideWaffle](http://www.sidewaffle.com)で公開されています。 + - 本スタイルやガイドラインに沿ったAngularのファイルのテンプレートが[SideWaffle](http://www.sidewaffle.com)で公開されています。 - [SideWaffle](http://www.sidewaffle.com) で Visual Studio extension (vsixファイル) をダウンロード - vsixファイルを実行 @@ -2711,9 +2807,9 @@ ### WebStorm ###### [Style [Y252](#style-y252)] - - 本スタイルやガイドラインに沿ったAngularJSスニペットとファイルテンプレート。WebStormのsettingsへインポートできます。 + - 本スタイルやガイドラインに沿ったAngularスニペットとファイルテンプレート。WebStormのsettingsへインポートできます。 - - [WebStorm AngularJS file templates and snippets](assets/webstorm-angular-file-template.settings.jar?raw=true)をダウンロード + - [WebStorm Angular file templates and snippets](assets/webstorm-angular-file-template.settings.jar?raw=true)をダウンロード - WebStormを開き、 `File`メニューを開く - メニューオプションから`Import Settings`を選ぶ - ファイルを選択し、`OK`をクリック @@ -2728,7 +2824,7 @@ ### Atom ###### [Style [Y253](#style-y253)] - - 本スタイルとガイドラインに沿ったAngularJSスニペット that follow these styles and guidelines. + - 本スタイルとガイドラインに沿ったAngularスニペット ``` apm install angularjs-styleguide-snippets ``` @@ -2746,6 +2842,36 @@ ngmodule // creates an Angular module ``` +### Brackets +###### [Style [Y254](#style-y254)] + + - 本スタイルとガイドラインに沿ったAngularのスニペット + + - Brackets Extension マネージャー ( File > Extension manager ) + - ['Brackets Snippets (by edc)'](https://github.com/chuyik/brackets-snippets)をインストール + - bracketsの右側にある電球をクリック + - `Settings`をクリックして`Import` + - ファイルを選択してChoose the file and select to skip or override + - `Start Import`をクリック + + - JavaScriptのファイルタイプで`TAB`に続いて下記のコマンドを打ちます。 + + ```javascript + // These are full file snippets containing an IIFE + ngcontroller // creates an Angular controller + ngdirective // creates an Angular directive + ngfactory // creates an Angular factory + ngapp // creates an Angular module setter + ngservice // creates an Angular service + ngfilter // creates an Angular filter + + // These are partial snippets intended to chained + ngmodule // creates an Angular module getter + ngstate // creates an Angular UI Router state defintion + ngconfig // defines a configuration phase function + ngrun // defines a run phase function + ``` + **[Back to top](#table-of-contents)** ## Yeoman Generator @@ -2801,6 +2927,8 @@ 自動タスクの生成に[Gulp](http://gulpjs.com)または[Grunt](http://gruntjs.com)を使って下さい。Gulpはコンフィグレーションをコーディングでリーンに行えます。一方で、Gruntはコードをコンフィグレーションでリーンに行うことができます。個人的には読みやすくまた書きやすいGulpを好みますが両者とも素晴らしいです。 +> 私の[Gulp Pluralsight course](http://jpapa.me/gulpps)でGulpについてやタスクの自動化についてより学ぶことができます。 + ###### [Style [Y400](#style-y400)] - その他全てのアプリケーションのJavaScriptファイルに先立って、モジュール定義ファイルの`*.module.js`をリスト化する自動化タスクを使って下さい。 @@ -2821,7 +2949,17 @@ **[Back to top](#table-of-contents)** -## AngularJS docs +## Filters + +###### [Style [Y420](#style-y420)] + + - 複雑なオブジェクトグラフの全てプロパティをスキャンするようなフィルタの使用を避けて下さい。選ばれたプロパティに対してフィルタを用いて下さい。 + + *なぜ ?*: フィルタは簡単に誤用されます。適切に用いられない場合、例えばフィルタが大きくて深いオブジェクトのグラフを読みだす時などパフォーマンス上にネガティブな効果があります。 + +**[Back to top](#table-of-contents)** + +## Angular docs その他の情報、APIリファレンス、については、[Angular documentation](//docs.angularjs.org/api)をチェックして下さい。 ## Contributing @@ -2839,10 +2977,11 @@ Open an issue first to discuss potential changes/additions. If you have question _tldr; Use this guide. Attributions are appreciated._ -### (The MIT License) - -Copyright (c) 2014 [John Papa](http://johnpapa.net) +### Copyright +Copyright (c) 2014-2015 [John Papa](http://johnpapa.net) + +### (The MIT License) 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 From 8005da19b0dca86f4eb3b3dba35c4be8478ec657 Mon Sep 17 00:00:00 2001 From: John Papa Date: Sun, 15 Mar 2015 09:06:27 -0400 Subject: [PATCH 255/567] removed whitespace and made descriptions in sync for brackets snippets --- README.md | 3 +- assets/brackets-angular-snippets.yaml | 52 ++++++++------------------- 2 files changed, 16 insertions(+), 39 deletions(-) diff --git a/README.md b/README.md index daa8f535..176d485d 100644 --- a/README.md +++ b/README.md @@ -2862,14 +2862,13 @@ Use file templates or snippets to help follow consistent styles and patterns. He ngapp // creates an Angular module setter ngservice // creates an Angular service ngfilter // creates an Angular filter - ngroute // creates an Angular routeProvider // These are partial snippets intended to chained ngmodule // creates an Angular module getter ngstate // creates an Angular UI Router state defintion ngconfig // defines a configuration phase function ngrun // defines a run phase function - ngwhen // defines a route for the routeProvider + ngroute // defines an Angular ngRoute 'when' definition ``` **[Back to top](#table-of-contents)** diff --git a/assets/brackets-angular-snippets.yaml b/assets/brackets-angular-snippets.yaml index 7839a74d..3d1b2d5f 100644 --- a/assets/brackets-angular-snippets.yaml +++ b/assets/brackets-angular-snippets.yaml @@ -4,13 +4,14 @@ text: | (function () { 'use strict'; + angular .module('${1:module}') .filter('${2:filter}', ${2:filter}); - function ${2:filter}() { return ${2:filter}Filter; + //////////////// function ${2:filter}Filter(${3:parameters}) { @@ -25,6 +26,7 @@ text: | (function () { 'use strict'; + angular .module('${1:module}') .service('${2:Service}', ${2:Service}); @@ -54,7 +56,6 @@ .module('${1:module}', [ '${2:dependencies}' ]); - })(); - trigger: ngfactory @@ -78,6 +79,7 @@ return exports; //////////////// + function ${4:func}() { } @@ -91,7 +93,6 @@ (function () { 'use strict'; - angular .module('${1:module}') .directive('${2:directive}', ${2:directive}); @@ -123,7 +124,6 @@ function ${4:Controller}(${6:dependencies}) { } - })(); - trigger: ngcontroller @@ -149,10 +149,21 @@ //////////////// function activate() { + } } })(); +- trigger: ngwhen + description: "Angular ngRouter 'when' route using John Papa's Angular style guide" + scope: javascript + text: | + .when('/${1:url}', { + templateUrl: '${2:template}.html', + controller: '${3:Controller}', + controllerAs: '${4:vm}' + }) + - trigger: ngstate description: "Angular UI-Router state using John Papa's Angular style guide" scope: javascript @@ -196,36 +207,3 @@ function ${1:runFn} (${2:dependencies}) { } - -- trigger: ngroute - description: "Angular routeProvider using John Papa's Angular style guide" - scope: javascript - mTime: 1426416190583 - text: | - (function() { - 'use strict'; - - angular - .module( '${1:app}' ) - .config( function( $routeProvider ) { - $routeProvider - .when( '/', { - templateUrl: '${2:home}.html', - controller: '${3:Home}', - controllerAs: 'vm' - }) - - }); - })(); - -- trigger: ngwhen - description: "Defines a route for routeProvider using John Papa's style guide" - scope: javascript - mTime: 1426416499728 - text: | - .when( '/${1:home}', { - templateUrl: '${1:home}.html', - controller: '${2:Home}', - controllerAs: '${3:vm}' - }) - From 7be2f171a407c5ec05178de51e4540c0d8f90d5a Mon Sep 17 00:00:00 2001 From: Ben Surman Date: Sun, 15 Mar 2015 20:32:14 +0000 Subject: [PATCH 256/567] added to controllerAs directive example Added example of naming the controller in the link function to match the controllerAs name --- README.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/README.md b/README.md index 176d485d..9f6b496b 100644 --- a/README.md +++ b/README.md @@ -1251,6 +1251,18 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see
min={{vm.min}}
``` + Note: You can also name the controller when you inject it into the link function and access directive attributes as properties of the controller. + + ```javascript + // Alternative to above example + function linkFunc(scope, el, attr, vm) { + console.log('LINK: scope.min = %s *** should be undefined', scope.min); + console.log('LINK: scope.max = %s *** should be undefined', scope.max); + console.log('LINK: vm.min = %s', vm.min); + console.log('LINK: vm.max = %s', vm.max); + } + ``` + ###### [Style [Y076](#style-y076)] - Use `bindToController = true` when using `controller as` syntax with a directive when you want to bind the outer scope to the directive's controller's scope. From 9d741b3a9970fa8a81053ee0d890a58689da437b Mon Sep 17 00:00:00 2001 From: John Papa Date: Sun, 15 Mar 2015 20:53:00 -0400 Subject: [PATCH 257/567] added link to brackets snippets. doh --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 176d485d..c31e87d0 100644 --- a/README.md +++ b/README.md @@ -2844,7 +2844,7 @@ Use file templates or snippets to help follow consistent styles and patterns. He ###### [Style [Y254](#style-y254)] - Angular snippets that follow these styles and guidelines. - + - Download the [Brackets Angular snippets](assets/brackets-angular-snippets.yaml?raw=true) - Brackets Extension manager ( File > Extension manager ) - Install ['Brackets Snippets (by edc)'](https://github.com/chuyik/brackets-snippets) - Click the light bulb in brackets' right gutter From ec8fb0b17269421ca57fbee7160b9c7a26fc701d Mon Sep 17 00:00:00 2001 From: John Papa Date: Mon, 16 Mar 2015 09:02:28 -0400 Subject: [PATCH 258/567] added end of snippet placeholders for cursors --- assets/brackets-angular-snippets.yaml | 80 ++++++++++++++------------- 1 file changed, 41 insertions(+), 39 deletions(-) diff --git a/assets/brackets-angular-snippets.yaml b/assets/brackets-angular-snippets.yaml index 3d1b2d5f..2eb074e6 100644 --- a/assets/brackets-angular-snippets.yaml +++ b/assets/brackets-angular-snippets.yaml @@ -8,12 +8,13 @@ angular .module('${1:module}') .filter('${2:filter}', ${2:filter}); - + function ${2:filter}() { + ${4:} return ${2:filter}Filter; //////////////// - + function ${2:filter}Filter(${3:parameters}) { return ${3:parameters}; }; @@ -30,17 +31,17 @@ angular .module('${1:module}') .service('${2:Service}', ${2:Service}); - - ${2:Service}.$inject = ['${3:dependencies}']; - + + ${2:Service}.$inject = ['${3:dependencies}']; + /* @ngInject */ function ${2:Service}(${3:dependencies}) { this.${4:func} = ${4:func}; - + //////////////// - + function ${4:func}() { - + ${5:} } } })(); @@ -51,7 +52,7 @@ text: | (function () { 'use strict'; - + angular .module('${1:module}', [ '${2:dependencies}' @@ -67,21 +68,21 @@ angular .module('${1:module}') .factory('${2:factory}', ${2:factory}); - + ${2:factory}.$inject = ['${3:dependencies}']; - + /* @ngInject */ function ${2: Factory}(${3:dependencies}){ var exports = { ${4:func}: ${4:func} }; - + ${5:} + return exports; - + //////////////// function ${4:func}() { - } } })(); @@ -92,13 +93,13 @@ text: | (function () { 'use strict'; - + angular .module('${1:module}') .directive('${2:directive}', ${2:directive}); - + ${2:directive}.$inject = ['${3:dependencies}']; - + /* @ngInject */ function ${2: directive}(${3:dependencies}) { // Usage: @@ -114,15 +115,16 @@ scope: {} }; return directive; - - function link(scope, element, attrs, controller) {} + + function link(scope, element, attrs, controller) { + ${7:} + } } - - ${4:Controller}.$inject = ['${6:dependencies}']; - + + ${4:Controller}.$inject = ['${6:dependencies}']; + /* @ngInject */ function ${4:Controller}(${6:dependencies}) { - } })(); @@ -132,24 +134,24 @@ text: | (function() { 'use strict'; - + angular .module('${1:module}') .controller('${2:Controller}', ${2:Controller}); - + ${2:Controller}.$inject = ['${3:dependencies}']; - + /* @ngInject */ function ${2:Controller}(${3:dependencies}){ var vm = this; vm.${4:property} = '${2:Controller}'; - + ${5:} + activate(); - + //////////////// - - function activate() { + function activate() { } } })(); @@ -162,7 +164,7 @@ templateUrl: '${2:template}.html', controller: '${3:Controller}', controllerAs: '${4:vm}' - }) + })${5:} - trigger: ngstate description: "Angular UI-Router state using John Papa's Angular style guide" @@ -173,26 +175,26 @@ templateUrl: '${3:template}.html', controller: '${4:Controller}' controllerAs: '${5:vm}' - }) + })${6:} - trigger: ngmodule description: "Angular module getter using John Papa's Angular style guide" scope: javascript text: | angular - .module('${1:module}') + .module('${1:module}')${2:} - trigger: ngconfig description: "Angular config phase function using John Papa's Angular style guide" scope: javascript text: | .config(${1:configuration}) - + ${1:configuration}.$inject = ['${2:dependencies}']; - + /* @ngInject */ function ${1:configuration} (${2:dependencies}) { - + ${3:} } - trigger: ngrun @@ -200,10 +202,10 @@ scope: javascript text: | .run(${1:runFn}) - + ${1:runFn}.$inject = ['${2:dependencies}']; - + /* @ngInject */ function ${1:runFn} (${2:dependencies}) { - + ${3:} } From 289fae4d79249b28d5c302deef919c575c826c94 Mon Sep 17 00:00:00 2001 From: John Papa Date: Mon, 16 Mar 2015 09:35:34 -0400 Subject: [PATCH 259/567] added const and value --- assets/brackets-angular-snippets.yaml | 34 ++++++++++++++++++--------- 1 file changed, 23 insertions(+), 11 deletions(-) diff --git a/assets/brackets-angular-snippets.yaml b/assets/brackets-angular-snippets.yaml index 2eb074e6..20ee0db7 100644 --- a/assets/brackets-angular-snippets.yaml +++ b/assets/brackets-angular-snippets.yaml @@ -1,5 +1,5 @@ - trigger: ngfilter - description: "Angular filter using John Papa's Angular style guide" + description: "Filter using Angular style guide" scope: javascript text: | (function () { @@ -22,7 +22,7 @@ })(); - trigger: ngservice - description: "Angular service using John Papa's Angular style guide" + description: "Service using Angular style guide" scope: javascript text: | (function () { @@ -47,7 +47,7 @@ })(); - trigger: ngapp - description: "Angular module app definition using John Papa's Angular style guide" + description: "Module definition using Angular style guide" scope: javascript text: | (function () { @@ -60,7 +60,7 @@ })(); - trigger: ngfactory - description: "Angular factory using John Papa's Angular style guide" + description: "Factory using Angular style guide" scope: javascript text: | (function () { @@ -88,7 +88,7 @@ })(); - trigger: ngdirective - description: "Angular directive using John Papa's Angular style guide" + description: "Directive using Angular style guide" scope: javascript text: | (function () { @@ -129,7 +129,7 @@ })(); - trigger: ngcontroller - description: "Angular controller using John Papa's Angular style guide" + description: "Controller using Angular style guide" scope: javascript text: | (function() { @@ -157,7 +157,7 @@ })(); - trigger: ngwhen - description: "Angular ngRouter 'when' route using John Papa's Angular style guide" + description: "ngRoute 'when' using Angular style guide" scope: javascript text: | .when('/${1:url}', { @@ -167,7 +167,7 @@ })${5:} - trigger: ngstate - description: "Angular UI-Router state using John Papa's Angular style guide" + description: "UI-Router state using Angular style guide" scope: javascript text: | state('${1:state}', { @@ -178,14 +178,26 @@ })${6:} - trigger: ngmodule - description: "Angular module getter using John Papa's Angular style guide" + description: "Module getter using Angular style guide" scope: javascript text: | angular .module('${1:module}')${2:} +- trigger: ngconst + description: "Constant using Angular style guide" + scope: javascript + text: | + .constant('${1:name}', ${2:value}); + +- trigger: ngvalue + description: "Value using Angular style guide" + scope: javascript + text: | + .value('${1:name}', ${2:value}); + - trigger: ngconfig - description: "Angular config phase function using John Papa's Angular style guide" + description: "Config function using Angular style guide" scope: javascript text: | .config(${1:configuration}) @@ -198,7 +210,7 @@ } - trigger: ngrun - description: "Angular run phase function using John Papa's Angular style guide" + description: "Run function from Angular style guide" scope: javascript text: | .run(${1:runFn}) From d1403a243a3648d9e8d7a7b66e01c5f1308defbe Mon Sep 17 00:00:00 2001 From: John Papa Date: Mon, 16 Mar 2015 09:42:43 -0400 Subject: [PATCH 260/567] made descriptions smaller --- assets/brackets-angular-snippets.yaml | 29 +++++++++++++-------------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/assets/brackets-angular-snippets.yaml b/assets/brackets-angular-snippets.yaml index 20ee0db7..720419af 100644 --- a/assets/brackets-angular-snippets.yaml +++ b/assets/brackets-angular-snippets.yaml @@ -1,5 +1,5 @@ - trigger: ngfilter - description: "Filter using Angular style guide" + description: "Filter" scope: javascript text: | (function () { @@ -22,7 +22,7 @@ })(); - trigger: ngservice - description: "Service using Angular style guide" + description: "Service" scope: javascript text: | (function () { @@ -47,7 +47,7 @@ })(); - trigger: ngapp - description: "Module definition using Angular style guide" + description: "Module definition" scope: javascript text: | (function () { @@ -60,7 +60,7 @@ })(); - trigger: ngfactory - description: "Factory using Angular style guide" + description: "Factory" scope: javascript text: | (function () { @@ -88,7 +88,7 @@ })(); - trigger: ngdirective - description: "Directive using Angular style guide" + description: "Directive" scope: javascript text: | (function () { @@ -129,7 +129,7 @@ })(); - trigger: ngcontroller - description: "Controller using Angular style guide" + description: "Controller" scope: javascript text: | (function() { @@ -157,7 +157,7 @@ })(); - trigger: ngwhen - description: "ngRoute 'when' using Angular style guide" + description: "ngRoute 'when'" scope: javascript text: | .when('/${1:url}', { @@ -167,10 +167,10 @@ })${5:} - trigger: ngstate - description: "UI-Router state using Angular style guide" + description: "UI-Router state" scope: javascript text: | - state('${1:state}', { + .state('${1:state}', { url: '${2:/url}' templateUrl: '${3:template}.html', controller: '${4:Controller}' @@ -178,26 +178,25 @@ })${6:} - trigger: ngmodule - description: "Module getter using Angular style guide" + description: "Module getter" scope: javascript text: | angular .module('${1:module}')${2:} - - trigger: ngconst - description: "Constant using Angular style guide" + description: "Constant" scope: javascript text: | .constant('${1:name}', ${2:value}); - trigger: ngvalue - description: "Value using Angular style guide" + description: "Value" scope: javascript text: | .value('${1:name}', ${2:value}); - trigger: ngconfig - description: "Config function using Angular style guide" + description: "Config phase function" scope: javascript text: | .config(${1:configuration}) @@ -210,7 +209,7 @@ } - trigger: ngrun - description: "Run function from Angular style guide" + description: "Run phase function" scope: javascript text: | .run(${1:runFn}) From 46bb5b0bc21d0411c18d8dcfdad54188b8f06589 Mon Sep 17 00:00:00 2001 From: John Papa Date: Mon, 16 Mar 2015 22:09:20 -0400 Subject: [PATCH 261/567] added translate snippet to brackets --- assets/brackets-angular-snippets.yaml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/assets/brackets-angular-snippets.yaml b/assets/brackets-angular-snippets.yaml index 720419af..ec207d87 100644 --- a/assets/brackets-angular-snippets.yaml +++ b/assets/brackets-angular-snippets.yaml @@ -220,3 +220,11 @@ function ${1:runFn} (${2:dependencies}) { ${3:} } + +- trigger: ngtranslate + description: "$translate service" + scope: javascript + text: | + $translate(['${1:key1}']).then(function(translations){ + ${2:value} = translations['${3:key1}']; + }); From 99434ac29fd11bd28640150cc64909b6799e7887 Mon Sep 17 00:00:00 2001 From: John Papa Date: Mon, 16 Mar 2015 22:13:10 -0400 Subject: [PATCH 262/567] added translate snippet to brackets --- README.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 015de6b8..3e44401d 100644 --- a/README.md +++ b/README.md @@ -1252,7 +1252,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see ``` Note: You can also name the controller when you inject it into the link function and access directive attributes as properties of the controller. - + ```javascript // Alternative to above example function linkFunc(scope, el, attr, vm) { @@ -1262,7 +1262,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see console.log('LINK: vm.max = %s', vm.max); } ``` - + ###### [Style [Y076](#style-y076)] - Use `bindToController = true` when using `controller as` syntax with a directive when you want to bind the outer scope to the directive's controller's scope. @@ -1979,7 +1979,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see - Use consistent names for all factories named after their feature. Use camel-casing for services and factories. Avoid prefixing factories and services with `$`. *Why?*: Provides a consistent way to quickly identify and reference factories. - + *Why?*: Avoids name collisions with built-in factories and services that use the `$` prefix. ```javascript @@ -2881,6 +2881,7 @@ Use file templates or snippets to help follow consistent styles and patterns. He ngconfig // defines a configuration phase function ngrun // defines a run phase function ngroute // defines an Angular ngRoute 'when' definition + ngtranslate // uses $translate service with its promise ``` **[Back to top](#table-of-contents)** From 2ae695ef7ffe57f65824770454b3ae32377c8a9f Mon Sep 17 00:00:00 2001 From: Jason Miazga Date: Tue, 24 Mar 2015 09:00:52 -0400 Subject: [PATCH 263/567] added service and filter to Atom snippets --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 3e44401d..e5a2e9a8 100644 --- a/README.md +++ b/README.md @@ -2850,6 +2850,8 @@ Use file templates or snippets to help follow consistent styles and patterns. He ngdirective // creates an Angular directive ngfactory // creates an Angular factory ngmodule // creates an Angular module + ngservice // creates an Angular service + ngfilter // creates an Angular filter ``` ### Brackets From c593cd113f66b23a69ecfbb6786c09097dbcdd3c Mon Sep 17 00:00:00 2001 From: angelochiello Date: Fri, 27 Mar 2015 08:51:20 +0100 Subject: [PATCH 264/567] [it-IT] Multiple new sections and PRs #337, #338, #340 #341 Updated adding the following sections: JSCS; Yeoman Generator; Routing; Task Automation; Filters. Updated as the following PRs: #337, #338, #340 --- i18n/it-IT.md | 189 ++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 168 insertions(+), 21 deletions(-) diff --git a/i18n/it-IT.md b/i18n/it-IT.md index 1530526b..cd285fe3 100644 --- a/i18n/it-IT.md +++ b/i18n/it-IT.md @@ -49,11 +49,13 @@ Nonostante questa guida spieghi i *cosa*, *come* e *perché*, trovo che sia di a 1. [Animazioni](#animazioni) 1. [Commenti](#commenti) 1. [JSHint](#jshint) + 1. [JSCS](#jscs) 1. [Costanti](#costanti) 1. [File Template e Snippet](#file-template-e-snippet) 1. [Generatore Yeoman](#generatore-yeoman) 1. [Routing](#routing) - 1. [Automazione dei Processi](#automazione-dei-processi) + 1. [Automazione dei processi](#automazione-dei-processi) + 1. [Filtri](#filtri) 1. [Documentazione di AngularJS](#documentazione-di-angularjs) 1. [Contribuire](#contribuire) 1. [Licenza](#licenza) @@ -1252,6 +1254,17 @@ Nonostante questa guida spieghi i *cosa*, *come* e *perché*, trovo che sia di a
min={{vm.min}}
``` + Nota: Puoi inoltre nominare il controller quando lo inietti nella link function e accedi agli attributi della directive come proprietà del controller. + + ```javascript + // Alternativa all'esempio sopra riportato + function linkFunc(scope, el, attr, vm) { + console.log('LINK: scope.min = %s *** should be undefined', scope.min); + console.log('LINK: scope.max = %s *** should be undefined', scope.max); + console.log('LINK: vm.min = %s', vm.min); + console.log('LINK: vm.max = %s', vm.max); + } + ``` ###### [Stile [Y076](#stile-y076)] - Usa `bindToController = true` quando usi la sintassi `controller as` con una directive al fine di fare il bind tra lo scope esterno e lo scope del controller della directive. @@ -1976,9 +1989,11 @@ Nonostante questa guida spieghi i *cosa*, *come* e *perché*, trovo che sia di a ### Nomi delle factory ###### [Stile [Y125](#stile-y125)] - - Usa una nomenclatura consistente per tutte le factory dando i nomi date le loro funzionalità. Usa il camel-case per service e factory. + - Usa una nomenclatura consistente per tutte le factory dando i nomi date le loro funzionalità. Usa il camel-case per service e factory. Evita di pre-nominare factory e service con `$` *Perché?*: Fornisce un modo consistente per identificare facilmente e referenziare le factory. + + *Perché?*: Evita collisione di nomi con factory e servizi di Angular esistenti che usano il prefisso `$`. ```javascript /** @@ -2641,6 +2656,94 @@ Gli unit test aiutano a mantenere il codice più chiaro, perciò ho incluso alcu **[Torna all'inizio](#tavola-dei-contenuti)** +## JSCS + +### Usa un file di opzioni +###### [Stile [Y235](#stile-y235)] + + - Usa JSCS per il controllo dello stile del tuo codice JavaScript ed assicurati di personalizzare il file di opzioni JSCS ed includerlo nel source control. Vedi [JSCS docs](http://www.jscs.info) per i dettagli sulle opzioni. + + *Perché?*: Fornisce un iniziale avvertimento prima di fare il commit di qualunque codice al source control. + + *Perché?*: Fornisce consistenza per l'intero team. + + ```javascript + { + "excludeFiles": ["node_modules/**", "bower_components/**"], + + "requireCurlyBraces": [ + "if", + "else", + "for", + "while", + "do", + "try", + "catch" + ], + "requireOperatorBeforeLineBreak": true, + "requireCamelCaseOrUpperCaseIdentifiers": true, + "maximumLineLength": { + "value": 100, + "allowComments": true, + "allowRegex": true + }, + "validateIndentation": 4, + "validateQuoteMarks": "'", + + "disallowMultipleLineStrings": true, + "disallowMixedSpacesAndTabs": true, + "disallowTrailingWhitespace": true, + "disallowSpaceAfterPrefixUnaryOperators": true, + "disallowMultipleVarDecl": null, + + "requireSpaceAfterKeywords": [ + "if", + "else", + "for", + "while", + "do", + "switch", + "return", + "try", + "catch" + ], + "requireSpaceBeforeBinaryOperators": [ + "=", "+=", "-=", "*=", "/=", "%=", "<<=", ">>=", ">>>=", + "&=", "|=", "^=", "+=", + + "+", "-", "*", "/", "%", "<<", ">>", ">>>", "&", + "|", "^", "&&", "||", "===", "==", ">=", + "<=", "<", ">", "!=", "!==" + ], + "requireSpaceAfterBinaryOperators": true, + "requireSpacesInConditionalExpression": true, + "requireSpaceBeforeBlockStatements": true, + "requireLineFeedAtFileEnd": true, + "disallowSpacesInsideObjectBrackets": "all", + "disallowSpacesInsideArrayBrackets": "all", + "disallowSpacesInsideParentheses": true, + + "validateJSDoc": { + "checkParamNames": true, + "requireParamTypes": true + }, + + "disallowMultipleLineBreaks": true, + + "disallowCommaBeforeLineBreak": null, + "disallowDanglingUnderscores": null, + "disallowEmptyBlocks": null, + "disallowMultipleLineStrings": null, + "disallowTrailingComma": null, + "requireCommaBeforeLineBreak": null, + "requireDotNotation": null, + "requireMultipleVarDecl": null, + "requireParenthesesAroundIIFE": true + } + ``` + +**[Torna all'inizio](#tavola-dei-contenuti)** + ## Costanti ### Variabili globali delle terze parti @@ -2758,12 +2861,44 @@ Usa file template o snippet che ti aiutino a seguire stili e schemi consistentem ngmodule // crea un module Angular ``` +### Brackets +###### [Stile [Y254](#stile-y254)] + + - Snippet di Angular che seguono questi stili e linee guida. + + - Brackets Extension manager ( File > Extension manager ) + - Installa ['Brackets Snippets (by edc)'](https://github.com/chuyik/brackets-snippets) + - Clicca sulla lampadina nel gutter destro in bracket + - Clicca su `Settings` e quindi `Import` + - Scegli il file e seleziona per saltare o fare l'override + - Clicca `Start Import` + + - In un file di tipo JavaScript digita questi comandi seguiti da un `TAB` + + ```javascript + // Questi sono snippet interi che contengono una IIFE + ngcontroller // crea un controller Angular + ngdirective // crea una directive Angular + ngfactory // crea una factory Angular + ngapp // crea una impostazione di modulo Angular + ngservice // crea un service Angular + ngfilter // crea un filtro Angular + ngroute // crea un routeProvider Angular + + // Questi sono snippet parziali intesi per essere concatenati + ngmodule // crea un getter di modulo Angular + ngstate // crea una definizione di stato di UI Router Angular + ngconfig // definisce un funzione per la fase di cofigurazione + ngrun // definisce una funzione per la fase di esecuzione + ngwhen // definisce una route per il routeProvider + ``` + **[Torna all'inizio](#tavola-dei-contenuti)** ## Generatore Yeoman ###### [Stile [Y260](#stile-y260)] -Puoi usare il [generatore yeoman di HotTowel](http://jpapa.me/yohottowel) per creare un'app che funga da punto di partenza per Angular che segua questa guida stilistica. +Puoi usare il [generatore yeoman di HotTowel](http://jpapa.me/yohottowel) per creare un'app che funga da punto di partenza per Angular che segue gli stili di questa guida. 1. Installa generator-hottowel @@ -2771,14 +2906,14 @@ Puoi usare il [generatore yeoman di HotTowel](http://jpapa.me/yohottowel) per cr npm install -g generator-hottowel ``` -2. Crea un nuova cartella e cambia la directory verso di essa +2. Crea una nuova cartella e cambia la directory su di essa ``` mkdir myapp cd myapp ``` -3. Lancia il generatore +3. Esegui il generatore ``` yo hottowel helloWorld @@ -2787,43 +2922,45 @@ Puoi usare il [generatore yeoman di HotTowel](http://jpapa.me/yohottowel) per cr **[Torna all'inizio](#tavola-dei-contenuti)** ## Routing -Il routing dal lato client è importante al fine di creare un flusso di navigazione tra le viste e le viste composte che sono fatte da diversi template più piccoli e directive. +Il routing del lato client è importante al fine di creare in flusso di navigazione tra view e composizione di view che sono costituite da template più piccoli e directive. ###### [Stile [Y270](#stile-y270)] - - Usa [AngularUI Router](http://angular-ui.github.io/ui-router/) per il routing dal lato client. + - Usa il [Router AngularUI](http://angular-ui.github.io/ui-router/) per il routing del lato client. - *Perché?*: UI Router offre tutte le funzionalità del router di Angular più altre che includono route nidificate e stati. + *Perché?*: UI Router offre tutte le funzionalità del router di Angular più alcune funzionalità aggiuntive che includono orute nidificate e stati. - *Perché?*: La sintassi è piuttosto simile al router di Angular ed è semplice migrare ad UI Router. + *Perché?*: la sintassi è piuttosto simile a quella del router di Angular ed è facile migrare a UI Router. ###### [Stile [Y271](#stile-y271)] - - Definisci le route per le viste nel modulo nel quale esistono. Ogni modulo dovrebbe contenere le route per le viste che si trovano nel modulo. + - Definisci le route per le view nel modulo dove queste esisteono. Ogni modulo dovrebbe contenere le route per le view del modulo. *Perché?*: Ogni modulo dovrebbe essere a se stante. - *Perché?*: Quando rimuovi o aggiungi un modulo, l'app conterrà le route che puntano a viste esistenti. + *Perché?*: Quando rimuovi o aggiungi un modulo, l'app conterrà soltanto route che puntano a view esistenti. - *Perché?*: Questo rende semplice abilitare o disabilitare porzioni di una applicazione senza preoccuparsi di route orfane. + *Perché?*: Ciò rende semplice abilitare o disabilitare porzioni di una applicazione senza preoccupazioni inerenti route orfane. **[Torna all'inizio](#tavola-dei-contenuti)** -## Automazione dei Processi -Usa [Gulp](http://gulpjs.com) o [Grunt](http://gruntjs.com) per la creazione di processi automatizzati. Gulp tende a codice sopra configurazione mentre Grunt tende a configurazione sopra codice. Personalmente preferisco Gulp perché lo percepisco più semplice da leggere e scrivere ma entrambi sono eccellenti. +## Automazione dei processi +Usa [Gulp](http://gulpjs.com) o [Grunt](http://gruntjs.com) per la creazione di processi automatizzati. Gulp si basa su codive sopra configurazione mentre Grunt si basa su configurazione sopre codice. Personalmente preferisco Gulp poiché lo percepisco come più facile da leggere e scrivere ma entrambi sono eccellenti. + +> Impara di più su Gulp per l'automazione dei processi e pattern in mio [corso Pluralsight su Gulp](http://jpapa.me/gulpps) (in inglese) ###### [Stile [Y400](#stile-y400)] - - Usa l'automazione dei processi per listare i file che deinifscono i moduli `*.module.js` prima di ogni altro file dell'applicazione di JavaScript. + - Usa l'automazione dei processi per elencare i file delle definizioni dei modili `*.module.js` prima di qualunque altro file JavaScript dell'applicazione. - *Perché?*: Angular necessita delle definizioni del moduli che devono essere registrati prima del loro utilizzo. + *Perché?*: Angular necessita delle definizione del modulo da essere registrate prima di essere usati. - *Perché?*: Dai i nomi ai moduli usando un pattern specifico quale `*.module.js` rende semplice prenderli con un glob e listarli prima. + *Perché?*: Nominare i moduli con un pattern specifico come `*.module.js` semplifica prenderli con un glob ed elencarli per primi. ```javascript var clientApp = './src/client/app/'; - // Prendi sempre i file dei moduli prima + // Prendi sempre i file dei moduli per primi var files = [ clientApp + '**/*.module.js', clientApp + '**/*.js' @@ -2832,8 +2969,18 @@ Usa [Gulp](http://gulpjs.com) o [Grunt](http://gruntjs.com) per la creazione di **[Torna all'inizio](#tavola-dei-contenuti)** +## Filtri + +###### [Stile [Y420](#stile-y420)] + + - Evita l'utilizzo di filtri per la scansione di tutte le proprietà di un grafico di un oggetto complesso. Usa i filtri per selezionare le proprietà. + + *Perché?*:I filtri possono facilmente essere abusati ed avere un impatto negativo sulle prestazioni se non usati con saggezza, per esempio quando i filtri hanno come soggetto un grafico di un ogetto largo e profondo. + +**[Torna all'inizio](#tavola-dei-contenuti)** + ## Documentazione di AngularJS -Per qualsiasi altro, riferimento alle API, controlla la [documentazione di Angular](//docs.angularjs.org/api). +For anything else, API reference, check the [Angular documentation](//docs.angularjs.org/api). ## Contribuire @@ -2843,8 +2990,8 @@ Apri prima una "issue" per discutere potenziali cambiamenti/aggiunte. Se hai del ### Processo - 1. Discuti i cambiamenti in un Issue di Github. - 2. Apri una Pull Request verso la brach develop, fai riferimento all issue e spiega i cambiamenti e perché questi aggiungono valore. + 1. Discuti i cambiamenti in un Issue. + 2. Apri una Pull Request, fai riferimento all issue e spiega i cambiamenti e perché questi aggiungono valore. 3. La Pull Request sarà vagliata e quindi fatto un merge o declinata. ## Licenza From df8e09a0077fb725de2e9dc3b402b79f11128ca4 Mon Sep 17 00:00:00 2001 From: angelochiello Date: Fri, 27 Mar 2015 08:55:23 +0100 Subject: [PATCH 265/567] [it-IT] PR #349 Updated as PR #349 "added service and filter to Atom snippets" --- i18n/it-IT.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/i18n/it-IT.md b/i18n/it-IT.md index cd285fe3..d7c826e5 100644 --- a/i18n/it-IT.md +++ b/i18n/it-IT.md @@ -2859,6 +2859,8 @@ Usa file template o snippet che ti aiutino a seguire stili e schemi consistentem ngdirective // crea una directive Angular ngfactory // crea una factory Angular ngmodule // crea un module Angular + ngservice // crea un servizio Angular + ngfilter // crea un filtro Angular ``` ### Brackets From bdb1056a6c0990d6179039e36d992152c1659712 Mon Sep 17 00:00:00 2001 From: Marek Goczol Date: Wed, 1 Apr 2015 09:03:14 +0400 Subject: [PATCH 266/567] typo --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index e5a2e9a8..85f58462 100644 --- a/README.md +++ b/README.md @@ -364,7 +364,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see } ``` - Note: You can avoid any [jshint](http://www.jshint.com/) warnings by placing the comment below above the line of code. However it is not needed when the function is named using UpperCasing, as this convention means it is a constructor function, which is what a controller is in Angular. + Note: You can avoid any [jshint](http://www.jshint.com/) warnings by placing the comment above the line of code. However it is not needed when the function is named using UpperCasing, as this convention means it is a constructor function, which is what a controller is in Angular. ```javascript /* jshint validthis: true */ From 61152ac7aa60a3bf0147c326ef90f23fb2fc95bc Mon Sep 17 00:00:00 2001 From: avillanueva Date: Wed, 1 Apr 2015 13:49:34 -0430 Subject: [PATCH 267/567] =?UTF-8?q?Correci=C3=B3nes=20y=20traduccion=20de?= =?UTF-8?q?=20palabras=20importantes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- i18n/es-ES.md | 190 +++++++++++++++++++++++++------------------------- 1 file changed, 95 insertions(+), 95 deletions(-) diff --git a/i18n/es-ES.md b/i18n/es-ES.md index d03d076b..af249df0 100644 --- a/i18n/es-ES.md +++ b/i18n/es-ES.md @@ -33,8 +33,8 @@ Mientras que esta guía explica el *qué*, *por qué* y *cómo*, me resulta úti 1. [Módulos](#módulos) 1. [Controladores](#controladores) 1. [Servicios](#servicios) - 1. [Factories](#factories) - 1. [Data Services](#data-services) + 1. [Fábricas](#fábricas) + 1. [Servicios de Datos](#servicios-de-datos) 1. [Directivas](#directivas) 1. [Resolviendo Promesas en un Controlador](#resolviendo-promesas-en-un-controlador) 1. [Anotación Manual para la Inyección de Dependencias](#anotación-manual-para-la-inyección-de-dependencias) @@ -66,7 +66,7 @@ Mientras que esta guía explica el *qué*, *por qué* y *cómo*, me resulta úti - Define 1 componente por archivo. - El siguiente ejemplo define el módulo `app` y sus dependencias, define un controlador, y defines una factory todo en el mismo archivo. + El siguiente ejemplo define el módulo `app` y sus dependencias, define un controlador, y defines una fábrica todo en el mismo archivo. ```javascript /* evitar */ @@ -175,7 +175,7 @@ Mientras que esta guía explica el *qué*, *por qué* y *cómo*, me resulta úti - Nota: Para acortar únicamente, el resto de los ejemplos de esta guía podrían omitir la sintaxis IIFE. - - Nota: IIFE previente que el código de los tests llegue a sus variables privadas, como expresiones regulares o funciones de ayuda que normalmente vienen bien para hacer pruebas por sí solas. Sin embargo, puedes acceder a ellas creando accesorios o accediendo a través de sus componentes. Por ejemplo, poniendo las funciones de ayuda, expresiones regulares o constantes en su propia factory. + - Nota: IIFE previente que el código de los tests llegue a sus variables privadas, como expresiones regulares o funciones de ayuda que normalmente vienen bien para hacer pruebas por sí solas. Sin embargo, puedes acceder a ellas creando accesorios o accediendo a través de sus componentes. Por ejemplo, poniendo las funciones de ayuda, expresiones regulares o constantes en su propia fábrica. **[Volver arriba](#tabla-de-contenidos)** @@ -325,7 +325,7 @@ Mientras que esta guía explica el *qué*, *por qué* y *cómo*, me resulta úti *¿Por qué?*: `controllerAs` es azúcar sintáctico sobre el `$scope`. Puedes enlazar a la vista y acceder a los métodos del `$scope`. - *¿Por qué?*: Ayuda a evitar la tentación de usar los métodos del `$scope` dentro de un controller cuando debería ser mejor evitar usarlos o moverlos a una factory. Considera usar `$scope` en una factory, o en un controlador sólo cuando sea necesario. Por ejemplo cuando publicas y te suscribes a eventos usando [`$emit`](https://docs.angularjs.org/api/ng/type/$rootScope.Scope#$emit), [`$broadcast`](https://docs.angularjs.org/api/ng/type/$rootScope.Scope#$broadcast), o [`$on`](https://docs.angularjs.org/api/ng/type/$rootScope.Scope#$on) considera mover estos usos a una factory e invocarlos desde el controller. + *¿Por qué?*: Ayuda a evitar la tentación de usar los métodos del `$scope` dentro de un controller cuando debería ser mejor evitar usarlos o moverlos a una fábrica. Considera usar `$scope` en una factory, o en un controlador sólo cuando sea necesario. Por ejemplo cuando publicas y te suscribes a eventos usando [`$emit`](https://docs.angularjs.org/api/ng/type/$rootScope.Scope#$emit), [`$broadcast`](https://docs.angularjs.org/api/ng/type/$rootScope.Scope#$broadcast), o [`$on`](https://docs.angularjs.org/api/ng/type/$rootScope.Scope#$on) considera mover estos usos a una fábrica e invocarlos desde el controlador. ```javascript /* evitar */ @@ -494,7 +494,7 @@ Mientras que esta guía explica el *qué*, *por qué* y *cómo*, me resulta úti proceso de hoisting así que no tenemos que preocuparnos por usar una función antes de que sea definida (como la habría si fueran funciones en forma de expresión) - *¿Por qué?*: No tendrás que propcuparte de que si pones `var a` antes de `var b` se rompa el código porque `a` dependa de `b`. + *¿Por qué?*: No tendrás que preocuparte de que si pones `var a` antes de `var b` se rompa el código porque `a` dependa de `b`. *¿Por qué?*: El orden es crítico para las funciones en forma de expresión @@ -527,7 +527,7 @@ Mientras que esta guía explica el *qué*, *por qué* y *cómo*, me resulta úti } ``` - Nótese que las cosas importantes están dispersas en el ejemplo anterior. En el siguiente ejemplo, lo importante está arriba. Por ejemplo, las variables asociadas al controller como `vm.avengers` y `vm.title`. Los detalles de implementación están debajo. Así es más fácil de leer. + Nótese que las cosas importantes están dispersas en el ejemplo anterior. En el siguiente ejemplo, lo importante está arriba. Por ejemplo, las variables asociadas al controlador como `vm.avengers` y `vm.title`. Los detalles de implementación están debajo. Así es más fácil de leer. ```javascript /* @@ -561,11 +561,11 @@ Mientras que esta guía explica el *qué*, *por qué* y *cómo*, me resulta úti ### Diferir la Lógica del Controlador ###### [Style [Y035](#style-y035)] - - Difiera la lógica dentro de un controlador delegándola a servicios y factories. + - Difiera la lógica dentro de un controlador delegándola a servicios y fábricas. *¿Por qué?*: La lógica podría ser reutilizada por varios controladores cuando la colocas en un servicio y la expones como una función. - *¿Por qué?*: La lógica en un servicio puede ser aislada en un test unitario, mientras que la lógica de llamadas en un controller se puede mockear fácilmente. + *¿Por qué?*: La lógica en un servicio puede ser aislada en un test unitario, mientras que la lógica de llamadas en un controlador se puede mockear fácilmente. *¿Por qué?*: Elimina dependencias y esconde detalles de implementación del controlador. @@ -619,7 +619,7 @@ Mientras que esta guía explica el *qué*, *por qué* y *cómo*, me resulta úti ### Mantén tus Controladores Enfocados ###### [Style [Y037](#style-y037)] - - Define un controller para una vista, no intentes reutilizar el controller para otras vistas. En lugar de eso, mueve la lógica que se pueda reutilizar a factories y deja el controlador simple y enfocado en su vista. + - Define un controlador para una vista, no intentes reutilizar el controlador para otras vistas. En lugar de eso, mueve la lógica que se pueda reutilizar a fábricas y deja el controlador simple y enfocado en su vista. *¿Por qué?*: Reutilizar controladores con varias vistas es arriesgado y necesitarías buena cobertura de tests end to end (e2e) para asegurar que todo funciona bien en la aplicación. @@ -719,17 +719,17 @@ Mientras que esta guía explica el *qué*, *por qué* y *cómo*, me resulta úti **[Volver arriba](#tabla-de-contenidos)** -## Factories +## Fábricas ### Responsabilidad Única ###### [Style [Y050](#style-y050)] - - Las factories deben tener una [responsabilidad única](http://en.wikipedia.org/wiki/Single_responsibility_principle), que es encapsulada por su contexto. Cuando una factory empiece a exceder el principio de responsabilidad única, una nueva factory debe ser creada. + - Las fábricas deben tener una [responsabilidad única](http://en.wikipedia.org/wiki/Single_responsibility_principle), que es encapsulada por su contexto. Cuando una fábrica empiece a exceder el principio de responsabilidad única, una nueva fábrica debe ser creada. ### Singletons ###### [Style [Y051](#style-y051)] - - Las Factories son singletos y devuelven un objeto que contiene las variables del servicio. + - Las Fábricas son singleton y devuelven un objeto que contiene las variables del servicio. Nota: [Todos los servicios AngularJS son singletons](https://docs.angularjs.org/guide/services). @@ -788,20 +788,20 @@ Mientras que esta guía explica el *qué*, *por qué* y *cómo*, me resulta úti De esta forma se asocian los bindeos desde el objeto que lo mantiene, los valores primitivos no se pueden modificar por si solos usando este patrón - ![Factories Usando "Above the Fold"](https://raw.githubusercontent.com/johnpapa/angularjs-styleguide/master/assets/above-the-fold-2.png) + ![Fábricas Usando "Above the Fold"](https://raw.githubusercontent.com/johnpapa/angularjs-styleguide/master/assets/above-the-fold-2.png) ### Declaración de Funciones para Esconder los Detalles de Implementación ###### [Style [Y053](#style-y053)] - - Declara funciones para esconder detalles de implementación. Manten los elementos accesibles en la parte superior de la factory. Referencia a los que aparezcan después en el archivo. Para más detalles visita [este post](http://www.johnpapa.net/angular-function-declarations-function-expressions-and-readable-code). + - Declara funciones para esconder detalles de implementación. Manten los elementos accesibles en la parte superior de la fábrica. Referencia a los que aparezcan después en el archivo. Para más detalles visita [este post](http://www.johnpapa.net/angular-function-declarations-function-expressions-and-readable-code). - *¿Por qué?*: Coloca los elementos accesibles en la parte superior para hacerlo más fácil de leer y ayudarte a identificar instantáneamente qué funciones de la factory se pueden accesar externamente. + *¿Por qué?*: Coloca los elementos accesibles en la parte superior para hacerlo más fácil de leer y ayudarte a identificar instantáneamente qué funciones de la fábrica se pueden accesar externamente. *¿Por qué?*: Colocar los detalles de implementación de una función al final del archivo mueve esa complegidad fuera de la vista, de esta forma puedes dejar lo importante arriba. - *¿Por qué?*: Las declaraciones de las funciones son "hoisted" de esta forma no hay problemas en usar una función antes de su definición (como la habría si fueran funciones en forma de expresión). + *¿Por qué?*: Las declaraciones de las funciones son "elevedas" de esta forma no hay problemas en usar una función antes de su definición (como la habría si fueran funciones en forma de expresión). - *¿Por qué?*: No tendrás que propcuparte de que si pones `var a` antes de `var b` se rompa el código porque `a` dependa de `b`. + *¿Por qué?*: No tendrás que preocuparte de que si pones `var a` antes de `var b` se rompa el código porque `a` dependa de `b`. *¿Por qué?*: El orden es crítico para las funciones en forma de expresión @@ -890,18 +890,18 @@ Mientras que esta guía explica el *qué*, *por qué* y *cómo*, me resulta úti **[Volver arriba](#tabla-de-contenidos)** -## Data Services +## Servicios de Datos ### Separate Data Calls ###### [Style [Y060](#style-y060)] - Refactoriza la lógica para hacer operaciones e interaciones con datos en una factory. Crear data services responsables de las peticiones XHR, local storage, memoria o cualquier otra operación con datos. - *¿Por qué?*: La responsabilidad del controlador es la de presentar y recoger información para la vista. No debe importarle cómo se consiguen los datos, sólo saber cómo conseguirlos. Separando los data services movemos la lógica de cómo conseguirlos al data service, y deja el controlador simple, enfocándose en la vista. + *¿Por qué?*: La responsabilidad del controlador es la de presentar y recoger información para la vista. No debe importarle cómo se consiguen los datos, sólo saber cómo conseguirlos. Separando los datos de servicios movemos la lógica de cómo conseguirlos al servicio de datos, y deja el controlador simple, enfocándose en la vista. *¿Por qué?*: Hace más fácil testear (mock o real) las llamadas de datos cuando testeamos un controlador que usa un data service. - *¿Por qué?*: La implementación del data service puede tener código muy específico para usar el repositorio de datos. Podría incluir cabeceras, cómo hablar a los datos, u otros servicios como $http. Separando la lógica en data services encapsulamos la lógica en un único lugar, escondiendo la implementación de sus consumidores externos (quizá un controlador), de esta forma es más fácil cambiar la implementación. + *¿Por qué?*: La implementación del servicio de datos puede tener código muy específico para usar el repositorio de datos. Podría incluir cabeceras, cómo hablar a los datos, u otros servicios como $http. Separando la lógica en servicios de datos encapsulamos la lógica en un único lugar, escondiendo la implementación de sus consumidores externos (quizá un controlador), de esta forma es más fácil cambiar la implementación. ```javascript /* recomendado */ @@ -934,7 +934,7 @@ Mientras que esta guía explica el *qué*, *por qué* y *cómo*, me resulta úti } ``` - Nota: El data service es llamado desde los consumidores, como el controlador, escondiendo la implementación del consumidor como se muestra a continuación. + Nota: El servicio de datos es llamado desde los consumidores, como el controlador, escondiendo la implementación del consumidor como se muestra a continuación. ```javascript /* recomendado */ @@ -971,7 +971,7 @@ Mientras que esta guía explica el *qué*, *por qué* y *cómo*, me resulta úti ### Regresa una Promesa desde las Llamadas a Datos ###### [Style [Y061](#style-y061)] - - Cuando llamamos a data services que devuelven una promesa como $http, devuelve una promesa en la llamada de tu función también. + - Cuando llamamos a servicios de datos que devuelven una promesa como $http, devuelve una promesa en la llamada de tu función también. *¿Por qué?*: Puedes encadenar promesas y hacer algo cuando la llamada se complete y resuelva o rechace la promesa. @@ -998,7 +998,7 @@ Mientras que esta guía explica el *qué*, *por qué* y *cómo*, me resulta úti function getAvengers() { /** * Step 2 - * Pide al data service los datos y espera + * Pide al servicio de datos los datos y espera * por la promesa */ return dataservice.getAvengers() @@ -1095,7 +1095,7 @@ Mientras que esta guía explica el *qué*, *por qué* y *cómo*, me resulta úti /* spinner.directive.js */ /** - * @desc directiva de spinner que puede ser usada a lo largo de las applicaciones en la compañía Acme + * @desc directiva de spinner que puede ser usada a lo largo de las aplicaciones en la compañía Acme * @example
*/ angular @@ -1107,7 +1107,7 @@ Mientras que esta guía explica el *qué*, *por qué* y *cómo*, me resulta úti } ``` - Nota: Hay muchas formas de llamar a las directivas, especialmente cuando pueden ser usadas en scopes específicos. Elige un nombre que tenga sentido para la directiva y que su archivo sea distintivo y claro. Hemos visto algunos ejemplos antes, pero veremos más en la sección de cómo nombrar. + Nota: Hay muchas formas de llamar a las directivas, especialmente cuando pueden ser usadas en ámbitos específicos. Elige un nombre que tenga sentido para la directiva y que su archivo sea distintivo y claro. Hemos visto algunos ejemplos antes, pero veremos más en la sección de cómo nombrar. ### Manipula el DOM en una Directiva ###### [Style [Y072](#style-y072)] @@ -1355,11 +1355,11 @@ Mientras que esta guía explica el *qué*, *por qué* y *cómo*, me resulta úti - Cuando un controlador depende en una promesa a ser resuelta antes de que el controlador se active, resuelve esas dependencias en el `$routeProvider` antes de que la lógica del controlador sea ejecutada. Si necesitas condicionalmente cancelar una ruta antes de que el controlador sea activado, usa un route resolver. - - Usa un route resolver cuando decidas cancelar la ruta antes de transicionar a la Vista. + - Usa un route resolver cuando decidas cancelar la ruta antes de hacer la transición a la Vista. - *¿Por qué?*: Un controlador puede requerir datos antes de que se cargue. Esos datos deben venir desde una promesa a través de una factory o de [$http](https://docs.angularjs.org/api/ng/service/$http). Usando un [route resolve](https://docs.angularjs.org/api/ngRoute/provider/$routeProvider) permite que la promesa se resuelva antes de que la lógica del controlador se ejecute, así puedes tomar decisiones basándote en los datos de la promesa. + *¿Por qué?*: Un controlador puede requerir datos antes de que se cargue. Esos datos deben venir desde una promesa a través de una fábrica o de [$http](https://docs.angularjs.org/api/ng/service/$http). Usando un [route resolve](https://docs.angularjs.org/api/ngRoute/provider/$routeProvider) permite que la promesa se resuelva antes de que la lógica del controlador se ejecute, así puedes tomar decisiones basándote en los datos de la promesa. - *¿Por qué?*: El código se ejecuta después de la ruta y la función activate del controlador. La Vista empieza a cargar al instante. El bindeo de los datos se jecutan cuando la promesa del activate se resuelva. Una animación de "Cargando" se puede mostrar durante la transición de la vista (via ng-view o ui-view) + *¿Por qué?*: El código se ejecuta después de la ruta y la función activate del controlador. La Vista empieza a cargar al instante. El bindeo de los datos se ejecutan cuando la promesa del activate se resuelva. Una animación de "Cargando" se puede mostrar durante la transición de la vista (via ng-view o ui-view) Nota: El código se ejecuta antes que la ruta mediante una promesa. Rechazar la promesa cancela la ruta. Resolverla hace que la nueva vista espere a que la ruta sea resuelta. Una animación de "Cargando" puede ser mostrada antes de que se resuelva. Si quieres que la Vista aparezca más rápido y no necesitas un checkpoint para decidir si puedes mostrar o no la view, considera la técnica [controller `activate`](#style-y080). @@ -1460,7 +1460,7 @@ Mientras que esta guía explica el *qué*, *por qué* y *cómo*, me resulta úti ### Insegura después de la Minificación ###### [Style [Y090](#style-y090)] - - Evita usar la sintaxis acortada para declarar dependencias sin usar algún método que permita minimifación. + - Evita usar la sintaxis acortada para declarar dependencias sin usar algún método que permita minificación. *¿Por qué?*: Los parámetros al componente (e.g. controller, factory, etc) se convertirán en variables acortadas. Por ejemplo, `common` y `dataservice` se convertirán `a` o `b` y no serán encontradas por AngularJS. @@ -1490,7 +1490,7 @@ Mientras que esta guía explica el *qué*, *por qué* y *cómo*, me resulta úti *¿Por qué?*: Esto salvaguarda tus dependencias de ser vulnerables de problemas a la hora de minimizar cuando los parámetros se acorten. Por ejemplo, `common` y `dataservice` se convertirán `a` o `b` y no serán encontradas por AngularJS. - *¿Por qué?*: Evita crear dependencias en línea, ya que las listas largas pueden ser difícil de leer en el array. También puede ser confuso que el array sea una serie de cadenas mientras que el último componente es una función. + *¿Por qué?*: Evita crear dependencias en línea, ya que las listas largas pueden ser difícil de leer en el arreglo. También puede ser confuso que el arreglo sea una serie de cadenas mientras que el último componente es una función. ```javascript /* evitar */ @@ -1525,7 +1525,7 @@ Mientras que esta guía explica el *qué*, *por qué* y *cómo*, me resulta úti } ``` - Nota: Cuando tu función está debajo de un return, $inject puede ser inalcanzable (esto puede pasar en una directiva). Puedes solucionarlo moviendo el $inject encima del return o usando la sintaxis de array para inyectar. + Nota: Cuando tu función está debajo de un return, $inject puede ser inalcanzable (esto puede pasar en una directiva). Puedes solucionarlo moviendo el $inject encima del return o usando la sintaxis de arreglo para inyectar. Nota: [`ng-annotate 0.10.0`](https://github.com/olov/ng-annotate) introduce una funcionalidad donde mueve `$inject` donde es alcanzable. @@ -1670,7 +1670,7 @@ Mientras que esta guía explica el *qué*, *por qué* y *cómo*, me resulta úti - Usa [gulp-ng-annotate](https://www.npmjs.org/package/gulp-ng-annotate) o [grunt-ng-annotate](https://www.npmjs.org/package/grunt-ng-annotate) en una tarea de construcción automática. Inyecta `/* @ngInject */` antes de cualquier función que tenga dependecias. - *¿Por qué?*: ng-annotate atrapará la mayoría de las dependecias, pero algunas veces requiere indicios usando la sintaxis `/* @ngInject */`. + *¿Por qué?*: ng-annotate atrapará la mayoría de las dependencias, pero algunas veces requiere indicios usando la sintaxis `/* @ngInject */`. El código siguiente es un ejemplo de una tarea de Gulp que usa ngAnnotate @@ -1700,14 +1700,14 @@ Mientras que esta guía explica el *qué*, *por qué* y *cómo*, me resulta úti ## Manejo de Excepciones -### decorators +### Decoradores ###### [Style [Y110](#style-y110)] - - Usa un [decorator](https://docs.angularjs.org/api/auto/service/$provide#decorator), en tiempo de configuración usando el servicio [`$provide`](https://docs.angularjs.org/api/auto/service/$provide), en el servicio [`$exceptionHandler`](https://docs.angularjs.org/api/ng/service/$exceptionHandler) para realizar acciones personalizadas cuando una excepción ocurra. + - Usa un decorador o [decorator](https://docs.angularjs.org/api/auto/service/$provide#decorator), en tiempo de configuración usando el servicio [`$provide`](https://docs.angularjs.org/api/auto/service/$provide), en el servicio [`$exceptionHandler`](https://docs.angularjs.org/api/ng/service/$exceptionHandler) para realizar acciones personalizadas cuando una excepción ocurra. *¿Por qué?*: Provee una manera consistente de manejar excepciones de AngularJS que no están siendo capturadas en tiempo de desarrollo o en tiempo de ejecución. - Nota: Otra opción es sobreescribir el servicio en lugar de usar un decorator. Esto está bien, pero si quiere mantener el comportamiento por default y extenderlo se recomienda usar un decorator. + Nota: Otra opción es sobreescribir el servicio en lugar de usar un decorador. Esto está bien, pero si quiere mantener el comportamiento por default y extenderlo se recomienda usar un decorador. ```javascript /* recomendado */ @@ -1745,7 +1745,7 @@ Mientras que esta guía explica el *qué*, *por qué* y *cómo*, me resulta úti ### Cachadores de Excepciones ###### [Style [Y111](#style-y111)] - - Crea una factory que exponga una interfaz para cachar y manejar excepciones elegantemente. + - Crea una fábrica que exponga una interfaz para cachar y manejar excepciones elegantemente. *¿Por qué?*: Provee de una manera consistente de cachar excepciones que puedan ser arrojadas en tu código (e.g. durante llamadas XHR o promesas que fallaron). @@ -1776,12 +1776,12 @@ Mientras que esta guía explica el *qué*, *por qué* y *cómo*, me resulta úti ### Errores de Ruta ###### [Style [Y112](#style-y112)] - - Maneja y logea todos los errors de ruteo usando [`$routeChangeError`](https://docs.angularjs.org/api/ngRoute/service/$route#$routeChangeError). + - Maneja y logea todos los errores de enrutamiento usando [`$routeChangeError`](https://docs.angularjs.org/api/ngRoute/service/$route#$routeChangeError). *¿Por qué?*: Provee una manera consistente de manejar todos los - errores de ruteo. + errores de enrutamiento. - *¿Por qué?*: Potencialmente provee una mejor experiencia de usuario si un error de ruteo ocurre y tu los redirijes a una pantalla amigable con más detalles u opciones de recuperación. + *¿Por qué?*: Potencialmente provee una mejor experiencia de usuario si un error de enrutamiento ocurre y tu los rediriges a una pantalla amigable con más detalles u opciones de recuperación. ```javascript /* recomendado */ @@ -1823,10 +1823,10 @@ Mientras que esta guía explica el *qué*, *por qué* y *cómo*, me resulta úti *¿Por qué?*: Las pautas para nombrar deberían simplemente ayudarte a encontrar tu código rápidamente y hacerlo más fácil de entender. -### Nombres de Archivo para Feature +### Nombres de Archivo para Característica ###### [Style [Y121](#style-y121)] - - Usa nombres consistentes para todos los componentes siguiendo un patrón que describa el feature del componente y después (opcionalmente) su tipo. Mi patrón recomendado es `feature.type.js`. + - Usa nombres consistentes para todos los componentes siguiendo un patrón que describa la característica o feature del componente y después (opcionalmente) su tipo. Mi patrón recomendado es `feature.type.js`. *¿Por qué?*: Provee de una manera consistente para identificar componentes rápidamente. @@ -1893,9 +1893,9 @@ Mientras que esta guía explica el *qué*, *por qué* y *cómo*, me resulta úti ### Nombres de Archivos de Prueba ###### [Style [Y122](#style-y122)] - - Nombra especificaciones de pruebas de manera similar a la del componente que estan probando con un sufijo de `spec`. + - Nombra especificaciones de pruebas de manera similar a la del componente que están probando con un sufijo de `spec`. - *¿Por qué?*: Provee de una manera consistente de idenficar componentes rápidamente. + *¿Por qué?*: Provee de una manera consistente de identificar componentes rápidamente. *¿Por qué?*: Provee de un patrón de coincidencia para [karma](http://karma-runner.github.io/) u otros test runners. @@ -1935,11 +1935,11 @@ Mientras que esta guía explica el *qué*, *por qué* y *cómo*, me resulta úti ###### [Style [Y124](#style-y124)] - Agrega el sufijo `Controller` al nombre del controlador o déjalo sin - sufijo. Escoje 1, no uses ambos. + sufijo. Escoge 1, no uses ambos. *¿Por qué?*: El sufijo `Controller` es usado más comúnmente y es más descriptivo explícitamente. - *¿Por qué?*: Omitir el sufijo es más sucinto y el controlador es fácilmente identificable más seguido incluso sin el sufijo. + *¿Por qué?*: Omitir el sufijo es más breve y el controlador es fácilmente identificable más seguido incluso sin el sufijo. ```javascript /** @@ -1967,12 +1967,12 @@ Mientras que esta guía explica el *qué*, *por qué* y *cómo*, me resulta úti function AvengersController() { } ``` -### Nombres de Factories +### Nombres de Fábricas ###### [Style [Y125](#style-y125)] - - Usa nombres consistentes para todas las factories nombradas a partir de lo que hacen. Usa camel-casing para los servicios y las factories. + - Usa nombres consistentes para todas las fábricas nombradas a partir de lo que hacen. Usa camel-casing para los servicios y las fábricas. - *¿Por qué?*: Provee una manera consistente de identificar y referenciar factories rápidamente. + *¿Por qué?*: Provee una manera consistente de identificar y referenciar fábricas rápidamente. ```javascript /** @@ -2030,7 +2030,7 @@ Mientras que esta guía explica el *qué*, *por qué* y *cómo*, me resulta úti ### Rutas ###### [Style [Y129](#style-y129)] - - Separa la configuración de la ruta en un arhivo propio. Algunos ejemplos pueden ser `app.route.js` para el módulo principal y `admin.route.js` para el módulo admin `admin`. Incluso en aplicaciones pequeñas prefiero esta separación del resto de la configuración. + - Separa la configuración de la ruta en un archivo propio. Algunos ejemplos pueden ser `app.route.js` para el módulo principal y `admin.route.js` para el módulo admin `admin`. Incluso en aplicaciones pequeñas prefiero esta separación del resto de la configuración. **[Volver arriba](#tabla-de-contenidos)** @@ -2040,9 +2040,9 @@ Mientras que esta guía explica el *qué*, *por qué* y *cómo*, me resulta úti - Estructura tu aplicación de tal manera que puedas Localizar (`L`ocate) tu código rápidamente, Identificar (`I`dentify) el código de un vistazo, mantener la estructura más plana (`F`lattest) que puedas, y Trata (`T`ry) de mantenerte DRY. La estructura debe de seguir estas 4 pautas básicas. - *¿Por qué LIFT?*: Provee una estructura consistente que escala bien, es modular, y hace más fácil incrementar la eficiencia de los desarrolladores al encontrar código rápidamente. Otra manera de checar la estructura de tu aplicación es preguntarte a ti mismo: ¿Qué tan rápido puede abrir y trabajar en todos los arhivos relacionados a una feature? + *¿Por qué LIFT?*: Provee una estructura consistente que escala bien, es modular, y hace más fácil incrementar la eficiencia de los desarrolladores al encontrar código rápidamente. Otra manera de checar la estructura de tu aplicación es preguntarte a ti mismo: ¿Qué tan rápido puede abrir y trabajar en todos los archivos relacionados a una caracteristica? - Cuando encuentro que mi estructura no se siente cómoda, regreso y revisito estas pautas LIFT + Cuando encuentro que mi estructura no se siente cómoda, regreso y reviso estas pautas LIFT 1. `L`ocating - Localizar nuestro código es fácil 2. `I`dentify - Identificar código de un vistazo @@ -2052,9 +2052,9 @@ Mientras que esta guía explica el *qué*, *por qué* y *cómo*, me resulta úti ### Localizar ###### [Style [Y141](#style-y141)] - - Has que la localizar tu código sea intuitivo, simple y rápido. + - Has que la localización tu código sea intuitivo, simple y rápido. - *¿Por qué?*: Encuentro que esto es super importante para un proyecto. Si el equipo no puede encontrar los archivos en los que necesita trabajar rápidamente, no podran trabajar tan eficientemente como sea posible, y la estructura necesita cambiar. Puede que no conozcas el nombre del archivo o donde están sus archivos relacionados, así que poniéndolos en las locaciones más intuitivas y cerca de los otros ahorra mucho tiempo. Una estructura de directorios descriptiva puede ayudar con esto. + *¿Por qué?*: Encuentro que esto es super importante para un proyecto. Si el equipo no puede encontrar los archivos en los que necesita trabajar rápidamente, no podrán trabajar tan eficientemente como sea posible, y la estructura necesita cambiar. Puede que no conozcas el nombre del archivo o donde están sus archivos relacionados, así que poniéndolos en las locaciones más intuitivas y cerca de los otros ahorra mucho tiempo. Una estructura de directorios descriptiva puede ayudar con esto. ``` /bower_components @@ -2077,9 +2077,9 @@ Mientras que esta guía explica el *qué*, *por qué* y *cómo*, me resulta úti ### Identificar ###### [Style [Y142](#style-y142)] - - Cuando miras en un arhivo deberías saber instantáneamente qué contiene y qué representa. + - Cuando miras en un archivo deberías saber instantáneamente qué contiene y qué representa. - *¿Por qué?*: Gastas menos tiempo buscando y urgando por código, y es más eficiente. Si esto significa que quieres nombres de archivos más largos, entonces que así sea. Se descriptivo con los nombres de los archivos y mantén el contenido del arhivo a exactamente 1 componente. Evita archivos con múltiples controladores, o una mezcla. Hay excepciones a la regla de 1 por archivo cuando tengo un conjunto de pequeñas features que están relacionadas unas con otras, aún así son fácilmente identificables. + *¿Por qué?*: Gastas menos tiempo buscando y urgando por código, y es más eficiente. Si esto significa que quieres nombres de archivos más largos, entonces que así sea. Se descriptivo con los nombres de los archivos y mantén el contenido del archivo a exactamente 1 componente. Evita archivos con múltiples controladores, o una mezcla. Hay excepciones a la regla de 1 por archivo cuando tengo un conjunto de pequeñas features que están relacionadas unas con otras, aún así son fácilmente identificables. ### Estructura Plana ###### [Style [Y143](#style-y143)] @@ -2102,21 +2102,21 @@ Mientras que esta guía explica el *qué*, *por qué* y *cómo*, me resulta úti ### Pautas Universales ###### [Style [Y150](#style-y150)] - - Ten una visión de implementación de corto y largo plazo. En otras palabras, empieza con poco pero ten en mente hacia donde se dirige la aplicación. Todo el código de la aplicación va en el directorio raíz llamado `app`. Todo el contenido es separado en 1 feature por archivo. Cada controlador, servicio, módulo, vista tiene su propio archivo. Todos los vendor scripts de terceros son almacenados en otro directorio raíz y no en el directorio `app`. Si yo no lo escribí no los quiero saturando mi aplicación (`bower_components`, `scripts`, `lib`). + - Ten una visión de implementación de corto y largo plazo. En otras palabras, empieza con poco pero ten en mente hacia donde se dirige la aplicación. Todo el código de la aplicación va en el directorio raíz llamado `app`. Todo el contenido es separado en 1 característica por archivo. Cada controlador, servicio, módulo, vista tiene su propio archivo. Todos los vendor scripts de terceros son almacenados en otro directorio raíz y no en el directorio `app`. Si yo no lo escribí no los quiero saturando mi aplicación (`bower_components`, `scripts`, `lib`). Nota: Encuentra más detalles y el razonamiento detrás de esta estructura en [este post original sobre la estructura de una aplicación](http://www.johnpapa.net/angular-app-structuring-guidelines/). ### Layout ###### [Style [Y151](#style-y151)] - - Coloca los componentes que definen el layout universal de la aplicación en un directorio llamado `layout`. Estos pueden incluir una vista caparazón y un controlador que actuen como un contenedor para la aplicación, navegación, menús, áreas de contenido, y otras regiones. + - Coloca los componentes que definen el layout universal de la aplicación en un directorio llamado `layout`. Estos pueden incluir una vista caparazón y un controlador que actúen como un contenedor para la aplicación, navegación, menús, áreas de contenido, y otras regiones. *¿Por qué?*: Organiza todo el layout en un lugar único reusado a lo largo de la aplicación. -### Estructura de Carpetas-por-Feature +### Estructura de Carpetas-por-Característica ###### [Style [Y152](#style-y152)] - - Crea carpetas llamadas de acuerdo al feature que representan. Cuando un folder crezca para contener más de 7 archivos, comienza a considerar la creación de una carpeta para ellos. Tu límite puede ser diferente, así que ajusta de acuerdo a tus necesidades. + - Crea carpetas llamadas de acuerdo al característica que representan. Cuando una carpeta crezca para contener más de 7 archivos, comienza a considerar la creación de una carpeta para ellos. Tu límite puede ser diferente, así que ajusta de acuerdo a tus necesidades. *¿Por qué?*: Un desarrollador puede localizar el código, identificar cada qué representa cada archivo de un vistazo, la estructura es tan plana como puede ser, y no hay nombres repetidos o redundantes. @@ -2124,7 +2124,7 @@ Mientras que esta guía explica el *qué*, *por qué* y *cómo*, me resulta úti *¿Por qué?*: Ayuda a evitar que la aplicación se sature a través de organizar el contenido y conservarlo alineado con las pautas LIFT. - *¿Por qué?*: Cuando hay demasiados archivos (10+) localizarlos es más fácil con una estructura de directorios consistente y más díficiles en una estructura plana. + *¿Por qué?*: Cuando hay demasiados archivos (10+) localizarlos es más fácil con una estructura de directorios consistente y más difíciles en una estructura plana. ```javascript /** @@ -2166,13 +2166,13 @@ Mientras que esta guía explica el *qué*, *por qué* y *cómo*, me resulta úti ![Sample App Structure](https://raw.githubusercontent.com/johnpapa/angularjs-styleguide/master/assets/modularity-2.png) - Nota: No estructures tu aplicación usando directorios-por-tipo. Esto require mover múltiples directorios cuando se está trabajando en una feature y se vuelve díficil de manejar conforme la aplicación crece a 5, 10 o 25+ vistas y controladores (y otras features), lo que lo hace más díficil que localizar archivos en una aplicación estructura en directorios-por-feature. + Nota: No estructures tu aplicación usando directorios-por-tipo. Esto requiere mover múltiples directorios cuando se está trabajando en una característica y se vuelve difícil de manejar conforme la aplicación crece a 5, 10 o 25+ vistas y controladores (y otras características), lo que lo hace más difícil que localizar archivos en una aplicación estructura en directorios-por-característica. ```javascript /* * evita * Alternativa directorios-por-tipo - * Yo recomiendo "directorios-por-feature", en su lugar. + * Yo recomiendo "directorios-por-característica", en su lugar. */ app/ @@ -2216,60 +2216,60 @@ Mientras que esta guía explica el *qué*, *por qué* y *cómo*, me resulta úti - Crea módulos pequeños que encapsulen una responsabilidad. - *¿Por qué?*: Aplicaciones modulares hace más fácil el plug and go ya que permiten a los equipos de desarrollo construir porciones verticales de la aplicación y lanzarlas incrementalmente. Esto significa que podemos conectar nuevas features conforme las desarrollamos. + *¿Por qué?*: Aplicaciones modulares hace más fácil el plug and go ya que permiten a los equipos de desarrollo construir porciones verticales de la aplicación y lanzarlas incrementalmente. Esto significa que podemos conectar nuevas características conforme las desarrollamos. ### Crea un Módulo App ###### [Style [Y161](#style-y161)] - - Crea una módulo raíz de aplicación cuyo rol sea unir todos los módulos y features de tu aplicación. Nombra éste de acuerdo a tu aplicación. + - Crea una módulo raíz de aplicación cuyo rol sea unir todos los módulos y características de tu aplicación. Nombra éste de acuerdo a tu aplicación. *¿Por qué?*: AngularJS incentiva la modularidad y patrones de separación. Crear un módulo raíz de aplicación cuyo rol es atar otros módulos juntos provee una manera muy directa de agregar o remover módulos de tu aplicación. ### Mantén el Módulo App Delgado ###### [Style [Y162](#style-y162)] - - Solo coloca lógica para unir la aplicación en el módulo app. Deja las features en sus propios módulos. + - Solo coloca lógica para unir la aplicación en el módulo app. Deja las características en sus propios módulos. - *¿Por qué?*: Agregar roles adicionales a la aplicación raíz para obtener datos remotos, mostrar vistas, u otra lógica no relaciona a la unión de la aplicación enturbia el módulo app y hace ambos conjuntos de features díficles de reusar y apagar. + *¿Por qué?*: Agregar roles adicionales a la aplicación raíz para obtener datos remotos, mostrar vistas, u otra lógica no relaciona a la unión de la aplicación enturbia el módulo app y hace ambos conjuntos de características difíciles de reusar y apagar. *¿Por qué?*: El módulo app se convierte en el manifiesto que describe qué módulos definen la aplicación. ### Áreas de Features son Módulos ###### [Style [Y163](#style-y163)] - - Crea módulos que representen áreas de features, como el layout, servicios reusables y compartidos, dashboards, y features específicos de la aplicación (e.g. customers, admin, sales). + - Crea módulos que representen áreas de características, como el layout, servicios reusables y compartidos, dashboards, y características específicás de la aplicación (e.g. customers, admin, sales). *¿Por qué?*: Módulos autocontenidos pueden ser agregados a la aplicación con poca o sin ninguna fricción. - *¿Por qué?*: Sprints o iteraciones pueden enfocarse en áreas de features y encendarlas al final del sprint o iteración. + *¿Por qué?*: Sprints o iteraciones pueden enfocarse en áreas de características y encendarlas al final del sprint o iteración. - *¿Por qué?*: Separar áreas de features en módulos hace más fácil testear módulos en aislamiento y reusar código. + *¿Por qué?*: Separar áreas de características en módulos hace más fácil testear módulos en aislamiento y reusar código. ### Bloques Reusables son Módulos ###### [Style [Y164](#style-y164)] - Crea módulos que representen bloques de la aplicación reusables para servicios cómunes como manejo de excepciones, logeo, diagnóstico, seguridad, y almacenamiento local de datos. - *¿Por qué?*: Este tipo de features son necesarias en muchas aplicaciones, así que mantenerlas separadas en sus propios módulos pueden ser genéricas de aplicación y pueden ser reusadas a lo largo de varias aplicaciones. + *¿Por qué?*: Este tipo de características son necesarias en muchas aplicaciones, así que mantenerlas separadas en sus propios módulos pueden ser genéricas de aplicación y pueden ser reusadas a lo largo de varias aplicaciones. ### Dependencias de Módulos ###### [Style [Y165](#style-y165)] - - El módulo raíz de la aplicación depende de módulos de features específicos y cualquier módulo compartido o reusable. + - El módulo raíz de la aplicación depende de módulos de características específicas y cualquier módulo compartido o reusable. ![Modularity and Dependencies](https://raw.githubusercontent.com/johnpapa/angularjs-styleguide/master/assets/modularity-1.png) - *¿Por qué?*: El módulo principal de la aplicación contiene un manifiesto rápidamente identificable de las features de la aplicación. + *¿Por qué?*: El módulo principal de la aplicación contiene un manifiesto rápidamente identificable de las características de la aplicación. - *¿Por qué?*: Cada área de feature contiene un manifiesto de lo que depende, así que puede ser extraído como dependecia en otras aplicaciones y seguir funcionando. + *¿Por qué?*: Cada área de características contiene un manifiesto de lo que depende, así que puede ser extraído como dependencia en otras aplicaciones y seguir funcionando. - *¿Por qué?*: Features internas de la aplicación como servicios de datos compartidos se hacen fácil de localizar y compartir desde `app.core` (elije tu nombre favorito para este módulo). + *¿Por qué?*: Características internas de la aplicación como servicios de datos compartidos se hacen fácil de localizar y compartir desde `app.core` (elije tu nombre favorito para este módulo). - Nota: Esta es una estrategia para consistencia. Hay muy buenas opciones aquí. Escoje una que sea consistente, que siga las reglas de dependencias de AngularJS, y que sea fácil de mantener y escalar. + Nota: Esta es una estrategia para consistencia. Hay muy buenas opciones aquí. Escoge una que sea consistente, que siga las reglas de dependencias de AngularJS, y que sea fácil de mantener y escalar. - > Mis estructuras varian ligeramente entre proyetos pero todas ellas siguen estas pautas para estructuras y modularidad. La implementación puede variar dependiendo de las features y el equipo. En otras palabras, no te quedes colgado en una estructura igual pero justifica tu estructura usando consistencia, mantenibilidad, y eficacia en mente. + > Mis estructuras varían ligeramente entre proyectos pero todas ellas siguen estas pautas para estructuras y modularidad. La implementación puede variar dependiendo de las características y el equipo. En otras palabras, no te quedes colgado en una estructura igual pero justifica tu estructura usando consistencia, mantenibilidad, y eficacia en mente. - > En una aplicación pequeña, también puedes considerar poner todas las dependencias compartidas en el módulo principal dónde los módulos de features no tienen dependencias directas. Esto hace más fácil mantener aplicaciones pequeñas, pero hace más díficil el reusar módulos fuera de esta aplicación. + > En una aplicación pequeña, también puedes considerar poner todas las dependencias compartidas en el módulo principal dónde los módulos de características no tienen dependencias directas. Esto hace más fácil mantener aplicaciones pequeñas, pero hace más difícil el reusar módulos fuera de esta aplicación. **[Volver arriba](#tabla-de-contenidos)** @@ -2310,9 +2310,9 @@ Mientras que esta guía explica el *qué*, *por qué* y *cómo*, me resulta úti ### Bloques Run ###### [Style [Y171](#style-y171)] - - Cualquier código que necesite ser ejecutado cuando una aplicación arranca debe ser declarado en una factory, ser expuesto a través de una función, o inyectado en el [bloque run](https://docs.angularjs.org/guide/module#module-loading-dependencies). + - Cualquier código que necesite ser ejecutado cuando una aplicación arranca debe ser declarado en una fábrica, ser expuesto a través de una función, o inyectado en el [bloque run](https://docs.angularjs.org/guide/module#module-loading-dependencies). - *¿Por qué?*: Código que está directamente en un bloque run puede ser díficil de testear. Colocarlo en una factory lo hace fácil de abstraer y mockear. + *¿Por qué?*: Código que está directamente en un bloque run puede ser difícil de testear. Colocarlo en una fábrica lo hace fácil de abstraer y mockear. ```javascript angular @@ -2382,9 +2382,9 @@ Las pruebas unitarias ayudan a mantener el código limpio, así que incluyo algu - Usa [Jasmine](http://jasmine.github.io/) o [Mocha](http://mochajs.org) para las pruebas unitarias. - *¿Por qué?*: Ambas Jasmine y Mocha son usadas ampliamente por la comunidad de AngularJS. Ambas son estables, bien mantenidas, y proveen de features de pruebas robustas. + *¿Por qué?*: Ambas Jasmine y Mocha son usadas ampliamente por la comunidad de AngularJS. Ambas son estables, bien mantenidas, y proveen de características de pruebas robustas. - Nota: When using Mocha, also consider choosing an assert library such as [Chai](http://chaijs.com). + Nota: Cuando uses Mocha, también considera elegir una librería como [Chai](http://chaijs.com). ### Test Runner ###### [Style [Y192](#style-y192)] @@ -2404,7 +2404,7 @@ Las pruebas unitarias ayudan a mantener el código limpio, así que incluyo algu - Usa [Sinon](http://sinonjs.org/) para el stubeo y espíar. - *¿Por qué?*: Sinon funciona bien con ambos Jasmine y Mocha y extiende las features de stubeo y espío que ellos ofrecen. + *¿Por qué?*: Sinon funciona bien con ambos Jasmine y Mocha y extiende las características de stubeo y espío que ellos ofrecen. *¿Por qué?*: Sinon hace más fácil cambiar entre Jasmine y Mocha, si quieres probar ambos. @@ -2413,7 +2413,7 @@ Las pruebas unitarias ayudan a mantener el código limpio, así que incluyo algu - Usa [PhantomJS](http://phantomjs.org/) para correr tus pruebas en un servidor. - *¿Por qué?*: PhantomJS es un navegador headless que ayuda a correr las pruebas necesitar una navegador "visual". Así que no necistas instalar Chrom, Safari u otros navegadores en tu servidor. + *¿Por qué?*: PhantomJS es un navegador headless que ayuda a correr las pruebas necesitar una navegador "visual". Así que no necesitas instalar Chrom, Safari u otros navegadores en tu servidor. Nota: Aún debes testear en todos los navegadores de tu entorno, así como sea apropiado para tu audiencia meta. @@ -2471,18 +2471,18 @@ Las pruebas unitarias ayudan a mantener el código limpio, así que incluyo algu ### Uso ###### [Style [Y210](#style-y210)] - - Usa sutiles [animaciones con AngularJS](https://docs.angularjs.org/guide/animations) para transicionar entre estados en vistas y elementos visuales primarios. Incluye el [módulo ngAnimate](https://docs.angularjs.org/api/ngAnimate). Las 3 claves son sutil, fluido, transparente. + - Usa sutiles [animaciones con AngularJS](https://docs.angularjs.org/guide/animations) para hacer transiciones entre estados en vistas y elementos visuales primarios. Incluye el [módulo ngAnimate](https://docs.angularjs.org/api/ngAnimate). Las 3 claves son sutil, fluido, transparente. *¿Por qué?*: Animaciones sutiles pueden mejorar la Experiencia de Usuario cuando son usadas apropiadamente. - *¿Por qué?*: Animaciones sutiles pueden mejorar el performance percibido como una transición de vista. + *¿Por qué?*: Animaciones sutiles pueden mejorar el rendimiento percibido como una transición de vista. ### Sub Segundos ###### [Style [Y211](#style-y211)] - Usa duraciones cortas para las animaciones. Yo generalmente empiezo con 300ms y ajusto hasta que es apropiado. - *¿Por qué?*: Animaciones largas pueden tener el efecto contrario en la Experiencia de Usuario y el performance percibido al dar la apariencia de una aplicación lenta. + *¿Por qué?*: Animaciones largas pueden tener el efecto contrario en la Experiencia de Usuario y el rendimiento percibido al dar la apariencia de una aplicación lenta. ### animate.css ###### [Style [Y212](#style-y212)] @@ -2508,7 +2508,7 @@ Las pruebas unitarias ayudan a mantener el código limpio, así que incluyo algu *¿Por qué?*: Puedes generar (y regenerar) documentación desde tu código, en lugar de escribirla desde cero. - *¿Por qué?*: Provee consistencia al usar una herramienta industrial cómun. + *¿Por qué?*: Provee consistencia al usar una herramienta industrial común. ```javascript /** @@ -2558,7 +2558,7 @@ Las pruebas unitarias ayudan a mantener el código limpio, así que incluyo algu - Usa JS Hint para resaltar problemas en tu JavaScript y asegurate de personalizar el arhivo de opciones de JS Hint e incluirlo en el control de versiones. Ve los [JS Hint docs](http://www.jshint.com/docs/) para detalles sobre estas opciones. - *¿Por qué?*: Provee una primera alerta antes de commitear cualquire código al control de versiones. + *¿Por qué?*: Provee una primera alerta antes de hacer commit de cualquier código al control de versiones. *¿Por qué?*: Provee consistencia a lo largo de tu equipo. @@ -2655,11 +2655,11 @@ Las pruebas unitarias ayudan a mantener el código limpio, así que incluyo algu - Usa constantes para valores que no cambian y no vienen de otro servicio. Cuando las constantes son usadas solo por para un módulo que pueda ser reutilizado en múltiples aplicaciones, coloca las constantes en un archivo por módulo nombrado a partir del módulo. Hasta que esto sea requerido, mantén las constantes en el módulo principal en un archivo `constants.js`. - *¿Por qué?*: Un valor que puede cambiar, incluso infrecuentemente, debería ser obtenido desde un servicio así no tendrás que cambiar el código fuente. Por ejemplo, una url para un data service puede ser colocada en una constante pero un mejor lugar sería cargarla desde un servicio web. + *¿Por qué?*: Un valor que puede cambiar, incluso infrecuentemente, debería ser obtenido desde un servicio así no tendrás que cambiar el código fuente. Por ejemplo, una url para un servicio de datos puede ser colocada en una constante pero un mejor lugar sería cargarla desde un servicio web. - *¿Por qué?*: Las Constantes pueden ser inyectadas en cualquire componente de angular, incluyendo providers. + *¿Por qué?*: Las Constantes pueden ser inyectadas en cualquier componente de angular, incluyendo providers. - *¿Por qué?*: Cuando una aplicación es separada en módulos que pueden ser reutilizados en otras aplicaciones, cada módulo autónomo debería ser capaz de operar por sí mismo incluyendo cualquer constante de la cual dependa. + *¿Por qué?*: Cuando una aplicación es separada en módulos que pueden ser reutilizados en otras aplicaciones, cada módulo autónomo debería ser capaz de operar por sí mismo incluyendo cualquier constante de la cual dependa. ```javascript // Constantes usadas por la aplicación entera @@ -2752,14 +2752,14 @@ Puedes usar el [generador de yeoman HotTowel](http://jpapa.me/yohottowel) para c **[Volver arriba](#tabla-de-contenidos)** -## Ruteo -Ruteo del lado del Cliente es importante para crear un flujo de navegación entre vistas y vistas de composición que están hechas de muchas pequeñas plantillas y directivas. +## Enrutamiento +Enrutamiento del lado del Cliente es importante para crear un flujo de navegación entre vistas y vistas de composición que están hechas de muchas pequeñas plantillas y directivas. ###### [Style [Y270](#style-y270)] - Usa el [AngularUI Router](http://angular-ui.github.io/ui-router/) para ruteo del lado del cliente. - *¿Por qué?*: UI Router ofrece todas las features del router de Angular mas algunas adicionales allincluyendo rutas anidadas the f y estados. + *¿Por qué?*: UI Router ofrece todas las características del router de Angular mas algunas adicionales incluyendo rutas anidadas y estados. *¿Por qué?*: La sintaxis es bastante similar al router de Angular y es fácil de migrar al UI Router. From 110dba97a669abd42d2bfdbed9ac5d7bb94d849d Mon Sep 17 00:00:00 2001 From: angelochiello Date: Thu, 2 Apr 2015 12:46:57 +0200 Subject: [PATCH 268/567] [it-IT] PR #356 Updated as PR: #356 "typo" --- i18n/it-IT.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/i18n/it-IT.md b/i18n/it-IT.md index d7c826e5..c8fd2d58 100644 --- a/i18n/it-IT.md +++ b/i18n/it-IT.md @@ -368,7 +368,7 @@ Nonostante questa guida spieghi i *cosa*, *come* e *perché*, trovo che sia di a } ``` - Nota: Puoi evitare ogni warning di [jshint](http://www.jshint.com/) ponendo il commento sotto riportato al di sopra della linea di codice. + Nota: Puoi evitare ogni warning di [jshint](http://www.jshint.com/) ponendo il commento sotto riportato al di sopra della linea di codice. Comunque ciò non è richiesto quando la funzione è nominata usando le Maiuscole, la convenzione è intesa come la funzione costruttore che è ciò che un controller è in Angular. ```javascript /* jshint validthis: true */ From 3a7f7904d45172164bf516aa2e20f225f9d78120 Mon Sep 17 00:00:00 2001 From: Aleksandar Bogatinov Date: Mon, 6 Apr 2015 10:17:43 +0200 Subject: [PATCH 269/567] Updated to latest version -translated new Brackets section -added references to snippets -translated typos --- i18n/mk-MK.md | 215 +++++++++++++++++++++++++++++++------------------- 1 file changed, 136 insertions(+), 79 deletions(-) diff --git a/i18n/mk-MK.md b/i18n/mk-MK.md index 76cc547e..6a06ba07 100644 --- a/i18n/mk-MK.md +++ b/i18n/mk-MK.md @@ -69,28 +69,28 @@ - Дефинирај 1 компонента во датотека. - Следниот пример го дефинира `app` модулот и неговите зависности, дефинира контролер, и дефинира фабрика, сé во една датотека + Следниот пример го дефинира `app` модулот и неговите зависности, дефинира контролер, и дефинира фабрика, сé во една датотека ```javascript /* избегнувајте */ angular - .module('app', ['ngRoute']) - .controller('someController', someController) - .factory('someFactory', someFactory); - + .module('app', ['ngRoute']) + .controller('someController', someController) + .factory('someFactory', someFactory); + function SomeController() { } function someFactory() { } ``` - Истите компоненти сега се разделени во свои датотеки. + Истите компоненти сега се разделени во свои датотеки. ```javascript /* препорачано */ // app.module.js angular - .module('app', ['ngRoute']); + .module('app', ['ngRoute']); ``` ```javascript @@ -98,8 +98,8 @@ // someController.js angular - .module('app') - .controller('SomeController', SomeController); + .module('app') + .controller('SomeController', SomeController); function SomeController() { } ``` @@ -109,9 +109,9 @@ // someFactory.js angular - .module('app') - .factory('someFactory', someFactory); - + .module('app') + .factory('someFactory', someFactory); + function someFactory() { } ``` @@ -194,7 +194,7 @@ ###### [Style [Y021](#style-Y021)] - Декларирај модули без променлива користејќи ја setter синтаксата. - *Зошто?*: Со 1 компонента во датотека, реткост е да поставиш нова променлива во модулот. + *Зошто?*: Со 1 компонента во датотека, реткост е да поставиш нова променлива во модулот. ```javascript /* избегнувајте*/ @@ -206,12 +206,12 @@ ]); ``` - Наместо тоа, употреби ја едноставната setter синтакса. + Наместо тоа, употреби ја едноставната setter синтакса. ```javascript /* препорачано */ angular - .module('app', [ + .module('app', [ 'ngAnimate', 'ngRoute', 'app.shared', @@ -223,7 +223,7 @@ ###### [Style [Y022](#style-Y022)] - Кога употребувате модул, избегнувајте користење на променливa. Наместо тоа употребете врзување со getter синтакса. - *Зошто?* : Ова создава читлив код и избегнува судири на променливи или протекувања. + *Зошто?* : Ова создава читлив код и избегнува судири на променливи или протекувања. ```javascript /* избегнувајте */ @@ -245,17 +245,17 @@ ### Setting vs Getting ###### [Style [Y023](#style-Y023)] - Само еднаш создади и земај го за сите други инстанци. - - *Зошто?*: Модул треба еднаш да биде создаден, и од тој момент да биде само превземен. - - - Употреби `angular.module('app', []);` за да создадеш модул. - - Употреби `angular.module('app');` за да го превземеш тој модул. + + *Зошто?*: Модул треба еднаш да биде создаден, и од тој момент да биде само превземен. + + - Употреби `angular.module('app', []);` за да создадеш модул. + - Употреби `angular.module('app');` за да го превземеш тој модул. ### Именувани vs Анонимни функции ###### [Style [Y024](#style-Y024)] - Употреби именувани функции наместо да проследиш анонимни функции како повратни повици (callback). - *Зошто?*: Ова создава читлив код, кој е полесен за дебагирање и го намалува бројот на вгнездени повратни повици. + *Зошто?*: Ова создава читлив код, кој е полесен за дебагирање и го намалува бројот на вгнездени повратни повици. ```javascript /* избегнувајте */ @@ -293,11 +293,11 @@ ###### [Style [Y030](#style-Y030)] - Употреби ја [`controllerAs`](http://www.johnpapa.net/do-you-like-your-angular-controllers-with-or-without-sugar/) синтаксата наместо `класичниот контролер со $scope` синтакса. - *Зошто?*: Контролерите се создаваат, се ажурираат и потоа се пристапуваат преку единствена нова инстанца. `controllerAs` синтаксата е поблиску до JavaScript конструктор наспроти `класичната $scope синтакса`. + *Зошто?*: Контролерите се создаваат, се ажурираат и потоа се пристапуваат преку единствена нова инстанца. `controllerAs` синтаксата е поблиску до JavaScript конструктор наспроти `класичната $scope синтакса`. *Зошто?*: Го промовира користењето на "dotted" објект во Прегледот (на пример `customer.name` наместо `name`), што е поконтекстуално, полесно за читање и избегнува проблеми со референцирање кои може да се појават без "dotting". - *Зошто?*: Помага при избегнување на `$parent` повици во Прегледи со вгнездени контролери. + *Зошто?*: Помага при избегнување на `$parent` повици во Прегледи со вгнездени контролери. ```html @@ -589,8 +589,8 @@ function checkCredit() { return creditService.isOrderTotalOk(vm.total) - .then(function(isOk) { vm.isCreditOk = isOk; }) - .catch(showServiceError); + .then(function(isOk) { vm.isCreditOk = isOk; }) + .catch(showServiceError); }; }; } @@ -1047,7 +1047,7 @@ /* customerInfo.directive.js */ /** - * @desc spinner директива која може да се користи низ апликацијата во компанијата Acme + * @desc sales директива која може да се користи низ апликацијата во компанијата Acme * @пример
*/ angular @@ -1076,7 +1076,7 @@ } ``` - Забелешка: Постојат повеќе начини на именување на директиви, посебно што можат да се искористат во широк или краток обем. Одлучете се за еден кој ја прави директивата и нејзиното име јасно и различно. Има неколку примери подоле, но посоветувајте се до секцијата за именување. + Забелешка: Постојат повеќе начини на именување на директиви, посебно што можат да се искористат во широк или краток обем. Одлучете се за еден кој ја прави директивата и нејзиното име јасно и различно. Има неколку примери подоле, но посоветувајте се до секцијата за [именување](#naming). ### Манипулирајте DOM во директивата ###### [Style [Y072](#style-Y072)] @@ -1208,7 +1208,7 @@ console.log('CTRL: $scope.vm.max = %s', $scope.vm.max); console.log('CTRL: vm.min = %s', vm.min); console.log('CTRL: vm.max = %s', vm.max); - } + } ``` ```html @@ -1218,6 +1218,19 @@
min={{vm.min}}
``` + Забелешка: Можете исто така да го именувате Контролерот кога ќе го вметнете во link функција и пристапите до атрибутите на директивата како својства на контролерот. + + ```javascript + // Алтернатива за примерот горе + function linkFunc(scope, el, attr, vm) { + console.log('LINK: scope.min = %s *** should be undefined', scope.min); + console.log('LINK: scope.max = %s *** should be undefined', scope.max); + console.log('LINK: vm.min = %s', vm.min); + console.log('LINK: vm.max = %s', vm.max); + } + ``` + + ###### [Style [Y076](#style-y076)] - Употребете `bindToController = true` кога употребувате `controller as` синтакса со директива чиј scope на контролерот ќе биде поврзан со надворешниот scope. @@ -1243,8 +1256,8 @@ max: '=' }, controller: ExampleController, - controllerAs: 'vm', - bindToController: true + controllerAs: 'vm', + bindToController: true }; return directive; @@ -1376,43 +1389,43 @@ } ``` - Забелешка: Примерот подоле покажува како решавање на патеката покажува кон именувана функција, која е полесна за дебагирање и полесно справување со вклучување на зависностите. - - ```javascript - /* уште подобро */ - - // route-config.js - angular - .module('app') - .config(config); - - function config($routeProvider) { - $routeProvider - .when('/avengers', { - templateUrl: 'avengers.html', - controller: 'Avengers', - controllerAs: 'vm', - resolve: { - moviesPrepService: moviesPrepService - } - }); - } - - function moviePrepService(movieService) { - return movieService.getMovies(); - } - - // avengers.js - angular - .module('app') - .controller('Avengers', Avengers); - - Avengers.$inject = ['moviesPrepService']; - function Avengers(moviesPrepService) { - var vm = this; - vm.movies = moviesPrepService.movies; - } - ``` + Забелешка: Примерот подоле покажува како решавање на патеката покажува кон именувана функција, која е полесна за дебагирање и полесно справување со вклучување на зависностите. + + ```javascript + /* уште подобро */ + + // route-config.js + angular + .module('app') + .config(config); + + function config($routeProvider) { + $routeProvider + .when('/avengers', { + templateUrl: 'avengers.html', + controller: 'Avengers', + controllerAs: 'vm', + resolve: { + moviesPrepService: moviesPrepService + } + }); + } + + function moviePrepService(movieService) { + return movieService.getMovies(); + } + + // avengers.js + angular + .module('app') + .controller('Avengers', Avengers); + + Avengers.$inject = ['moviesPrepService']; + function Avengers(moviesPrepService) { + var vm = this; + vm.movies = moviesPrepService.movies; + } + ``` Забелешка: Примерот на `movieService` не е безбеден за минификација. За детали како да го направите безбеден за минификација, прегледајте ги секциите за [dependency injection](#manual-annotating-for-dependency-injection) и [minification and annotation](#minification-and-annotation). @@ -1669,7 +1682,7 @@ Забелешка: Друга опција е да се прескокне сервисот наместо да се користи декоратор. Ова е добра опција, но доколку сакате да го задржите стандардното однесување и проширите, тогаш препорачливо е да користите декоратор. - ```javascript + ```javascript /* препорачано */ angular .module('blocks.exception') @@ -1699,7 +1712,7 @@ toastr.error(exception.msg, errorData); }; } - ``` + ``` ### Ловци на исклучоци ###### [Style [Y111](#style-Y111)] @@ -1754,10 +1767,10 @@ if (handlingRouteChangeError) { return; } handlingRouteChangeError = true; var destination = (current && (current.title || - current.name || current.loadedTemplateUrl)) || - 'unknown target'; + current.name || current.loadedTemplateUrl)) || + 'unknown target'; var msg = 'Error routing to ' + destination + '. ' + - (rejection.msg || ''); + (rejection.msg || ''); /** * Опционално логирајте со рачно изработен сервис или $log. * (Не заборавајте да го вклучите рачно изработениот сервис) @@ -1913,10 +1926,12 @@ ### Имиња на фабрики ###### [Style [Y125](#style-Y125)] - - Употребете конзистентни имиња за сите фабрики според нивната функција. Употребете camel-casing за сервиси и фабрики. + - Употребете конзистентни имиња за сите фабрики според нивната функција. Употребете camel-casing за сервиси и фабрики. Избегнувајте префикси на фабрики и сервиси со `$`. *Зошто?*: Обезбедува конзистентен начин за брзо препознавање и референцирање фабрики. + *Зошто?*: Избегнува судири со имиња на вградени фабрики и сервиси кои го користат `$` префиксот. + ```javascript /** * препорачано @@ -2687,16 +2702,21 @@ angular ###### [Style [Y250](#style-Y250)] - Angular кратки кодови кои ги следат овие водичи и стилови на код. - - Симнете ги [Sublime Angular кратки кодови](assets/sublime-angular-snippets.zip?raw=true) + - Симнете ги [Sublime Angular кратки кодови](assets/sublime-angular-snippets?raw=true) - Поставете ги во вашата Packages папка - Рестартирајте го Sublime - Во JavaScript датотека напишете ја следната команда и потоа кликнете на `TAB` ```javascript ngcontroller // создава Angular контролер - ngdirective // создава Angular директива - ngfactory // создава Angular фабрика - ngmodule // создава Angular модул + ngdirective // создава Angular директива + ngfactory // создава Angular фабрика + ngmodule // создава Angular модул + ngdirective // создава Angular директива + ngfactory // создава Angular фабрика + ngmodule // создава Angular модул + ngservice // создава Angular сервис + ngfilter // создава Angular филтер ``` ### Visual Studio @@ -2744,10 +2764,47 @@ angular ngdirective // создава Angular директива ngfactory // создава Angular фабрика ngmodule // создава Angular модул + ngservice // создава Angular сервис + ngfilter // создава Angular филтер ``` **[Назад кон содржината](#table-of-contents)** +### Brackets +###### [Style [Y254](#style-y254)] + + - Angular програмки кои ги следат овие стилови и водичи. + + - Симнете [Brackets Angular програмки](assets/brackets-angular-snippets.yaml?raw=true) + - Brackets менаџер за екстензии ( File > Extension manager ) + - Инсталирајте ['Brackets Snippets (од edc)'](https://github.com/chuyik/brackets-snippets) + - Кликнете на сијалицата во десниот дел од brackets + - Кликнете на `Settings` и потоа `Import` + - Одберете датотека и одберете skip или override + - Кликнете `Start Import` + + - Во JavaScript датотека напишете ги овие команди следејќи го `TAB` + + ```javascript + // Овие се целосни програмки кои содржат IIFE + ngcontroller // создава Angular контролер + ngdirective // создава Angular директива + ngfactory // создава Angular фабрика + ngapp // создава Angular поставувач за модул + ngservice // создава Angular сервис + ngfilter // создава Angular филтер + + // Овие се парцијални програмки наменети за врзување + ngmodule // создава Angular земач на модули + ngstate // создава Angular UI Router дефиниција на состојба + ngconfig // дефинира configuration phase функција + ngrun // дефинира run phase функција + ngroute // дефинира Angular ngRoute 'when' дефиниција + ngtranslate // употребува $translate сервисот заедно со неговиот promise + ``` + + **[Назад кон содржината](#table-of-contents)** + ## Yeoman Generator ###### [Style [Y260](#style-y260)] @@ -2875,4 +2932,4 @@ 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. -**[Назад кон содржината](#table-of-contents)** +**[Назад кон содржината](#table-of-contents)** \ No newline at end of file From 88659fdeff1b8ee43b52eac2ec5ce46a3787e55b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=B5=B5=E5=8F=AF?= Date: Mon, 6 Apr 2015 22:06:50 +0800 Subject: [PATCH 270/567] optimize transition --- README.md | 22 +- i18n/zh-CN.md | 1250 ++++++++++++++++++++++++++----------------------- 2 files changed, 678 insertions(+), 594 deletions(-) diff --git a/README.md b/README.md index e5a2e9a8..e4efacf6 100644 --- a/README.md +++ b/README.md @@ -898,7 +898,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see *Why?*: This makes it easier to test (mock or real) the data calls when testing a controller that uses a data service. - *Why?*: Data service implementation may have very specific code to handle the data repository. This may include headers, how to talk to the data, or other services such as $http. Separating the logic into a data service encapsulates this logic in a single place hiding the implementation from the outside consumers (perhaps a controller), also making it easier to change the implementation. + *Why?*: Data service implementation may have very specific code to handle the data repository. This may include headers, how to talk to the data, or other services such as `$http`. Separating the logic into a data service encapsulates this logic in a single place hiding the implementation from the outside consumers (perhaps a controller), also making it easier to change the implementation. ```javascript /* recommended */ @@ -1010,7 +1010,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see } ``` - **[Back to top](#table-of-contents)** +**[Back to top](#table-of-contents)** ## Directives ### Limit 1 Per File @@ -1022,7 +1022,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see *Why?*: One directive per file is easy to maintain. - > Note: "**Best Practice**: Directives should clean up after themselves. You can use `element.on('$destroy', ...)` or `scope.$on('$destroy', ...)` to run a clean-up function when the directive is removed" ... from the Angular documentation + > Note: "**Best Practice**: Directives should clean up after themselves. You can use `element.on('$destroy', ...)` or `scope.$on('$destroy', ...)` to run a clean-up function when the directive is removed" ... from the Angular documentation. ```javascript /* avoid */ @@ -1313,7 +1313,6 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see **[Back to top](#table-of-contents)** ## Resolving Promises for a Controller - ### Controller Activation Promises ###### [Style [Y080](#style-y080)] @@ -1418,8 +1417,8 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see Avengers.$inject = ['moviesPrepService']; function Avengers(moviesPrepService) { - var vm = this; - vm.movies = moviesPrepService.movies; + var vm = this; + vm.movies = moviesPrepService.movies; } ``` @@ -2188,6 +2187,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see app.module.js app.config.js app.routes.js + directives.js controllers/ attendees.js session-detail.js @@ -2328,12 +2328,12 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see .module('app') .run(runBlock); - runBlock.$inject = ['authenticator', 'translator']; + runBlock.$inject = ['authenticator', 'translator']; - function runBlock(authenticator, translator) { - authenticator.initialize(); - translator.initialize(); - } + function runBlock(authenticator, translator) { + authenticator.initialize(); + translator.initialize(); + } ``` **[Back to top](#table-of-contents)** diff --git a/i18n/zh-CN.md b/i18n/zh-CN.md index 39b41dbe..8e72ffe1 100644 --- a/i18n/zh-CN.md +++ b/i18n/zh-CN.md @@ -6,16 +6,16 @@ >The [original English version](http://jpapa.me/ngstyles) is the source of truth, as it is maintained and updated first. -如果你正在寻找一些关于语法、约定和结构化的Angular应用的一个有建设性的风格指南,这个repo正适合你。这里所包含的风格是基于我在团队中使用[Angular](//angularjs.org)的一些经验、一些演讲和[Pluralsight培训课程](http://pluralsight.com/training/Authors/Details/john-papa)。 +如果你正在寻找一些关于语法、约定和结构化的Angular应用的一个有建设性的风格指南,那么你来对地方了。这里所包含的风格是基于我在团队中使用[Angular](//angularjs.org)的一些经验、一些演讲和[Pluralsight培训课程](http://pluralsight.com/training/Authors/Details/john-papa)。 这个风格指南的目的是为构建Angular应用提供指导,当然更加重要的是让大家知道我为什么要选择它们。 ->如果你喜欢这个指南,请在Pluralsight上检出我的[Angular Patterns: Clean Code](http://jpapa.me/ngclean)。 +>如果你喜欢这个指南,请在Pluralsight看看[Angular Patterns: Clean Code](http://jpapa.me/ngclean)。 [![Angular Patterns: Clean Code](https://raw.githubusercontent.com/johnpapa/angular-styleguide/master/assets/ng-clean-code-banner.png)](http://jpapa.me/ngclean) ## Community Awesomeness and Credit -我发现Angular社区是一个热衷于分享经验的令人难以置信的社区,尽管Todd Motto(他是我的一个朋友,也是Angular专家)和我合作了多种风格和惯例,但是我们也存在着一些分歧。我鼓励你去看看[Todd的指南](https://github.com/toddmotto/angularjs-styleguide),从其中了解他的做法和它们是如何比较的。 +Angular社区是一个热衷于分享经验的令人难以置信的社区,尽管Todd Motto(他是我的一个朋友,也是Angular专家)和我合作了多种风格和惯例,但是我们也存在着一些分歧。我鼓励你去看看[Todd的指南](https://github.com/toddmotto/angularjs-styleguide),在那里你能看到我们之间的区别。 我的许多风格都是从大量的程序会话[Ward Bell](http://twitter.com/wardbell)和我所拥有的而来的,我的好友Ward也影响了本指南的最终演变。 @@ -26,7 +26,6 @@ [Angular风格指南翻译版本](https://github.com/johnpapa/angular-styleguide/tree/master/i18n)。 ##目录 - 1. [单一职责](#单一职责) 1. [IIFE](#iife) 1. [Modules](#modules) @@ -61,15 +60,14 @@ 1. [许可](#许可) ## 单一职责 - ###规则一 ###### [Style [Y001](#style-y001)] - - 一个文件只定义一个组件。 + - 一个文件只定义一个组件。 - 下面的一个例子在同一个文件中定义了一个`app`的module和它的一些依赖、一个controller和一个factory。 + 下面的例子在同一个文件中定义了一个`app`的module和它的一些依赖、一个controller和一个factory。 - ```javascript + ```javascript /* avoid */ angular .module('app', ['ngRoute']) @@ -81,8 +79,7 @@ function someFactory() { } ``` - 现在把相同的组件分割成单独的文件。 - + 推荐以下面的方式来做,把上面相同的组件分割成单独的文件。 ```javascript /* recommended */ @@ -104,7 +101,6 @@ ```javascript /* recommended */ - // someFactory.js angular .module('app') @@ -123,7 +119,7 @@ *为什么?*:把变量从全局作用域中删除了,这有助于防止变量和函数声明比预期在全局作用域中有更长的生命周期,也有助于避免变量冲突。 - *为什么?*:当你的代码为了发布而压缩了并且被合并到同一个文件中时,可能会有变量和很多全局变量的冲突,IIFE通过给每一个文件提供一个单独的作用域来保护你免受这些困扰。 + *为什么?*:当你的代码为了发布而压缩了并且被合并到同一个文件中时,可能会有很多变量发生冲突,使用了IIFE(给每个文件提供了一个独立的作用域),你就不用担心这个了。 ```javascript /* avoid */ @@ -132,7 +128,7 @@ .module('app') .factory('logger', logger); - // logger function is added as a global variable + // logger function会被当作一个全局变量 function logger() { } // storage.js @@ -140,7 +136,7 @@ .module('app') .factory('storage', storage); - // storage function is added as a global variable + // storage function会被当作一个全局变量 function storage() { } ``` @@ -148,7 +144,7 @@ /** * recommended * - * no globals are left behind + * 再也不存在全局变量了 */ // logger.js @@ -174,7 +170,7 @@ })(); ``` - - 注:为了简便起见,本指南余下的示例中将会省略IIFE语法。 + - 注:为了简洁起见,本指南余下的示例中将会省略IIFE语法。 - 注:IIFE阻止了测试代码访问私有成员(正则表达式、helper函数等),这对于自身测试是非常友好的。然而你可以把这些私有成员暴露到可访问成员中进行测试,例如把私有成员(正则表达式、helper函数等)放到factory或是constant中。 @@ -185,7 +181,7 @@ ###避免命名冲突 ###### [Style [Y020](#style-y020)] - - 给独立子模块使用唯一的命名约定。 + - 每一个独立子模块使用唯一的命名约定。 *为什么*:避免冲突,每个模块也可以方便定义子模块。 @@ -194,7 +190,7 @@ - 不使用任何一个使用了setter语法的变量来定义modules。 - *为什么?*:在一个文件只有一个组件的条件下,很少有需要为一个模块引入一个变量。 + *为什么?*:在一个文件只有一个组件的条件下,完全不需要为一个模块引入一个变量。 ```javascript /* avoid */ @@ -206,7 +202,7 @@ ]); ``` - 用简单的setter语法来代替。 + 你只需要用简单的setter语法来代替。 ```javascript /* recommended */ @@ -222,7 +218,7 @@ ###Getters ###### [Style [Y022](#style-y022)] - - 当使用一个module的时候,避免使用一个变量,而是使用getter语法链接。 + - 使用module的时候,避免直接用一个变量,而是使用getter的链式语法。 *为什么?*:这将产生更加易读的代码,并且可以避免变量冲突和泄漏。 @@ -246,19 +242,19 @@ ###Setting vs Getting ###### [Style [Y023](#style-y023)] - - 设置一次,获取其它所有的实例。 + - 只能设置一次。 - *为什么?*:一个module只能被创建一次,然后从该点恢复。 + *为什么?*:一个module只能被创建一次,创建之后才能被检索到。 - - 用 `angular.module('app', []);` 设置一个module。 - - 用 `angular.module('app');` 获取一个module。 + - 设置module,`angular.module('app', []);`。 + - 获取module,`angular.module('app');`。 ###命名函数 vs 匿名函数 ###### [Style [Y024](#style-y024)] - - 用一个命名函数而不是通过一个匿名函数作为回调函数。 + - 回调函数使用命名函数,不要用匿名函数。 - *为什么?*:这将产生更加易读的代码,更加方便调试,减少嵌套回调函数的数量。 + *为什么?*:易读,方便调试,减少嵌套回调函数的数量。 ```javascript /* avoid */ @@ -297,9 +293,9 @@ - 使用[`controllerAs`](http://www.johnpapa.net/do-you-like-your-angular-controllers-with-or-without-sugar/) 语法代替直接用经典的$scope定义的controller的方式。 - *为什么?*:congtroller被构建的时候,就会有一个新的实例,`controllerAs` 的语法比`经典的$scope语法`更接近JavaScript构造函数 + *为什么?*:congtroller被构建的时候,就会有一个新的实例,`controllerAs` 的语法比`经典的$scope语法`更接近JavaScript构造函数。 - *为什么?*:这促进在View中对绑定到’dotted‘的对象的使用(例如用`customer.name` 代替`name`),这将更有语境、更容易阅读,也避免了任何没有“dotting”而产生的引用问题。 + *为什么?*:这促进在View中对绑定到“有修饰”的对象的使用(例如用`customer.name` 代替`name`),这将更有语境、更容易阅读,也避免了任何没有“修饰”而产生的引用问题。 *为什么?*:有助于避免在有嵌套的controllers的Views中调用 `$parent`。 @@ -322,11 +318,11 @@ - 使用 `controllerAs` 语法代替 `经典的$scope语法` 语法。 - - `controllerAs` 语法在controllers里面使用被绑定到`$scope`中的`this`。 + - 使用`controllerAs` 时,controller中的`$scope`被绑定到了`this`上。 *为什么?*:`controllerAs` 是`$scope`的语法修饰,你仍然可以绑定到View上并且访问 `$scope`的方法。 - *为什么?*:有助于避免在controller内部使用 `$scope`中的方法的诱惑,这能够更好地避免它们或把它们移到一个factory中。考虑到在factory中使用`$scope`,或者没办法的时候必须在controller中使用`$scope`,例如当使用[`$emit`](https://docs.angularjs.org/api/ng/type/$rootScope.Scope#$emit), [`$broadcast`](https://docs.angularjs.org/api/ng/type/$rootScope.Scope#$broadcast),或者 [`$on`](https://docs.angularjs.org/api/ng/type/$rootScope.Scope#$on)来发布和订阅事件时,可以考虑把这些调用挪到factory当中,并从controller中调用。 + *为什么?*:避免在controller中使用 `$scope`,最好不用它们或是把它们移到一个factory中。factory中可以考虑使用`$scope`,controller中只在需要时候才使用`$scope`,例如当使用[`$emit`](https://docs.angularjs.org/api/ng/type/$rootScope.Scope#$emit), [`$broadcast`](https://docs.angularjs.org/api/ng/type/$rootScope.Scope#$broadcast),或者 [`$on`](https://docs.angularjs.org/api/ng/type/$rootScope.Scope#$on)来发布和订阅事件时,可以考虑把这些调用挪到factory当中,并从controller中调用。 ```javascript /* avoid */ @@ -345,10 +341,11 @@ ``` ###controllerAs with vm +###### [Style [Y032](#style-y032)] - - 使用`controllerAs`语法时把`this` 赋值给一个捕获变量,选择一个相一致的名称,例如`vm`代表ViewModel。 + - 使用`controllerAs`语法时把`this` 赋值给一个可捕获的变量,选择一个有代表性的名称,例如`vm`代表ViewModel。 - *为什么?*:`this`在不同的地方有不同的语义(就是作用域不同),在一个controller中的一个函数内部使用`this`时可能会改变它的上下文。用一个变量来捕获`this`的上下文从而可以避免遇到这个问题。 + *为什么?*:`this`在不同的地方有不同的语义(就是作用域不同),在controller中的一个函数内部使用`this`时可能会改变它的上下文。用一个变量来捕获`this`的上下文从而可以避免遇到这样的坑。 ```javascript /* avoid */ @@ -367,7 +364,7 @@ } ``` - - 注:你可以按照下面的做法来避免 [jshint](http://www.jshint.com/)的警告。但是构造函数(函数名首字母大写)是不需要这个的. + - 注:你可以参照下面的做法来避免 [jshint](http://www.jshint.com/)的警告。但是构造函数(函数名首字母大写)是不需要这个的. ```javascript /* jshint validthis: true */ @@ -397,9 +394,9 @@ - 把可绑定的成员放到controller的顶部,按字母排序,并且不要通过controller的代码传播。 - *为什么?*:把可绑定的成员放到顶部使代码更易读,并且让你可以立即识别controller中的哪些成员可以在View中绑定和使用。 + *为什么?*:易读,可以让你立即识别controller中的哪些成员可以在View中绑定和使用。 - *为什么?*:设置一个单行的匿名函数是很容易的,但是当这些函数的代码超过一行时,这将极大降低代码的可读性。把函数定义到可绑定成员下面(这些函数被提出来),把具体的实现细节放到下面,可绑定成员放到顶部,这会提高代码的可读性。 + *为什么?*:虽然设置单行匿名函数很容易,但是当这些函数的代码超过一行时,这将极大降低代码的可读性。在可绑定成员下面定义函数(这些函数被提出来),把具体的实现细节放到下面,可绑定成员放到顶部,这会提高代码的可读性。 ```javascript /* avoid */ @@ -484,7 +481,7 @@ ###函数声明隐藏实现细节 ###### [Style [Y034](#style-y034)] - - 函数声明隐藏实现细节,把绑定成员放到顶部,当你需要在controller中绑定一个函数时,把它指向一个函数声明,这个函数声明在文件的后面会出现。 + - 使用函数声明来隐藏实现细节,把绑定成员放到顶部,当你需要在controller中绑定一个函数时,把它指向一个在文件的后面会出现函数声明。更多详情请看[这里](http://www.johnpapa.net/angular-function-declarations-function-expressions-and-readable-code)。 *为什么?*:易读,易识别哪些成员可以在View中绑定和使用。 @@ -587,7 +584,7 @@ // Use JSONP for this browser if it doesn't support CORS return $http.get(settings) .then(function(data) { - // Unpack JSON data in the response object + // Unpack JSON data in the response object // to find maxRemainingAmount vm.isCreditOk = vm.total <= maxRemainingAmount }) @@ -601,7 +598,6 @@ ``` ```javascript - /* recommended */ function Order (creditService) { var vm = this; @@ -610,7 +606,7 @@ vm.total = 0; function checkCredit () { - return creditService.isOrderTotalOk(vm.total) + return creditService.isOrderTotalOk(vm.total) .then(function(isOk) { vm.isCreditOk = isOk; }) .catch(showServiceError); }; @@ -620,18 +616,18 @@ ###保持Controller的专一性 ###### [Style [Y037](#style-y037)] - - 一个view定义一个controller,尽量不要在其它view中使用这个controller。把可重用的逻辑放到factory中,保证controller的单一,只专注于当前视图。 + - 一个view定义一个controller,尽量不要在其它view中使用这个controller。把可重用的逻辑放到factory中,保证controller只服务于当前视图。 - *为什么?*:不同的view用同一个controller是非常不科学的,良好的端对端测试覆盖率对于保证大型应用稳定性是必需的。 + *为什么?*:不同的view用同一个controller是非常不科学的,良好的端对端测试覆盖率对于保证大型应用稳定性是必需的。 ###分配Controller ###### [Style [Y038](#style-y038)] - 当一个controller必须匹配一个view时或者任何一个组件可能被其它controller或是view重用时,连同controller的route一起定义。 - - 注:如果一个view是通过route外的其它形式加载的,那么就用`ng-controller="Avengers as vm"`语法。 + 注:如果一个view是通过route外的其它形式加载的,那么就用`ng-controller="Avengers as vm"`语法。 - *为什么?*:在route中匹配controller允许不同的路由调用不同的相匹配的controller和view,当在view中通过[`ng-controller`](https://docs.angularjs.org/api/ng/directive/ngController)分配controller时,这个view总是和相同的controller相关联。 + *为什么?*:在route中匹配controller允许不同的路由调用不同的相匹配的controller和view,当在view中通过[`ng-controller`](https://docs.angularjs.org/api/ng/directive/ngController)分配controller时,这个view总是和相同的controller相关联。 ```javascript /* avoid - when using with a route and dynamic pairing is desired */ @@ -686,13 +682,12 @@ ###单例 ###### [Style [Y040](#style-y040)] - - 用`new`实例化service,用`this`实例化公共方法和变量,由于这和facotry是类似的,所以推荐用facotry来代替。 + - 用`new`实例化service,用`this`实例化公共方法和变量,由于这和factory是类似的,所以为了保持统一,推荐用facotry来代替。 注意:[所有的Angular services都是单例](https://docs.angularjs.org/guide/services),这意味着每个injector都只有一个实例化的service。 ```javascript // service - angular .module('app') .service('logger', logger); @@ -729,6 +724,7 @@ - factory应该是[单一职责](http://en.wikipedia.org/wiki/Single_responsibility_principle),这是由其上下文进行封装的。一旦一个factory将要处理超过单一的目的时,就应该创建一个新的factory。 ###单例 +###### [Style [Y051](#style-y051)] - facotry是一个单例,它返回一个包含service成员的对象。 @@ -739,17 +735,17 @@ - 使用从[显露模块模式](http://addyosmani.com/resources/essentialjsdesignpatterns/book/#revealingmodulepatternjavascript)派生出来的技术把service(它的接口)中可调用的成员暴露到顶部, - *为什么?*:把可调用的成员放到顶部使代码更加易读,并且让你可以立即识别service中的哪些成员可以被调用,哪些成员必须进行单元测试(或者被别人嘲笑)。 + *为什么?*:易读,并且让你可以立即识别service中的哪些成员可以被调用,哪些成员必须进行单元测试(或者被别人嘲笑)。 - *为什么?*:当文件变长时,这将非常有用,因为这可以避免需要滚动才能看到暴露了哪些东西。 + *为什么?*:当文件内容很长时,这可以避免需要滚动才能看到暴露了哪些东西。 - *为什么?*:以你的方式设置函数是很容易的,但当函数代码超过一行时就会降低可读性并造成滚动。通过把实现细节放下面、可调用接口放到顶部的返回service的方式来定义可调用的接口,从而使代码更加易读。 + *为什么?*:虽然你可以随意写一个函数,但当函数代码超过一行时就会降低可读性并造成滚动。通过把实现细节放下面、可调用接口放到顶部的返回service的方式来定义可调用的接口,从而使代码更加易读。 ```javascript /* avoid */ function dataService () { var someValue = ''; - function save () { + function save () { /* */ }; function validate () { @@ -776,6 +772,7 @@ return service; //////////// + function save () { /* */ }; @@ -897,11 +894,11 @@ - 把进行数据操作和数据交互的逻辑放到factory中,数据服务负责XHR请求、本地存储、内存存储和其它任何数据操作。 - *为什么?*:controller的作用是查看view和收集view的信息,它不应该关心如何取得数据,只需要知道哪里需要用到数据。把取数据的逻辑分离到data service中能够让controller更简单、更专注于对view的控制。 + *为什么?*:controller的作用是查看视图和收集视图的信息,它不应该关心如何取得数据,只需要知道哪里需要用到数据。把取数据的逻辑放到数据服务中能够让controller更简单、更专注于对view的控制。 - *为什么?*:使用这种方式使得测试数据调用这一块更加简单。 + *为什么?*:方便测试。 - *为什么?*:data service的实现可能有非常明确的代码来处理数据仓库,这可能包含headers、如何与数据交互或是其它service,例如$http。把逻辑分离到data service中,把逻辑封装到了一个单独的地方,这隐藏了外部消费者(可能是controller)对数据的直接操作,这使得改变执行更加容易。 + *为什么?*:数据服务的实现可能有非常明确的代码来处理数据仓库,这可能包含headers、如何与数据交互或是其它service,例如`$http`。把逻辑封装到单独的数据服务中,这隐藏了外部调用者(例如controller)对数据的直接操作,这样更加容易执行变更。 ```javascript /* recommended */ @@ -933,7 +930,8 @@ } } ``` - 注意:data service是被消费者调用的(例如controller),隐藏了消费者的直接行为,如下所示。 + + 注意:数据服务被调用时(例如controller),隐藏调用的直接行为,如下所示。 ```javascript /* recommended */ @@ -967,10 +965,10 @@ } ``` -###从Data调用那里返回一个Promise +###数据调用返回一个Promise ###### [Style [Y061](#style-y061)] - - 就像`$http`一样,当调用data service时返回一个promise,在你的调用函数中也返回一个promise。 + - 就像`$http`一样,调用数据时返回一个promise,在你的调用函数中也返回一个promise。 *为什么?*:你可以把promise链接到一起,在数据调用完成并且resolve或是reject这个promise后采取进一步的行为。 @@ -1014,30 +1012,32 @@ **[返回顶部](#目录)** - ## Directives - -###一个文件限制一个 +###一个dirctive一个文件 ###### [Style [Y070](#style-y070)] - 一个文件中只创建一个directive,并依照directive来命名文件。 - *为什么?*:把所有directive放到一个文件中很容易,但是当一些directive是跨应用的,一些是跨模块的,一些仅仅在一个模块中使用时,想把它们独立出来是非常困难的。 + *为什么?*:虽然把所有directive放到一个文件中很简单,但是当一些directive是跨应用的,一些是跨模块的,一些仅仅在一个模块中使用时,想把它们独立出来就非常困难了。 *为什么?*:一个文件一个directive也更加容易维护。 + > 注: "**最佳实践**:Angular文档中有提过,directive应该自动回收,当directive被移除后,你可以使用`element.on('$destroy', ...)`或者`scope.$on('$destroy', ...)`来执行一个clearn-up函数。" + ```javascript /* avoid */ + /* directives.js */ + angular .module('app.widgets') - /* order directive that is specific to the order module */ + /* order directive仅仅会被order module用到 */ .directive('orderCalendarRange', orderCalendarRange) - /* sales directive that can be used anywhere across the sales app */ + /* sales directive可以在sales app的任意地方使用 */ .directive('salesCustomerInfo', salesCustomerInfo) - /* spinner directive that can be used anywhere across apps */ + /* spinner directive可以在任意apps中使用 */ .directive('sharedSpinner', sharedSpinner); function orderCalendarRange() { @@ -1104,12 +1104,12 @@ } ``` - 注:directive有很多命名选项,特别是从它们能够在一个狭隘的或者广泛的作用域中使用时。选择一个让directive和它的文件名都清楚分明的名字。下面有一些例子,不过更多的建议去看[命名](#命名)章节。 + 注:由于directive使用条件比较广,所以命名就存在很多的选项。选择一个让directive和它的文件名都清楚分明的名字。下面有一些例子,不过更多的建议去看[命名](#命名)章节。 ###在directive中操作DOM ###### [Style [Y072](#style-y072)] - - 当需要直接操作DOM的时候,使用directive。如果有替代方法可以使用,例如:使用CSS来设置样式、[animation services](https://docs.angularjs.org/api/ngAnimate)、Angular模板、[`ngShow`](https://docs.angularjs.org/api/ng/directive/ngShow) or [`ngHide`](https://docs.angularjs.org/api/ng/directive/ngHide),那么就直接用这些即可。例如,如果一个directive只是想控制显示和隐藏,用ngHide/ngShow即可。 + - 当需要直接操作DOM的时候,使用directive。如果有替代方法可以使用,例如:使用CSS来设置样式、[animation services](https://docs.angularjs.org/api/ngAnimate)、Angular模板、[`ngShow`](https://docs.angularjs.org/api/ng/directive/ngShow)或者[`ngHide`](https://docs.angularjs.org/api/ng/directive/ngHide),那么就直接用这些即可。例如,如果一个directive只是想控制显示和隐藏,用ngHide/ngShow即可。 *为什么?*:DOM操作的测试和调试是很困难的,通常会有更好的方法(CSS、animations、templates)。 @@ -1125,7 +1125,7 @@ ###限制元素和属性 ###### [Style [Y074](#style-y074)] - - 当创建一个directive需要作为一个独立元素是有意义时,允许限制`E`(自定义元素),可选限制`A`(自定义属性)。一般来说,如果它可能是它自己的控制,用`E`是合适的做法。一般原则是允许`EA`,但是当它是独立的时候这更倾向于作为一个元素来实施,当它是为了增强已存在的DOM元素时则更倾向于作为一个属性来实施。 + - 当创建一个directive需要作为一个独立元素时,restrict值设置为`E`(自定义元素),也可以设置可选值`A`(自定义属性)。一般来说,如果它就是为了独立存在,用`E`是合适的做法。一般原则是允许`EA`,但是当它是独立的时候这更倾向于作为一个元素来实施,当它是为了增强已存在的DOM元素时则更倾向于作为一个属性来实施。 *为什么?*:这很有意义! @@ -1191,13 +1191,12 @@ *为什么?*:因为不难且有必要这样做。 - 注意:下面的directive演示了一些你可以在link和directivedirective控制器中使用scope的方法,用controllerAs。这里把template放在行内是为了在一个地方写出这些代码。 + 注意:下面的directive演示了一些你可以在link和directive控制器中使用scope的方法,用controllerAs。这里把template放在行内是为了在一个地方写出这些代码。 注意:关于依赖注入的内容,请看[手动依赖注入](#手动依赖注入)。 注意:directive的控制器是在directive外部的,这种风格避免了由于注入造成的`return`之后的代码无法访问的情况。 - ```html
``` @@ -1243,8 +1242,6 @@ console.log('CTRL: vm.min = %s', vm.min); console.log('CTRL: vm.max = %s', vm.max); } - - ``` ```html @@ -1254,11 +1251,23 @@
min={{vm.min}}
``` + 注意:当你把controller注入到link的函数或可访问的directive的attributes时,你可以把它命名为控制器的属性。 + + ```javascript + // Alternative to above example + function linkFunc(scope, el, attr, vm) { // 和上面例子的区别在于把vm直接传递进来 + console.log('LINK: scope.min = %s *** should be undefined', scope.min); + console.log('LINK: scope.max = %s *** should be undefined', scope.max); + console.log('LINK: vm.min = %s', vm.min); + console.log('LINK: vm.max = %s', vm.max); + } + ``` + ###### [Style [Y076](#style-y076)] - 当directive中使用了`controller as`语法时,如果你想把父级作用域绑定到directive的controller作用域时,使用`bindToController = true`。 - *为什么?*:这使得绑定作用域到controller变得更加简单。 + *为什么?*:这使得把外部作用域绑定到directive controller中变得更加简单。 注意:Angular 1.3.0才介绍了`bindToController`。 @@ -1279,8 +1288,8 @@ max: '=' }, controller: ExampleController, - controllerAs: 'vm', - bindToController: true + controllerAs: 'vm', + bindToController: true }; return directive; @@ -1304,13 +1313,12 @@ **[返回顶部](#目录)** ## 解决Controller的Promises - ###Controller Activation Promises ###### [Style [Y080](#style-y080)] - 在`activate`函数中解决controller的启动逻辑。 - *为什么?*:把启动逻辑放在一个controller中固定的位置可以更方便定位、有更加一致性的测试,并能够避免在controller中到处都是激活逻辑。 + *为什么?*:把启动逻辑放在一个controller中固定的位置可以方便定位、有利于保持测试的一致性,并能够避免controller中到处都是激活逻辑。 *为什么?*:`activate`这个controller使得重用刷新视图的逻辑变得很方便,把所有的逻辑都放到了一起,可以让用户更快地看到视图,可以很轻松地对`ng-view` 或 `ui-view`使用动画,用户体验更好。 @@ -1353,16 +1361,15 @@ ###Route Resolve Promises ###### [Style [Y081](#style-y081)] - - 当一个controller依赖于一个需要在controller被激活之前的就resoved的promise,那么就在controller的逻辑执行之前在`$routeProvider`中解决这些依赖。如果你需要在controller被激活之前有条件地取消一个路由,那么就用route resolver。 + - 当一个controller在激活之前,需要依赖一个promise的完成时,那么就在controller的逻辑执行之前在`$routeProvider`中解决这些依赖。如果你需要在controller被激活之前有条件地取消一个路由,那么就用route resolver。 - - 当你决定在过渡到视图之前取消路由时,使用route resolve。 + - 当你决定在过渡到视图之前取消路由时,使用route resolve。 *为什么?*:controller在加载前可能需要一些数据,这些数据可能是从一个通过自定义factory或是[$http](https://docs.angularjs.org/api/ng/service/$http)的promise而来的。[route resolve](https://docs.angularjs.org/api/ngRoute/provider/$routeProvider)允许promise在controller的逻辑执行之前解决,因此它可能对从promise中来的数据做一些处理。 - *为什么?*:这段代码将在路由后的controller的激活函数中执行,视图立即加载,数据绑定将在promise resolve之后,可以(通过`ng-view`或`ui-view`)在视图的过渡之间可以加个loading状态的动画。 - - 注意:这段代码将在路由之前通过一个promise来执行,拒绝了承诺就会取消路由,接受了就会等待路由跳转到新视图。如果你想更快地进入视图,并且无需验证是否可以进入视图,你可以考虑用[控制器 `activate` 技术](#style-y080)代替。 + *为什么?*:这段代码将在路由后的controller的激活函数中执行,视图立即加载,promise resolve的时候将会开始进行数据绑定,可以(通过`ng-view`或`ui-view`)在视图的过渡之间加个loading状态的动画。 + 注意:这段代码将在路由之前通过一个promise来执行,拒绝了承诺就会取消路由,接受了就会等待路由跳转到新视图。如果你想更快地进入视图,并且无需验证是否可以进入视图,你可以考虑用[控制器 `activate` 技术](#style-y080)。 ```javascript /* avoid */ @@ -1376,7 +1383,7 @@ vm.movies; // resolved asynchronously movieService.getMovies().then(function(response) { - vm.movies = response.movies; + vm.movies = response.movies; }); } ``` @@ -1396,9 +1403,9 @@ controller: 'Avengers', controllerAs: 'vm', resolve: { - moviesPrepService: function(movieService) { - return movieService.getMovies(); - } + moviesPrepService: function(movieService) { + return movieService.getMovies(); + } } }); } @@ -1408,12 +1415,14 @@ .module('app') .controller('Avengers', Avengers); + Avengers.$inject = ['moviesPrepService']; function Avengers (moviesPrepService) { var vm = this; vm.movies = moviesPrepService.movies; } ``` - 注意:下面这个例子展示了命名函数的路由解决,这种方式对于调试和处理依赖注入更加方便。 + + 注意:下面这个例子展示了命名函数的路由解决,这种方式对于调试和处理依赖注入更加方便。 ```javascript /* even better */ @@ -1450,18 +1459,16 @@ vm.movies = moviesPrepService.movies; } ``` - - 注意:示例代码中的`movieService`不是安全压缩的做法,可以到[手动依赖注入](#手动依赖注入)和[压缩和注释](#压缩和注释)部分学习如何安全压缩。 - + 注意:示例代码中的`movieService`不符合安全压缩的做法,可以到[手动依赖注入](#手动依赖注入)和[压缩和注释](#压缩和注释)部分学习如何安全压缩。 **[返回顶部](#目录)** ## 手动依赖注入 -###缩写的不安全性 +### 压缩的不安全性 ###### [Style [Y090](#style-y090)] - - 声明依赖时避免使用不安全缩写方法的缩写语法。 + - 声明依赖时避免使用缩写语法。 *为什么?*:组件的参数(例如controller、factory等等)将会被转换成各种乱七八糟错误的变量。例如,`common`和`dataservice`可能会变成`a`或者`b`,但是这些转换后的变量在Angular中是找不到的。 @@ -1475,7 +1482,7 @@ } ``` - - 这一段代码在压缩时会产生错误的变量,因此在运行时就会报错。 + 这一段代码在压缩时会产生错误的变量,因此在运行时就会报错。 ```javascript /* avoid - not minification-safe*/ @@ -1491,7 +1498,7 @@ *为什么?*:可以避免依赖变成其它Angular找不到的变量,例如,`common`和`dataservice`可能会变成`a`或者`b`。 - *为什么?*:避免创建内嵌的依赖,因为一个数组中很长的列表是很难阅读的,此外,内嵌的方式也会让人感到困惑,比如数组是一系列的字符串,但是最后一个却是组件的function。 + *为什么?*:避免创建内嵌的依赖,因为一个数组太长不利于阅读,此外,内嵌的方式也会让人感到困惑,比如数组是一系列的字符串,但是最后一个却是组件的function。 ```javascript /* avoid */ @@ -1504,7 +1511,6 @@ ``` ```javascript - /* avoid */ angular .module('app') @@ -1527,7 +1533,7 @@ } ``` - 注意:当你的函数处于一个return语句下,那么`$inject`可能无法访问(这会在directive中发生),你可以通过把Controller移到directive外面来解决这个问题。 + 注意:当你的函数处于return语句后面,那么`$inject`是无法访问的(这会在directive中发生),你可以通过把Controller移到directive外面来解决这个问题。 ```javascript /* avoid */ @@ -1590,7 +1596,6 @@ } ``` - **[返回顶部](#目录)** ## 压缩和注释 @@ -1600,59 +1605,76 @@ - 在[Gulp](http://gulpjs.com)或[Grunt](http://gruntjs.com)中使用[ng-annotate](//github.com/olov/ng-annotate),用`/** @ngInject */`对需要自动依赖注入的function进行注释。 - *为什么?*:可以避免代码中的依赖使用到任何不安全缩写的写法。 + *为什么?*:可以避免代码中的依赖使用到任何不安全的写法。 - *为什么?*:[`ng-min`](https://github.com/btford/ngmin)是不推荐的用法。 + *为什么?*:不推荐用[`ng-min`](https://github.com/btford/ngmin)。 >我更喜欢Gulp,因为我觉得它是易写易读易调试的。 - 下面的代码没有使用压缩安全依赖。 + 下面的代码没有注入依赖,显然压缩是不安全的。 - ```javascript - angular - .module('app') - .controller('Avengers', Avengers); + ```javascript + angular + .module('app') + .controller('Avengers', Avengers); - /* @ngInject */ - function Avengers (storageService, avengerService) { - var vm = this; - vm.heroSearch = ''; - vm.storeHero = storeHero; + /* @ngInject */ + function Avengers (storageService, avengerService) { + var vm = this; + vm.heroSearch = ''; + vm.storeHero = storeHero; - function storeHero(){ - var hero = avengerService.find(vm.heroSearch); - storageService.save(hero.name, hero); - } - } - ``` + function storeHero(){ + var hero = avengerService.find(vm.heroSearch); + storageService.save(hero.name, hero); + } + } + ``` 当上面的代码通过ng-annotate运行时,就会产生如下的带有`$inject`注释的输出结果,这样的话压缩就会安全了。 - ```javascript - angular - .module('app') - .controller('Avengers', Avengers); - - /* @ngInject */ - function Avengers (storageService, avengerService) { - var vm = this; - vm.heroSearch = ''; - vm.storeHero = storeHero; + ```javascript + angular + .module('app') + .controller('Avengers', Avengers); - function storeHero(){ - var hero = avengerService.find(vm.heroSearch); - storageService.save(hero.name, hero); - } - } + /* @ngInject */ + function Avengers (storageService, avengerService) { + var vm = this; + vm.heroSearch = ''; + vm.storeHero = storeHero; - Avengers.$inject = ['storageService', 'avengerService']; + function storeHero(){ + var hero = avengerService.find(vm.heroSearch); + storageService.save(hero.name, hero); + } + } - ``` + Avengers.$inject = ['storageService', 'avengerService']; + ``` 注意:如果`ng-annotate`检测到已经有注入了(例如发现了`@ngInject`),就不会重复生成`$inject`代码了。 - > 注意:从Angular 1.3开始,你就可以用[`ngApp`](https://docs.angularjs.org/api/ng/directive/ngApp)指令的 `ngStrictDi`参数来检测任何可能失去依赖的地方,当以“strict-di”模式创建injector时,会导致应用程序无法调用不使用显示函数注释的函数(这也许无法安全压缩)。记录在控制台的调试信息可以帮助追踪出问题的代码。我只在需要调试的时候才会用到`ng-strict-di`。 + 注意:路由的函数前面也可以用`/* @ngInject */` + + ```javascript + // Using @ngInject annotations + function config($routeProvider) { + $routeProvider + .when('/avengers', { + templateUrl: 'avengers.html', + controller: 'Avengers', + controllerAs: 'vm', + resolve: { /* @ngInject */ + moviesPrepService: function(movieService) { + return movieService.getMovies(); + } + } + }); + } + ``` + > 注意:从Angular 1.3开始,你就可以用[`ngApp`](https://docs.angularjs.org/api/ng/directive/ngApp)指令的 `ngStrictDi`参数来检测任何可能失去依赖的地方,当以“strict-di”模式创建injector时,会导致应用程序无法调用不使用显示函数注释的函数(这也许无法安全压缩)。记录在控制台的调试信息可以帮助追踪出问题的代码。我只在需要调试的时候才会用到`ng-strict-di`。 `` ###使用Gulp或Grunt结合ng-annotate @@ -1664,25 +1686,25 @@ 下面的代码是gulp任务使用ngAnnotate的例子。 - ```javascript - gulp.task('js', ['jshint'], function() { - var source = pkg.paths.js; - - return gulp.src(source) - .pipe(sourcemaps.init()) - .pipe(concat('all.min.js', {newLine: ';'})) - // Annotate before uglify so the code get's min'd properly. - .pipe(ngAnnotate({ - // true helps add where @ngInject is not used. It infers. - // Doesn't work with resolve, so we must be explicit there - add: true - })) - .pipe(bytediff.start()) - .pipe(uglify({mangle: true})) - .pipe(bytediff.stop()) - .pipe(sourcemaps.write('./')) - .pipe(gulp.dest(pkg.paths.dev)); - }); + ```javascript + gulp.task('js', ['jshint'], function() { + var source = pkg.paths.js; + + return gulp.src(source) + .pipe(sourcemaps.init()) + .pipe(concat('all.min.js', {newLine: ';'})) + // Annotate before uglify so the code get's min'd properly. + .pipe(ngAnnotate({ + // true helps add where @ngInject is not used. It infers. + // Doesn't work with resolve, so we must be explicit there + add: true + })) + .pipe(bytediff.start()) + .pipe(uglify({mangle: true})) + .pipe(bytediff.stop()) + .pipe(sourcemaps.write('./')) + .pipe(gulp.dest(pkg.paths.dev)); + }); ``` @@ -1697,39 +1719,39 @@ *为什么?*:在开发时和运行时提供了一种统一的方式来处理未被捕获的Angular异常。 - 注:另一个选项是用来覆盖service的,这个可以代替decorator,这是一个非常nice的选项,但是如果你想保持默认行为,那么推荐你拓展一个decorator。 + 注:另一个选项是用来覆盖service的,这个可以代替decorator,这是一个非常nice的选项,但是如果你想保持默认行为,那么推荐你扩展一个decorator。 - ```javascript - /* recommended */ - angular - .module('blocks.exception') - .config(exceptionConfig); + ```javascript + /* recommended */ + angular + .module('blocks.exception') + .config(exceptionConfig); - exceptionConfig.$inject = ['$provide']; + exceptionConfig.$inject = ['$provide']; - function exceptionConfig($provide) { - $provide.decorator('$exceptionHandler', extendExceptionHandler); - } + function exceptionConfig($provide) { + $provide.decorator('$exceptionHandler', extendExceptionHandler); + } - extendExceptionHandler.$inject = ['$delegate', 'toastr']; + extendExceptionHandler.$inject = ['$delegate', 'toastr']; - function extendExceptionHandler($delegate, toastr) { - return function(exception, cause) { - $delegate(exception, cause); - var errorData = { - exception: exception, - cause: cause - }; - /** - * Could add the error to a service's collection, - * add errors to $rootScope, log errors to remote web server, - * or log locally. Or throw hard. It is entirely up to you. - * throw exception; - */ - toastr.error(exception.msg, errorData); - }; - } - ``` + function extendExceptionHandler($delegate, toastr) { + return function(exception, cause) { + $delegate(exception, cause); + var errorData = { + exception: exception, + cause: cause + }; + /** + * Could add the error to a service's collection, + * add errors to $rootScope, log errors to remote web server, + * or log locally. Or throw hard. It is entirely up to you. + * throw exception; + */ + toastr.error(exception.msg, errorData); + }; + } + ``` ###异常捕获器 ###### [Style [Y111](#style-y111)] @@ -1738,29 +1760,29 @@ *为什么?*:提供了一个统一的方法来捕获代码中抛出的异常。 - 注:异常捕获器对特殊异常的捕获和反应是非常好的,例如,使用XHR从远程服务获取数据时,你想要捕获所有异常并做出不同的反应。 + 注:异常捕获器对特殊异常的捕获和反应是非常友好的,例如,使用XHR从远程服务获取数据时,你想要捕获所有异常并做出不同的反应。 - ```javascript - /* recommended */ - angular - .module('blocks.exception') - .factory('exception', exception); + ```javascript + /* recommended */ + angular + .module('blocks.exception') + .factory('exception', exception); - exception.$inject = ['logger']; + exception.$inject = ['logger']; - function exception(logger) { - var service = { - catcher: catcher - }; - return service; + function exception(logger) { + var service = { + catcher: catcher + }; + return service; - function catcher(message) { - return function(reason) { - logger.error(message, reason); - }; - } - } - ``` + function catcher(message) { + return function(reason) { + logger.error(message, reason); + }; + } + } + ``` ###路由错误 ###### [Style [Y112](#style-y112)] @@ -1769,43 +1791,43 @@ *为什么?*:提供一个统一的方式来处理所有的路由错误。 - *为什么?*:当一个路由发生错误的时候,如果能把用户带到一个有更多细节或是恢复选项的友好界面的话将会带来更好的用户体验。 + *为什么?*:当一个路由发生错误的时候,可以给展示一个提示信息,提高用户体验。 - ```javascript - /* recommended */ - var handlingRouteChangeError = false; + ```javascript + /* recommended */ + var handlingRouteChangeError = false; - function handleRoutingErrors() { - /** - * Route cancellation: - * On routing error, go to the dashboard. - * Provide an exit clause if it tries to do it twice. - */ - $rootScope.$on('$routeChangeError', - function(event, current, previous, rejection) { - if (handlingRouteChangeError) { return; } + function handleRoutingErrors() { + /** + * Route cancellation: + * On routing error, go to the dashboard. + * Provide an exit clause if it tries to do it twice. + */ + $rootScope.$on('$routeChangeError', + function(event, current, previous, rejection) { + if (handlingRouteChangeError) { return; } handlingRouteChangeError = true; var destination = (current && (current.title || current.name || current.loadedTemplateUrl)) || 'unknown target'; - var msg = 'Error routing to ' + destination + '. ' + + var msg = 'Error routing to ' + destination + '. ' + (rejection.msg || ''); - /** - * Optionally log using a custom service or $log. - * (Don't forget to inject custom service) - */ - logger.warning(msg, [current]); + /** + * Optionally log using a custom service or $log. + * (Don't forget to inject custom service) + */ + logger.warning(msg, [current]); - /** - * On routing error, go to another route/state. - */ - $location.path('/'); + /** + * On routing error, go to another route/state. + */ + $location.path('/'); - } - ); - } - ``` + } + ); + } + ``` **[返回顶部](#目录)** @@ -1825,69 +1847,69 @@ ###功能文件命名 ###### [Style [Y121](#style-y121)] - - 遵循以描述组件功能,然后是类型(可选)的方式来给所有的组件提供统一的命名,我推荐的做法是`feature.type.js`。 + - 遵循以“描述组件功能.类型(可选)”的方式来给所有的组件提供统一的命名,我推荐的做法是`feature.type.js`。 *为什么?*:为快速识别组件提供了统一的方式。 *为什么?*:为任何自动化的任务提供模式匹配。 - ```javascript - /** - * common options - */ + ```javascript + /** + * common options + */ - // Controllers - avengers.js - avengers.controller.js - avengersController.js + // Controllers + avengers.js + avengers.controller.js + avengersController.js - // Services/Factories - logger.js - logger.service.js - loggerService.js - ``` + // Services/Factories + logger.js + logger.service.js + loggerService.js + ``` - ```javascript - /** - * recommended - */ + ```javascript + /** + * recommended + */ - // controllers - avengers.controller.js - avengers.controller.spec.js + // controllers + avengers.controller.js + avengers.controller.spec.js - // services/factories - logger.service.js - logger.service.spec.js + // services/factories + logger.service.js + logger.service.spec.js - // constants - constants.js - - // module definition - avengers.module.js + // constants + constants.js + + // module definition + avengers.module.js - // routes - avengers.routes.js - avengers.routes.spec.js + // routes + avengers.routes.js + avengers.routes.spec.js - // configuration - avengers.config.js - - // directives - avenger-profile.directive.js - avenger-profile.directive.spec.js - ``` + // configuration + avengers.config.js + + // directives + avenger-profile.directive.js + avenger-profile.directive.spec.js + ``` - 注意:另外一种常见的约定就是不要用`controller`这个词来给controller文件命名,例如不要用`avengers.controller.js`,而是用`avengers.js`。所有其它的约定都坚持使用类型作为后缀,但是controller是组件中最为常用的类型,因此这种做法的好处貌似仅仅是节省了打字,但是仍然很容易识别。我建议你为你的团队选择一种约定,并且要保持统一性。我喜欢的命名方式是`avengers.controller.js`。 + 注意:另外一种常见的约定就是不要用`controller`这个词来给controller文件命名,例如不要用`avengers.controller.js`,而是用`avengers.js`。所有其它的约定都坚持使用类型作为后缀,但是controller是组件中最为常用的类型,因此这种做法的好处貌似仅仅是节省了打字,但是仍然很容易识别。我建议你为你的团队选择一种约定,并且要保持统一性。我喜欢的命名方式是`avengers.controller.js`。 - ```javascript - /** - * recommended - */ - // Controllers - avengers.js - avengers.spec.js - ``` + ```javascript + /** + * recommended + */ + // Controllers + avengers.js + avengers.spec.js + ``` ###测试文件命名 ###### [Style [Y122](#style-y122)] @@ -1898,37 +1920,37 @@ *为什么?*:为[karma](http://karma-runner.github.io/)或是其它测试运行器提供模式匹配。 - ```javascript - /** - * recommended - */ - avengers.controller.spec.js - logger.service.spec.js - avengers.routes.spec.js - avenger-profile.directive.spec.js - ``` + ```javascript + /** + * recommended + */ + avengers.controller.spec.js + logger.service.spec.js + avengers.routes.spec.js + avenger-profile.directive.spec.js + ``` ###Controller命名 ###### [Style [Y123](#style-y123)] - - 为所有controller提供统一的名称,特征然后名字,鉴于controller是构造函数,所以要采用UpperCamelCase(每个单词首字母大写)的方式。 + - 为所有controller提供统一的名称,先特征后名字,鉴于controller是构造函数,所以要采用UpperCamelCase(每个单词首字母大写)的方式。 *为什么?*:为快速识别和引用controller提供统一的方式。 *为什么?*:UpperCamelCase是常规的识别一个可以用构造函数来实例化的对象的方式。 - ```javascript - /** - * recommended - */ + ```javascript + /** + * recommended + */ - // avengers.controller.js - angular - .module - .controller('HeroAvengersController', HeroAvengersController); + // avengers.controller.js + angular + .module + .controller('HeroAvengersController', HeroAvengersController); - function HeroAvengers(){ } - ``` + function HeroAvengers(){ } + ``` ###Controller命名后缀 ###### [Style [Y124](#style-y124)] @@ -1937,38 +1959,40 @@ *为什么?*:`Controller`使用更广泛、更明确、更具有描述性。 - ```javascript - /** - * recommended - */ + ```javascript + /** + * recommended + */ - // avengers.controller.js - angular - .module - .controller('AvengersController', AvengersController); + // avengers.controller.js + angular + .module + .controller('AvengersController', AvengersController); - function AvengersController(){ } - ``` + function AvengersController(){ } + ``` ###Factory命名 ###### [Style [Y125](#style-y125)] - - 一样要统一,对service和factory使用camel-casing(驼峰式,第一个单词首字母小写,后面单词首字母大写)方式。 + - 一样要统一,对service和factory使用camel-casing(驼峰式,第一个单词首字母小写,后面单词首字母大写)方式。避免使用`$`前缀。 *为什么?*:可以快速识别和引用factory。 + + *为什么?*:避免与内部使用`$`前缀的服务发生冲突。 - ```javascript - /** - * recommended - */ + ```javascript + /** + * recommended + */ - // logger.service.js - angular - .module - .factory('logger', logger); + // logger.service.js + angular + .module + .factory('logger', logger); - function logger(){ } - ``` + function logger(){ } + ``` ###Directive组件命名 ###### [Style [Y126](#style-y126)] @@ -1977,25 +2001,25 @@ *为什么?*:可以快速识别和引用controller。 - ```javascript - /** - * recommended - */ + ```javascript + /** + * recommended + */ - // avenger-profile.directive.js - angular - .module - .directive('xxAvengerProfile', xxAvengerProfile); + // avenger-profile.directive.js + angular + .module + .directive('xxAvengerProfile', xxAvengerProfile); - // usage is + // usage is - function xxAvengerProfile(){ } - ``` + function xxAvengerProfile(){ } + ``` ###模块 ###### [Style [Y127](#style-y127)] - - 当有很多的模块时,主模块文件命名成`app.module.js`,其它依赖模块以它们代表的东西来命名。例如,一个管理员模块命名成`admin.module.js`,它们各自的注册模块名字就是`app`和`admin`。 + - 当有很多的模块时,主模块文件命名成`app.module.js`,其它依赖模块以它们代表的内容来命名。例如,一个管理员模块命名成`admin.module.js`,它们各自的注册模块名字就是`app`和`admin`。 *为什么?*:给多模块的应用提供统一的方式,这也是为了扩展大型应用。 @@ -2015,11 +2039,9 @@ - 把路由的配置独立到单独的文件。主模块的路由可能是`app.route.js`,`admin`模块的路由可能是`admin.route.js`。即使是在很小的应用中,我也喜欢把路由的配置从其余的配置中分离出来。 - **[返回顶部](#目录)** ## 应用程序结构的LIFT准则 - ###LIFT ###### [Style [Y140](#style-y140)] @@ -2039,7 +2061,7 @@ - 更直观、更简单、更快捷地定位代码 - *为什么?*:我发现这对于一个项目是非常重要的,如果一个团队不能快速找到他们需要工作的文件,这将不能使团队足够高效地工作,那么这个代码结构就得改变。你可能不知道文件名或是相关的文件放在了哪里,那么就把他们放在最直观的地方,放在一起会节省大量的时间。一个参考目录结构。 + *为什么?*:我发现这对于一个项目是非常重要的,如果一个团队不能快速找到他们需要工作的文件,这将不能使团队足够高效地工作,那么这个代码结构就得改变。你可能不知道文件名或是相关的文件放在了哪里,那么就把他们放在最直观的地方,放在一起会节省大量的时间。下面是一个参考目录结构。 ``` /bower_components @@ -2080,7 +2102,6 @@ *为什么?*:保持DRY很重要,但是如果牺牲了其它LIFT,那么它就没那么重要了,这就是为什么说尽量坚持DRY。 - **[返回顶部](#目录)** ## 应用程序结构 @@ -2090,6 +2111,8 @@ - 有实施的短期看法和长远的目标,换句话说,从小处入手,但是要记住app的走向。app的所有代码都在一个叫做`app`的根目录下,所有的内容都遵循一个功能一个文件,每一个controller、service、module、view都是独立的文件。第三方脚本存放在另外的根文件夹中(`bower_components`、`scripts`、`lib`)。 + 注:了解实例结构的具体信息看[Angular应用结构](http://www.johnpapa.net/angular-app-structuring-guidelines/)。 + ###Layout ###### [Style [Y151](#style-y151)] @@ -2110,82 +2133,88 @@ *为什么?*:超过10个文件时,在一个一致性的文件夹中很容易定位,但是在一个平直的文件夹结构中确实很难定位。 - ```javascript - /** - * recommended - */ + ```javascript + /** + * recommended + */ - app/ - app.module.js - app.config.js - directives/ - calendar.directive.js - calendar.directive.html - user-profile.directive.js - user-profile.directive.html - services/ - dataservice.js - localstorage.js - logger.js - spinner.js - layout/ - shell.html - shell.controller.js - topnav.html - topnav.controller.js - people/ - attendees.html - attendees.controller.js - people.routes.js - speakers.html - speakers.controller.js - speaker-detail.html - speaker-detail.controller.js - sessions/ - sessions.html - sessions.controller.js - sessions.routes.js - session-detail.html - session-detail.controller.js - ``` + app/ + app.module.js + app.config.js + directives/ + calendar.directive.js + calendar.directive.html + user-profile.directive.js + user-profile.directive.html + services/ + dataservice.js + localstorage.js + logger.js + spinner.js + layout/ + shell.html + shell.controller.js + topnav.html + topnav.controller.js + people/ + attendees.html + attendees.controller.js + people.routes.js + speakers.html + speakers.controller.js + speaker-detail.html + speaker-detail.controller.js + sessions/ + sessions.html + sessions.controller.js + sessions.routes.js + session-detail.html + session-detail.controller.js + ``` + + ![实例App结构](https://raw.githubusercontent.com/johnpapa/angular-styleguide/master/assets/modularity-2.png) 注意:不要使用按类型划分文件夹结构,因为如果这样的话,当做一个功能时,需要在多个文件夹中来回切换。当应用程序有5个、10个,甚至是25个以上的view、controller(或其他feature)时,这种方式将迅速变得不实用,这就使得它定位文件比按功能分文件夹的方式要困难的多。 - ```javascript - /* - * avoid - * Alternative folders-by-type. - * I recommend "folders-by-feature", instead. - */ - - app/ - app.module.js - app.config.js - app.routes.js - directives.js - controllers/ - attendees.js - session-detail.js - sessions.js - shell.js - speakers.js - speaker-detail.js - topnav.js - views/ - attendees.html - session-detail.html - sessions.html - shell.html - speakers.html - speaker-detail.html - topnav.html - services/ - dataservice.js - localstorage.js - logger.js - spinner.js - ``` + ```javascript + /* + * avoid + * Alternative folders-by-type. + * I recommend "folders-by-feature", instead. + */ + app/ + app.module.js + app.config.js + app.routes.js + directives.js + controllers/ + attendees.js + session-detail.js + sessions.js + shell.js + speakers.js + speaker-detail.js + topnav.js + directives/ + calendar.directive.js + calendar.directive.html + user-profile.directive.js + user-profile.directive.html + services/ + dataservice.js + localstorage.js + logger.js + spinner.js + views/ + attendees.html + session-detail.html + sessions.html + shell.html + speakers.html + speaker-detail.html + topnav.html + ``` **[返回顶部](#目录)** @@ -2196,7 +2225,7 @@ - 创建只封装一个职责的小模块。 - *为什么?*:模块化的应用程序很容易插入新的功能。 + *为什么?*:模块化的应用程序很容易添加新的功能。 ###创建一个App Module ###### [Style [Y161](#style-y161)] @@ -2219,11 +2248,11 @@ - 创建代表功能区的模块,例如布局、可重用、共享服务、仪表盘和app的特殊功能(例如客户、管理、销售)。 - *为什么?*:自包含的模块可以无摩擦地被添加到应用程序中。 + *为什么?*:自包含的模块可以无缝地被添加到应用程序中。 - *为什么?*:冲刺或迭代可以专注于功能,在结束阶段启用它们。 + *为什么?*:项目进行功能迭代时,可以专注于功能,在开发完成启用它们即可。 - *为什么?*:分离功能为模块可以更容易测试。 + *为什么?*:把功能拆分成不同模块方便测试。 ###可重用的块就是模块 ###### [Style [Y164](#style-y164)] @@ -2249,6 +2278,7 @@ > 我的不同项目间的结构略有不同,但是它们都遵循了这些结构和模块化的准则,具体的实施方案会根据功能和团队发生变化。也就是说,不要在一棵树上吊死,但是心中一定要记得保持一致性、可维护性和效率。 + > 小项目中,你可以直接把所有依赖都放到app module中,这对于小项目来说比较容易维护,但是想在此项目外重用模块就比较难了。 **[返回顶部](#目录)** @@ -2261,30 +2291,30 @@ *为什么?*:这使得在更少的地方进行配置变得容易。 - ```javascript - angular - .module('app') - .config(configure); + ```javascript + angular + .module('app') + .config(configure); - configure.$inject = - ['routerHelperProvider', 'exceptionHandlerProvider', 'toastr']; - - function configure (routerHelperProvider, exceptionHandlerProvider, toastr) { - exceptionHandlerProvider.configure(config.appErrorPrefix); - configureStateHelper(); + configure.$inject = + ['routerHelperProvider', 'exceptionHandlerProvider', 'toastr']; + + function configure (routerHelperProvider, exceptionHandlerProvider, toastr) { + exceptionHandlerProvider.configure(config.appErrorPrefix); + configureStateHelper(); - toastr.options.timeOut = 4000; - toastr.options.positionClass = 'toast-bottom-right'; + toastr.options.timeOut = 4000; + toastr.options.positionClass = 'toast-bottom-right'; - //////////////// + //////////////// - function configureStateHelper() { - routerHelperProvider.configure({ - docTitle: 'NG-Modular: ' - }); - } - } - ``` + function configureStateHelper() { + routerHelperProvider.configure({ + docTitle: 'NG-Modular: ' + }); + } + } + ``` ### 运行代码块 ###### [Style [Y171](#style-y171)] @@ -2298,12 +2328,12 @@ .module('app') .run(runBlock); - runBlock.$inject = ['authenticator', 'translator']; + runBlock.$inject = ['authenticator', 'translator']; - function runBlock(authenticator, translator) { - authenticator.initialize(); - translator.initialize(); - } + function runBlock(authenticator, translator) { + authenticator.initialize(); + translator.initialize(); + } ``` **[返回顶部](#目录)** @@ -2327,7 +2357,6 @@ **[返回顶部](#目录)** ## 测试 - 单元测试有助于保持代码的清晰,因此我加入一些关于单元测试的基础和获取更多信息的链接。 ###用故事来编写测试 @@ -2337,25 +2366,25 @@ *为什么?*:编写测试有助于明确规定你的故事要做什么、不做什么以及你如何判断是否成功。 - ```javascript - it('should have Avengers controller', function() { - //TODO - }); + ```javascript + it('should have Avengers controller', function() { + //TODO + }); - it('should find 1 Avenger when filtered by name', function() { - //TODO - }); + it('should find 1 Avenger when filtered by name', function() { + //TODO + }); - it('should have 10 Avengers', function() { - //TODO (mock data?) - }); + it('should have 10 Avengers', function() { + //TODO (mock data?) + }); - it('should return Avengers via XHR', function() { - //TODO ($httpBackend?) - }); + it('should return Avengers via XHR', function() { + //TODO ($httpBackend?) + }); - // and so on - ``` + // and so on + ``` ###测试库 ###### [Style [Y191](#style-y191)] @@ -2413,15 +2442,15 @@ *为什么?*:测试也是代码,因此要和对待其它生产代码一样重视测试代码的质量。然而,测试框架中允许使用全局变量,例如,在你的测试单例中允许使用this。 - ```javascript - /* jshint -W117, -W030 */ - ``` - 或者你也可以把下面的这几行加入到你的JSHint Options文件中。 + ```javascript + /* jshint -W117, -W030 */ + ``` + 或者你也可以把下面的这几行加入到你的JSHint Options文件中。 - ```javascript - "jasmine": true, - "mocha": true, - ``` + ```javascript + "jasmine": true, + "mocha": true, + ``` ![测试工具](https://raw.githubusercontent.com/johnpapa/angular-styleguide/master/assets/testing-tools.png) @@ -2452,7 +2481,6 @@ /customers.route.spec.js ``` - **[返回顶部](#目录)** ## 动画 @@ -2460,7 +2488,7 @@ ###用法 ###### [Style [Y210](#style-y210)] - - 在view和主要的视觉元素上使用细微的[Angular动画](https://docs.angularjs.org/guide/animations)进行过渡,包括[ngAnimate模块](https://docs.angularjs.org/api/ngAnimate)。三个关键点是细微、平滑、无缝。 + - 在页面过渡时使用[Angular动画](https://docs.angularjs.org/guide/animations),包括[ngAnimate模块](https://docs.angularjs.org/api/ngAnimate)。三个关键点是细微、平滑、无缝。 *为什么?*:使用得当的话能够提高用户体验。 @@ -2488,63 +2516,61 @@ **[返回顶部](#目录)** - ## 注释 -###jsDoc +### jsDoc ###### [Style [Y220](#style-y220)] - - 如果你计划产出一个文档,那么就使用[`jsDoc`](http://usejsdoc.org/)的语法来记录函数名、描述、参数和返回值。使用`@namespace`和`@memberOf`来匹配应用程序结构。 + - 如果你准备做一个文档,那么就使用[`jsDoc`](http://usejsdoc.org/)的语法来记录函数名、描述、参数和返回值。使用`@namespace`和`@memberOf`来匹配应用程序结构。 *为什么?*:你可以从代码中生成(重新生成)文档,而不必从头开始编写文档。 *为什么?*:使用业内通用工具保持了统一性。 - ```javascript - /** - * Logger Factory - * @namespace Factories - */ - (function() { - angular - .module('app') - .factory('logger', logger); - + ```javascript /** - * @name logger - * @namespace Logger - * @desc Application wide logger - * @memberOf Factories + * Logger Factory + * @namespace Factories */ - function logger ($log) { - var service = { - logError: logError - }; - return service; + (function() { + angular + .module('app') + .factory('logger', logger); - //////////// + /** + * @namespace Logger + * @desc Application wide logger + * @memberOf Factories + */ + function logger ($log) { + var service = { + logError: logError + }; + return service; - /** - * @name logError - * @desc Logs errors - * @param {String} msg Message to log - * @returns {String} - * @memberOf Factories.Logger - */ - function logError(msg) { - var loggedMsg = 'Error: ' + msg; - $log.error(loggedMsg); - return loggedMsg; - }; - } - })(); - ``` + //////////// + + /** + * @name logError + * @desc Logs errors + * @param {String} msg Message to log + * @returns {String} + * @memberOf Factories.Logger + */ + function logError(msg) { + var loggedMsg = 'Error: ' + msg; + $log.error(loggedMsg); + return loggedMsg; + }; + } + })(); + ``` **[返回顶部](#目录)** ## JS Hint -###使用一个选项文件 +###使用一个Options文件 ###### [Style [Y230](#style-y230)] - 用JS Hint来分析你的JavaScript代码,确保你自定义了JS Hint选项文件并且包含在源控制里。详细信息:[JS Hint文档](http://www.jshint.com/docs/)。 @@ -2553,69 +2579,69 @@ *为什么?*:统一性。 - ```javascript - { - "bitwise": true, - "camelcase": true, - "curly": true, - "eqeqeq": true, - "es3": false, - "forin": true, - "freeze": true, - "immed": true, - "indent": 4, - "latedef": "nofunc", - "newcap": true, - "noarg": true, - "noempty": true, - "nonbsp": true, - "nonew": true, - "plusplus": false, - "quotmark": "single", - "undef": true, - "unused": false, - "strict": false, - "maxparams": 10, - "maxdepth": 5, - "maxstatements": 40, - "maxcomplexity": 8, - "maxlen": 120, - - "asi": false, - "boss": false, - "debug": false, - "eqnull": true, - "esnext": false, - "evil": false, - "expr": false, - "funcscope": false, - "globalstrict": false, - "iterator": false, - "lastsemic": false, - "laxbreak": false, - "laxcomma": false, - "loopfunc": true, - "maxerr": false, - "moz": false, - "multistr": false, - "notypeof": false, - "proto": false, - "scripturl": false, - "shadow": false, - "sub": true, - "supernew": false, - "validthis": false, - "noyield": false, - - "browser": true, - "node": true, - - "globals": { - "angular": false, - "$": false - } - } - ``` + ```javascript + { + "bitwise": true, + "camelcase": true, + "curly": true, + "eqeqeq": true, + "es3": false, + "forin": true, + "freeze": true, + "immed": true, + "indent": 4, + "latedef": "nofunc", + "newcap": true, + "noarg": true, + "noempty": true, + "nonbsp": true, + "nonew": true, + "plusplus": false, + "quotmark": "single", + "undef": true, + "unused": false, + "strict": false, + "maxparams": 10, + "maxdepth": 5, + "maxstatements": 40, + "maxcomplexity": 8, + "maxlen": 120, + + "asi": false, + "boss": false, + "debug": false, + "eqnull": true, + "esnext": false, + "evil": false, + "expr": false, + "funcscope": false, + "globalstrict": false, + "iterator": false, + "lastsemic": false, + "laxbreak": false, + "laxcomma": false, + "loopfunc": true, + "maxerr": false, + "moz": false, + "multistr": false, + "notypeof": false, + "proto": false, + "scripturl": false, + "shadow": false, + "sub": true, + "supernew": false, + "validthis": false, + "noyield": false, + + "browser": true, + "node": true, + + "globals": { + "angular": false, + "$": false + } + } + ``` **[返回顶部](#目录)** @@ -2716,19 +2742,19 @@ *为什么?*:提供一种注入到供应库的方法,否则就是全局变量。通过让你更容易地了解你的组件之间的依赖关系来提高代码的可测试性。这还允许你模拟这些依赖关系,这是很有意义的。 - ```javascript - // constants.js + ```javascript + // constants.js - /* global toastr:false, moment:false */ - (function() { - 'use strict'; + /* global toastr:false, moment:false */ + (function() { + 'use strict'; - angular - .module('app.core') - .constant('toastr', toastr) - .constant('moment', moment); - })(); - ``` + angular + .module('app.core') + .constant('toastr', toastr) + .constant('moment', moment); + })(); + ``` ###### [Style [Y241](#style-y241)] @@ -2770,16 +2796,20 @@ - 重启Sublime - 在JavaScript文件中输入下面的命令然后按下`TAB`键即可: - ```javascript - ngcontroller // creates an Angular controller - ngdirective // creates an Angular directive - ngfactory // creates an Angular factory - ngmodule // creates an Angular module - ``` + ```javascript + ngcontroller // creates an Angular controller + ngdirective // creates an Angular directive + ngfactory // creates an Angular factory + ngmodule // creates an Angular module + ngservice // creates an Angular service + ngfilter // creates an Angular filter + ``` ###Visual Studio ###### [Style [Y251](#style-y251)] + - Angular文件遵循[SideWaffle](http://www.sidewaffle.com)所介绍的风格指南。 + - 下载Visual Studio扩展文件[SideWaffle](http://www.sidewaffle.com) - 运行下载的vsix文件 - 重启Visual Studio @@ -2804,23 +2834,58 @@ ### Atom ###### [Style [Y253](#style-y253)] - - Angular snippets that follow these styles and guidelines. + - Angular片段遵循以下指南。 ``` apm install angularjs-styleguide-snippets ``` - or - - Open Atom, then open the Package Manager (Packages -> Settings View -> Install Packages/Themes) - - Search for the package 'angularjs-styleguide-snippets' - - Click 'Install' to install the package + 或 + - 打开Atom,打开包管理器(Packages -> Settings View -> Install Packages/Themes) + - 搜索'angularjs-styleguide-snippets' + - 点击'Install' 进行安装 - - In a JavaScript file type these commands followed by a `TAB` + - JavaScript文件中输入以下命令后以`TAB`结束 ```javascript ngcontroller // creates an Angular controller ngdirective // creates an Angular directive ngfactory // creates an Angular factory ngmodule // creates an Angular module + ngservice // creates an Angular service + ngfilter // creates an Angular filter ``` + +### Brackets +###### [Style [Y254](#style-y254)] + + - Angular代码片段遵循以下风格指南。 + + - 下载[Brackets Angular snippets](assets/brackets-angular-snippets.yaml?raw=true) + - 拓展管理器( File > Extension manager ) + - 安装['Brackets Snippets (by edc)'](https://github.com/chuyik/brackets-snippets) + - Click the light bulb in brackets' right gutter + - Click `Settings` and then `Import` + - Choose the file and select to skip or override + - Click `Start Import` + + - JavaScript文件中输入以下命令后以`TAB`结束 + + ```javascript + // These are full file snippets containing an IIFE + ngcontroller // creates an Angular controller + ngdirective // creates an Angular directive + ngfactory // creates an Angular factory + ngapp // creates an Angular module setter + ngservice // creates an Angular service + ngfilter // creates an Angular filter + + // These are partial snippets intended to chained + ngmodule // creates an Angular module getter + ngstate // creates an Angular UI Router state defintion + ngconfig // defines a configuration phase function + ngrun // defines a run phase function + ngroute // creates an Angular routeProvider + ``` + **[返回顶部](#目录)** ## Yeoman Generator @@ -2846,22 +2911,23 @@ ``` yo hottowel helloWorld ``` + **[返回顶部](#目录)** ## 路由 客户端路由对于在视图和很多小模板和指令组成的构成视图中创建导航是非常重要的。 + ###### [Style [Y270](#style-y270)] - 用[AngularUI Router](http://angular-ui.github.io/ui-router/)来做路由控制。 *为什么?*:它包含了Angular路由的所有特性,并且增加了一些额外的特性,如嵌套路由和状态。 - *为什么?*:语法和Angular路由很想,很容易迁移到UI Router。 + *为什么?*:语法和Angular路由很像,很容易迁移到UI Router。 ###### [Style [Y271](#style-y271)] - - Define routes for views in the module where they exist. - Each module should contain the routes for the views in the module. + - Define routes for views in the module where they exist,Each module should contain the routes for the views in the module. *为什么?*:每个模块应该是独立的。 @@ -2915,7 +2981,6 @@ *贡献代码到这个仓库就意味着你同意了本仓库的许可证内容* - ###过程 1. 在Github Issue中讨论这个问题。 2. 拉取一个pull request,引用这个问题,解释你做的修改和为什么要这样做。 @@ -2929,5 +2994,24 @@ Copyright (c) 2014-2015 [John Papa](http://johnpapa.net) +### (The MIT License) +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. **[返回顶部](#目录)** From b12e18934f9461be0aa5e9086f65cb75446ec501 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=B5=B5=E5=8F=AF?= Date: Thu, 9 Apr 2015 12:05:26 +0800 Subject: [PATCH 271/567] change transition of style guide --- i18n/zh-CN.md | 44 ++++++++++++++++++++++---------------------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/i18n/zh-CN.md b/i18n/zh-CN.md index 8e72ffe1..b18619de 100644 --- a/i18n/zh-CN.md +++ b/i18n/zh-CN.md @@ -1,29 +1,29 @@ -# Angular风格指南 +# Angular规范 -*Angular风格指南[@john_papa](//twitter.com/john_papa)* +*Angular规范[@john_papa](//twitter.com/john_papa)* -*由[kerncink](https://github.com/natee)翻译* +*由[ZhaoKe](https://github.com/natee)翻译* >The [original English version](http://jpapa.me/ngstyles) is the source of truth, as it is maintained and updated first. -如果你正在寻找一些关于语法、约定和结构化的Angular应用的一个有建设性的风格指南,那么你来对地方了。这里所包含的风格是基于我在团队中使用[Angular](//angularjs.org)的一些经验、一些演讲和[Pluralsight培训课程](http://pluralsight.com/training/Authors/Details/john-papa)。 +如果你正在寻找一些关于语法、约定和结构化的Angular应用的一个有建设性的规范,那么你来对地方了。这里所包含的内容是基于我在团队中使用[Angular](//angularjs.org)的一些经验、一些演讲和[Pluralsight培训课程](http://pluralsight.com/training/Authors/Details/john-papa)。 -这个风格指南的目的是为构建Angular应用提供指导,当然更加重要的是让大家知道我为什么要选择它们。 +这个规范的目的是为构建Angular应用提供指导,当然更加重要的是让大家知道我为什么要选择它们。 ->如果你喜欢这个指南,请在Pluralsight看看[Angular Patterns: Clean Code](http://jpapa.me/ngclean)。 +>如果你喜欢这个规范,请在Pluralsight看看[Angular Patterns: Clean Code](http://jpapa.me/ngclean)。 [![Angular Patterns: Clean Code](https://raw.githubusercontent.com/johnpapa/angular-styleguide/master/assets/ng-clean-code-banner.png)](http://jpapa.me/ngclean) ## Community Awesomeness and Credit -Angular社区是一个热衷于分享经验的令人难以置信的社区,尽管Todd Motto(他是我的一个朋友,也是Angular专家)和我合作了多种风格和惯例,但是我们也存在着一些分歧。我鼓励你去看看[Todd的指南](https://github.com/toddmotto/angularjs-styleguide),在那里你能看到我们之间的区别。 +Angular社区是一个热衷于分享经验的令人难以置信的社区,尽管Todd Motto(他是我的一个朋友,也是Angular专家)和我合作了多种规范和惯例,但是我们也存在着一些分歧。我鼓励你去看看[Todd的指南](https://github.com/toddmotto/angularjs-styleguide),在那里你能看到我们之间的区别。 -我的许多风格都是从大量的程序会话[Ward Bell](http://twitter.com/wardbell)和我所拥有的而来的,我的好友Ward也影响了本指南的最终演变。 +我的许多规范都是从大量的程序会话[Ward Bell](http://twitter.com/wardbell)和我所拥有的而来的,我的好友Ward也影响了本规范的最终演变。 -## 在示例App中了解这些风格 +## 在示例App中了解这些规范 看示例代码有助于你更好地理解,你可以在`modular`文件夹下找到[命名为modular的示例应用程序](https://github.com/johnpapa/ng-demos),随便克隆。 ##翻译 -[Angular风格指南翻译版本](https://github.com/johnpapa/angular-styleguide/tree/master/i18n)。 +[Angular规范翻译版本](https://github.com/johnpapa/angular-styleguide/tree/master/i18n)。 ##目录 1. [单一职责](#单一职责) @@ -170,7 +170,7 @@ Angular社区是一个热衷于分享经验的令人难以置信的社区,尽 })(); ``` - - 注:为了简洁起见,本指南余下的示例中将会省略IIFE语法。 + - 注:为了简洁起见,本规范余下的示例中将会省略IIFE语法。 - 注:IIFE阻止了测试代码访问私有成员(正则表达式、helper函数等),这对于自身测试是非常友好的。然而你可以把这些私有成员暴露到可访问成员中进行测试,例如把私有成员(正则表达式、helper函数等)放到factory或是constant中。 @@ -2106,7 +2106,7 @@ Angular社区是一个热衷于分享经验的令人难以置信的社区,尽 ## 应用程序结构 -###总指南 +###总规范 ###### [Style [Y150](#style-y150)] - 有实施的短期看法和长远的目标,换句话说,从小处入手,但是要记住app的走向。app的所有代码都在一个叫做`app`的根目录下,所有的内容都遵循一个功能一个文件,每一个controller、service、module、view都是独立的文件。第三方脚本存放在另外的根文件夹中(`bower_components`、`scripts`、`lib`)。 @@ -2127,7 +2127,7 @@ Angular社区是一个热衷于分享经验的令人难以置信的社区,尽 *为什么?*:开发者可以快速定位代码、快速识别文件代表的意思,结构尽可能平直,没有重复,没有多余名字。 - *为什么?*:LIFT指南都包括在内。 + *为什么?*:LIFT规范都包括在内。 *为什么?*:通过组织内容和让它们保持和LIFT指导准则一致,帮助降低应用程序变得混乱的可能性。 @@ -2650,7 +2650,7 @@ Angular社区是一个热衷于分享经验的令人难以置信的社区,尽 ### 用一个Options文件 ###### [Style [Y235](#style-y235)] - - 使用JSCS检查代码风格,确保你的代码控制中有定制的JSCS options文件,在这里[JSCS docs](http://www.jscs.info)查看更多信息。 + - 使用JSCS检查代码规范,确保你的代码控制中有定制的JSCS options文件,在这里[JSCS docs](http://www.jscs.info)查看更多信息。 *为什么?*:提交代码前第一时间提供一个预警。 @@ -2784,12 +2784,12 @@ Angular社区是一个热衷于分享经验的令人难以置信的社区,尽 **[返回顶部](#目录)** ## 文件模板和片段 -使用文件模板和片段帮助保持一致性的风格,这里有针对一些web开发的编辑器和IDE的模板和(或)片段。 +为了遵循一致的规范和模式,使用文件模板和片段,这里有针对一些web开发的编辑器和IDE的模板和(或)片段。 ###Sublime Text ###### [Style [Y250](#style-y250)] - - Angular片段遵循这些风格指南。 + - Angular片段遵循这些规范。 - 下载[Sublime Angular snippets](assets/sublime-angular-snippets?raw=true) - 把它放到Packages文件夹中 @@ -2808,7 +2808,7 @@ Angular社区是一个热衷于分享经验的令人难以置信的社区,尽 ###Visual Studio ###### [Style [Y251](#style-y251)] - - Angular文件遵循[SideWaffle](http://www.sidewaffle.com)所介绍的风格指南。 + - Angular文件遵循[SideWaffle](http://www.sidewaffle.com)所介绍的规范。 - 下载Visual Studio扩展文件[SideWaffle](http://www.sidewaffle.com) - 运行下载的vsix文件 @@ -2834,7 +2834,7 @@ Angular社区是一个热衷于分享经验的令人难以置信的社区,尽 ### Atom ###### [Style [Y253](#style-y253)] - - Angular片段遵循以下指南。 + - Angular片段遵循以下规范。 ``` apm install angularjs-styleguide-snippets ``` @@ -2857,7 +2857,7 @@ Angular社区是一个热衷于分享经验的令人难以置信的社区,尽 ### Brackets ###### [Style [Y254](#style-y254)] - - Angular代码片段遵循以下风格指南。 + - Angular代码片段遵循以下规范。 - 下载[Brackets Angular snippets](assets/brackets-angular-snippets.yaml?raw=true) - 拓展管理器( File > Extension manager ) @@ -2891,7 +2891,7 @@ Angular社区是一个热衷于分享经验的令人难以置信的社区,尽 ## Yeoman Generator ###### [Style [Y260](#style-y260)] -你可以使用[HotTowel yeoman generator](http://jpapa.me/yohottowel)来创建一个遵循本指南的Angular起步应用。 +你可以使用[HotTowel yeoman generator](http://jpapa.me/yohottowel)来创建一个遵循本规范的Angular入门应用。 1. 安装generator-hottowel @@ -2977,7 +2977,7 @@ Angular社区是一个热衷于分享经验的令人难以置信的社区,尽 ## 贡献 -先打开一个问题讨论潜在的变化和增加。如果你对这篇指南有问题,随时在仓库中提出问题。如果你发现了一个错字,创建一个pull request。这样做是为了保持内容的更新,使用github的原生功能通过问题和PR来帮助讲述这个故事,具体做法可以google一下。为什么?因为如果你有问题,其他人可能有同样的问题,你在这里可以学到如何贡献。 +先打开一个问题讨论潜在的变化和增加。如果你对这篇规范有任何疑惑,随时在仓库中提出问题。如果你发现了一个错字,创建一个pull request。这样做是为了保持内容的更新,使用github的原生功能通过问题和PR来帮助讲述这个故事,具体做法可以google一下。为什么?因为如果你有问题,其他人可能有同样的问题,你在这里可以学到如何贡献。 *贡献代码到这个仓库就意味着你同意了本仓库的许可证内容* @@ -2988,7 +2988,7 @@ Angular社区是一个热衷于分享经验的令人难以置信的社区,尽 ## 许可证 - - **tldr;** 如果可以的话,使用本指南的时候还是指明归属吧。 + - **tldr;** 如果可以的话,使用本规范的时候还是指明归属吧。 ### Copyright From 526ab9b1c54173cb0da88ac5e567bbdb4ca2d42f Mon Sep 17 00:00:00 2001 From: angelochiello Date: Thu, 9 Apr 2015 09:50:24 +0200 Subject: [PATCH 272/567] [it-IT] Update as PR #361 Updated as PR: #361 "zh-CN update" --- i18n/it-IT.md | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/i18n/it-IT.md b/i18n/it-IT.md index c8fd2d58..6cb815eb 100644 --- a/i18n/it-IT.md +++ b/i18n/it-IT.md @@ -903,7 +903,7 @@ Nonostante questa guida spieghi i *cosa*, *come* e *perché*, trovo che sia di a *Perché?*: Ciò rende più semplice da testare (vere o simulate) le chiamate ai dati quando si testa un controller che usa un servizio ai dati. - *Perché?*: L'implementazione di un servizio ai dati può avere del codice molto specifico su come trattare i repository dei dati. Questo può includere header, come comunicare con i dati o altri servizi quali $http. Separare la logica in un servizio ai dati incapsula questa logica in un posto unico nascondendo l'implementazione ai consumatori esterni (forse un controller), rendendo inoltre più semplice cambiarne l'implementazione. + *Perché?*: L'implementazione di un servizio ai dati può avere del codice molto specifico su come trattare i repository dei dati. Questo può includere header, come comunicare con i dati o altri servizi quali `$http`. Separare la logica in un servizio ai dati incapsula questa logica in un posto unico nascondendo l'implementazione ai consumatori esterni (forse un controller), rendendo inoltre più semplice cambiarne l'implementazione. ```javascript /* consigliato */ @@ -1015,7 +1015,7 @@ Nonostante questa guida spieghi i *cosa*, *come* e *perché*, trovo che sia di a } ``` - **[Torna all'inizio](#tavola-dei-contenuti)** +**[Torna all'inizio](#tavola-dei-contenuti)** ## Directive ### Limite di 1 per file @@ -1026,6 +1026,8 @@ Nonostante questa guida spieghi i *cosa*, *come* e *perché*, trovo che sia di a *Perché?*: È facile mescolare tutte le directive in un unico file ma difficoltoso da separarle così che alcune siano condivise tra le applicazioni, alcune tra moduli, altre solo per un module. *Perché?*: Una directive per file è semplice da manutenere. + + > Nota: "**Best Practice**: Le directive dovrebbero fare pulizia alla fine. Puoi usare `element.on('$destroy', ...)` oppure `scope.$on('$destroy', ...)` per lanciare una funzione di pulizia quando la directive è rimossa" ... dalla documentazione di Angular. ```javascript /* evitare */ @@ -1315,7 +1317,6 @@ Nonostante questa guida spieghi i *cosa*, *come* e *perché*, trovo che sia di a **[Torna all'inizio](#tavola-dei-contenuti)** ## Risoluzioni di promesse per un controller - ### Promesse di attivazione di un Controller ###### [Stile [Y080](#stile-y080)] @@ -1420,9 +1421,8 @@ Nonostante questa guida spieghi i *cosa*, *come* e *perché*, trovo che sia di a Avengers.$inject = ['moviesPrepService']; function Avengers(moviesPrepService) { - /* jshint validthis:true */ - var vm = this; - vm.movies = moviesPrepService.movies; + var vm = this; + vm.movies = moviesPrepService.movies; } ``` @@ -2201,6 +2201,7 @@ Nonostante questa guida spieghi i *cosa*, *come* e *perché*, trovo che sia di a app.module.js app.config.js app.routes.js + directives.js controllers/ attendees.js session-detail.js @@ -2341,12 +2342,12 @@ Nonostante questa guida spieghi i *cosa*, *come* e *perché*, trovo che sia di a .module('app') .run(runBlock); - runBlock.$inject = ['authenticator', 'translator']; + runBlock.$inject = ['authenticator', 'translator']; - function runBlock(authenticator, translator) { - authenticator.initialize(); - translator.initialize(); - } + function runBlock(authenticator, translator) { + authenticator.initialize(); + translator.initialize(); + } ``` **[Torna all'inizio](#tavola-dei-contenuti)** From 644f0e4791bba840a7da9a973b5b2f45d10af3c8 Mon Sep 17 00:00:00 2001 From: John Papa Date: Fri, 10 Apr 2015 07:55:38 -0400 Subject: [PATCH 273/567] added code for style 270 with routerHelperProvider to set routes during the run phase and across files and modules --- README.md | 70 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 70 insertions(+) diff --git a/README.md b/README.md index 3e44401d..a133eee2 100644 --- a/README.md +++ b/README.md @@ -2923,6 +2923,76 @@ Client-side routing is important for creating a navigation flow between views an *Why?*: The syntax is quite similar to the Angular router and is easy to migrate to UI Router. + - Note: You can use a provider such as the `routerHelperProvider` shown below to help configure states across files, during the run phase. + + ```javascript + // customers.routes.js + angular + .module('app.customers') + .run(appRun); + + /* @ngInject */ + function appRun(routerHelper) { + routerHelper.configureStates(getStates()); + } + + function getStates() { + return [ + { + state: 'customer', + config: { + abstract: true, + template: '', + url: '/customer' + } + } + ]; + } + ``` + + ```javascript + // routerHelperProvider.js + angular + .module('blocks.router') + .provider('routerHelper', routerHelperProvider); + + routerHelperProvider.$inject = ['$locationProvider', '$stateProvider', '$urlRouterProvider']; + /* @ngInject */ + function routerHelperProvider($locationProvider, $stateProvider, $urlRouterProvider) { + /* jshint validthis:true */ + this.$get = RouterHelper; + + $locationProvider.html5Mode(true); + + RouterHelper.$inject = ['$state']; + /* @ngInject */ + function RouterHelper($state) { + var hasOtherwise = false; + + var service = { + configureStates: configureStates, + getStates: getStates + }; + + return service; + + /////////////// + + function configureStates(states, otherwisePath) { + states.forEach(function(state) { + $stateProvider.state(state.state, state.config); + }); + if (otherwisePath && !hasOtherwise) { + hasOtherwise = true; + $urlRouterProvider.otherwise(otherwisePath); + } + } + + function getStates() { return $state.get(); } + } + } + ``` + ###### [Style [Y271](#style-y271)] - Define routes for views in the module where they exist. Each module should contain the routes for the views in the module. From 49146cf6519443e4ec0ccad8bae6aba4fd1cc2c8 Mon Sep 17 00:00:00 2001 From: Jeff Sheets Date: Tue, 14 Apr 2015 12:08:53 -0500 Subject: [PATCH 274/567] Fix moviesPrepService typo in Resolve section Fix moviesPrepService typo in Route Resolve section --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index da08f7e2..41435abb 100644 --- a/README.md +++ b/README.md @@ -1444,7 +1444,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see }); } - function moviePrepService(movieService) { + function moviesPrepService(movieService) { return movieService.getMovies(); } From 366400068c644105fd01cb2eadf940398235f2b7 Mon Sep 17 00:00:00 2001 From: Jeff Sheets Date: Tue, 14 Apr 2015 21:39:30 -0500 Subject: [PATCH 275/567] More moviePrepService typo fixes Renamed moviePrepService lines to moviesPrepService to match the rest of the code --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 41435abb..3b807055 100644 --- a/README.md +++ b/README.md @@ -1585,13 +1585,13 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see controller: 'AvengersController', controllerAs: 'vm', resolve: { - moviesPrepService: moviePrepService + moviesPrepService: moviesPrepService } }); } - moviePrepService.$inject = ['movieService']; - function moviePrepService(movieService) { + moviesPrepService.$inject = ['movieService']; + function moviesPrepService(movieService) { return movieService.getMovies(); } ``` From df9fb65197b4fe6261ffdfe6d75eefbee04c1fed Mon Sep 17 00:00:00 2001 From: Tomoyuki Kashiro Date: Mon, 20 Apr 2015 23:00:49 +0900 Subject: [PATCH 276/567] add snippet for vim --- README.md | 17 +++++++++ .../angular.controller.snip | 22 ++++++++++++ .../angular.directive.snip | 35 +++++++++++++++++++ .../vim-angular-snippets/angular.factory.snip | 22 ++++++++++++ .../vim-angular-snippets/angular.filter.snip | 19 ++++++++++ .../vim-angular-snippets/angular.module.snip | 10 ++++++ .../vim-angular-snippets/angular.service.snip | 19 ++++++++++ 7 files changed, 144 insertions(+) create mode 100644 assets/vim-angular-snippets/angular.controller.snip create mode 100644 assets/vim-angular-snippets/angular.directive.snip create mode 100644 assets/vim-angular-snippets/angular.factory.snip create mode 100644 assets/vim-angular-snippets/angular.filter.snip create mode 100644 assets/vim-angular-snippets/angular.module.snip create mode 100644 assets/vim-angular-snippets/angular.service.snip diff --git a/README.md b/README.md index 3b807055..88fda2f4 100644 --- a/README.md +++ b/README.md @@ -2886,6 +2886,23 @@ Use file templates or snippets to help follow consistent styles and patterns. He ngtranslate // uses $translate service with its promise ``` +### vim +###### [Style [Y255](#style-y255)] + + - vim snippets that follow these styles and guidelines. + + - Download the [vim Angular snippets](https://github.com/kashiro/angular-styleguide/tree/master/assets/vim-angular-snippets) + - set [neosnippet.vim](https://github.com/Shougo/neosnippet.vim) + - copy snippets to snippet directory + + ```javascript + ngcontroller // creates an Angular controller + ngdirective // creates an Angular directive + ngfactory // creates an Angular factory + ngmodule // creates an Angular module + ngservice // creates an Angular service + ngfilter // creates an Angular filter + **[Back to top](#table-of-contents)** ## Yeoman Generator diff --git a/assets/vim-angular-snippets/angular.controller.snip b/assets/vim-angular-snippets/angular.controller.snip new file mode 100644 index 00000000..f8a0cc7c --- /dev/null +++ b/assets/vim-angular-snippets/angular.controller.snip @@ -0,0 +1,22 @@ +snippet ngcontroller +options head + (function() { + 'use strict'; + + angular + .module('${1:module}') + .controller('${2:Controller}Controller', $2Controller); + + /* @ngInject */ + function $2Controller(${3:dependencies}) { + var vm = this; + vm.title = '$2Controller'; + + activate(); + + //////////////// + + function activate() { + } + } + })(); diff --git a/assets/vim-angular-snippets/angular.directive.snip b/assets/vim-angular-snippets/angular.directive.snip new file mode 100644 index 00000000..c8335fa5 --- /dev/null +++ b/assets/vim-angular-snippets/angular.directive.snip @@ -0,0 +1,35 @@ +snippet ngdirective +options head + (function() { + 'use strict'; + + angular + .module('${1:module}') + .directive('${2:directive}', $2); + + /* @ngInject */ + function $2(${3:dependencies}) { + // Usage: + // + // Creates: + // + var directive = { + bindToController: true, + controller: ${4:Controller}, + controllerAs: '${5:vm}', + link: link, + restrict: 'A', + scope: { + } + }; + return directive; + + function link(scope, element, attrs) { + } + } + + /* @ngInject */ + function $4() { + + } + })(); diff --git a/assets/vim-angular-snippets/angular.factory.snip b/assets/vim-angular-snippets/angular.factory.snip new file mode 100644 index 00000000..83817faa --- /dev/null +++ b/assets/vim-angular-snippets/angular.factory.snip @@ -0,0 +1,22 @@ +snippet ngfactory +options head + (function() { + 'use strict'; + + angular + .module('${1:module}') + .factory('${2:factory}', $2); + + /* @ngInject */ + function $2(${3:dependencies}) { + var service = { + ${4:func}: $4 + }; + return service; + + //////////////// + + function $4() { + } + } + })(); diff --git a/assets/vim-angular-snippets/angular.filter.snip b/assets/vim-angular-snippets/angular.filter.snip new file mode 100644 index 00000000..4999f3b8 --- /dev/null +++ b/assets/vim-angular-snippets/angular.filter.snip @@ -0,0 +1,19 @@ +snippet ngfilter +options head + (function() { + 'use strict'; + + angular + .module('${1:module}') + .filter('${2:filter}', $2); + + function $2() { + return $2Filter; + + //////////////// + function $2Filter(${3:params}) { + return $3; + }; + } + + })(); diff --git a/assets/vim-angular-snippets/angular.module.snip b/assets/vim-angular-snippets/angular.module.snip new file mode 100644 index 00000000..fe43cd48 --- /dev/null +++ b/assets/vim-angular-snippets/angular.module.snip @@ -0,0 +1,10 @@ +snippet ngmodule +options head + (function() { + 'use strict'; + + angular + .module('${1:module}', [ + '${2:dependencies}' + ]); + })(); diff --git a/assets/vim-angular-snippets/angular.service.snip b/assets/vim-angular-snippets/angular.service.snip new file mode 100644 index 00000000..99d15fc1 --- /dev/null +++ b/assets/vim-angular-snippets/angular.service.snip @@ -0,0 +1,19 @@ +snippet ngservice +options head + (function() { + 'use strict'; + + angular + .module('${1:module}') + .service('${2:Service}', $2); + + /* @ngInject */ + function $2(${3:dependencies}) { + this.${4:func} = $4; + + //////////////// + + function $4() { + } + } + })(); From 3d4d49533e9f8027ad1e8f47337e6ab4455ece62 Mon Sep 17 00:00:00 2001 From: Avi levy Date: Mon, 20 Apr 2015 19:23:36 +0300 Subject: [PATCH 277/567] Typo fix --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 3b807055..18f6183c 100644 --- a/README.md +++ b/README.md @@ -2109,7 +2109,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see ### Overall Guidelines ###### [Style [Y150](#style-y150)] - - Have a near term view of implementation and a long term vision. In other words, start small and but keep in mind on where the app is heading down the road. All of the app's code goes in a root folder named `app`. All content is 1 feature per file. Each controller, service, module, view is in its own file. All 3rd party vendor scripts are stored in another root folder and not in the `app` folder. I didn't write them and I don't want them cluttering my app (`bower_components`, `scripts`, `lib`). + - Have a near term view of implementation and a long term vision. In other words, start small but keep in mind on where the app is heading down the road. All of the app's code goes in a root folder named `app`. All content is 1 feature per file. Each controller, service, module, view is in its own file. All 3rd party vendor scripts are stored in another root folder and not in the `app` folder. I didn't write them and I don't want them cluttering my app (`bower_components`, `scripts`, `lib`). Note: Find more details and reasoning behind the structure at [this original post on application structure](http://www.johnpapa.net/angular-app-structuring-guidelines/). From e7678d50066af1ae2f7dc6c14d0bb7221adf2732 Mon Sep 17 00:00:00 2001 From: wmalgoire Date: Tue, 21 Apr 2015 09:25:16 +0200 Subject: [PATCH 278/567] Filling dependencies with regular expressions --- .../sublime-angular-snippets/angular.controller.sublime-snippet | 2 ++ .../sublime-angular-snippets/angular.directive.sublime-snippet | 2 ++ assets/sublime-angular-snippets/angular.factory.sublime-snippet | 2 ++ assets/sublime-angular-snippets/angular.service.sublime-snippet | 2 ++ 4 files changed, 8 insertions(+) diff --git a/assets/sublime-angular-snippets/angular.controller.sublime-snippet b/assets/sublime-angular-snippets/angular.controller.sublime-snippet index de0a18ca..6201bb01 100644 --- a/assets/sublime-angular-snippets/angular.controller.sublime-snippet +++ b/assets/sublime-angular-snippets/angular.controller.sublime-snippet @@ -6,6 +6,8 @@ .module('${1:module}') .controller('${2:Controller}', ${2:Controller}); + ${2:controller}.\$inject = [${3/(\$(\w+)|\w+)/'$1'/g}]; + /* @ngInject */ function ${2:Controller}(${3:dependencies}) { var vm = this; diff --git a/assets/sublime-angular-snippets/angular.directive.sublime-snippet b/assets/sublime-angular-snippets/angular.directive.sublime-snippet index 62a9e127..f2bcf719 100644 --- a/assets/sublime-angular-snippets/angular.directive.sublime-snippet +++ b/assets/sublime-angular-snippets/angular.directive.sublime-snippet @@ -6,6 +6,8 @@ .module('${1:module}') .directive('${2:directive}', ${2:directive}); + ${2:directive}.\$inject = [${3/(\$(\w+)|\w+)/'$1'/g}]; + /* @ngInject */ function ${2:directive} (${3:dependencies}) { // Usage: diff --git a/assets/sublime-angular-snippets/angular.factory.sublime-snippet b/assets/sublime-angular-snippets/angular.factory.sublime-snippet index 17da8d00..94dab353 100644 --- a/assets/sublime-angular-snippets/angular.factory.sublime-snippet +++ b/assets/sublime-angular-snippets/angular.factory.sublime-snippet @@ -6,6 +6,8 @@ .module('${1:module}') .factory('${2:factory}', ${2:factory}); + ${2:factory}.\$inject = [${3/(\$(\w+)|\w+)/'$1'/g}]; + /* @ngInject */ function ${2:Factory}(${3:dependencies}) { var service = { diff --git a/assets/sublime-angular-snippets/angular.service.sublime-snippet b/assets/sublime-angular-snippets/angular.service.sublime-snippet index aa2bc250..e980c4b1 100644 --- a/assets/sublime-angular-snippets/angular.service.sublime-snippet +++ b/assets/sublime-angular-snippets/angular.service.sublime-snippet @@ -6,6 +6,8 @@ .module('${1:module}') .service('${2:Service}', ${2:Service}); + ${2:Service}.\$inject = [${3/(\$(\w+)|\w+)/'$1'/g}]; + /* @ngInject */ function ${2:Service}(${3:dependencies}) { this.${4:func} = ${4:func}; From afdf30df9d1a651c6c21d9c28c16652b3a1b4683 Mon Sep 17 00:00:00 2001 From: wmalgoire Date: Tue, 21 Apr 2015 09:27:50 +0200 Subject: [PATCH 279/567] Fixed Controller PascalCase --- .../sublime-angular-snippets/angular.controller.sublime-snippet | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets/sublime-angular-snippets/angular.controller.sublime-snippet b/assets/sublime-angular-snippets/angular.controller.sublime-snippet index 6201bb01..5e3c7c5f 100644 --- a/assets/sublime-angular-snippets/angular.controller.sublime-snippet +++ b/assets/sublime-angular-snippets/angular.controller.sublime-snippet @@ -6,7 +6,7 @@ .module('${1:module}') .controller('${2:Controller}', ${2:Controller}); - ${2:controller}.\$inject = [${3/(\$(\w+)|\w+)/'$1'/g}]; + ${2:Controller}.\$inject = [${3/(\$(\w+)|\w+)/'$1'/g}]; /* @ngInject */ function ${2:Controller}(${3:dependencies}) { From f188bea4585ce971dfccb1cd944ff10f6112e900 Mon Sep 17 00:00:00 2001 From: reflexdemon Date: Tue, 21 Apr 2015 07:05:33 -0400 Subject: [PATCH 280/567] Added the end code block --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 18b1699f..1f973d9a 100644 --- a/README.md +++ b/README.md @@ -2902,7 +2902,7 @@ Use file templates or snippets to help follow consistent styles and patterns. He ngmodule // creates an Angular module ngservice // creates an Angular service ngfilter // creates an Angular filter - + ``` **[Back to top](#table-of-contents)** ## Yeoman Generator From 4fcb00eebcd9474cc7a08c8cfb04b843432fbb2c Mon Sep 17 00:00:00 2001 From: Tomoyuki Kashiro Date: Tue, 21 Apr 2015 22:06:59 +0900 Subject: [PATCH 281/567] modify vim snippets link --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 18b1699f..b674a9fd 100644 --- a/README.md +++ b/README.md @@ -2891,7 +2891,7 @@ Use file templates or snippets to help follow consistent styles and patterns. He - vim snippets that follow these styles and guidelines. - - Download the [vim Angular snippets](https://github.com/kashiro/angular-styleguide/tree/master/assets/vim-angular-snippets) + - Download the [vim Angular snippets](assets/vim-angular-snippets?raw=true) - set [neosnippet.vim](https://github.com/Shougo/neosnippet.vim) - copy snippets to snippet directory From 8110d0503a6c28712c51ab2baf982f65ce83aaaa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=B5=B5=E5=8F=AF?= Date: Mon, 27 Apr 2015 19:03:29 +0800 Subject: [PATCH 282/567] update to #381 --- i18n/zh-CN.md | 95 ++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 91 insertions(+), 4 deletions(-) diff --git a/i18n/zh-CN.md b/i18n/zh-CN.md index b18619de..fcfdbbf0 100644 --- a/i18n/zh-CN.md +++ b/i18n/zh-CN.md @@ -1444,7 +1444,7 @@ Angular社区是一个热衷于分享经验的令人难以置信的社区,尽 }); } - function moviePrepService(movieService) { + function moviesPrepService(movieService) { return movieService.getMovies(); } @@ -1585,13 +1585,13 @@ Angular社区是一个热衷于分享经验的令人难以置信的社区,尽 controller: 'AvengersController', controllerAs: 'vm', resolve: { - moviesPrepService: moviePrepService + moviesPrepService: moviesPrepService } }); } - moviePrepService.$inject = ['movieService']; - function moviePrepService(movieService) { + moviesPrepService.$inject = ['movieService']; + function moviesPrepService(movieService) { return movieService.getMovies(); } ``` @@ -2886,6 +2886,23 @@ Angular社区是一个热衷于分享经验的令人难以置信的社区,尽 ngroute // creates an Angular routeProvider ``` +### vim +###### [Style [Y255](#style-y255)] + + - vim代码片段遵循以下规范。 + + - 下载[vim Angular代码段](assets/vim-angular-snippets?raw=true) + - 设置[neosnippet.vim](https://github.com/Shougo/neosnippet.vim) + - 粘贴到snippet路径下 + + ```javascript + ngcontroller // creates an Angular controller + ngdirective // creates an Angular directive + ngfactory // creates an Angular factory + ngmodule // creates an Angular module + ngservice // creates an Angular service + ngfilter // creates an Angular filter + ``` **[返回顶部](#目录)** ## Yeoman Generator @@ -2925,6 +2942,76 @@ Angular社区是一个热衷于分享经验的令人难以置信的社区,尽 *为什么?*:语法和Angular路由很像,很容易迁移到UI Router。 + - 注意:你可以在运行期间使用`routerHelperProvider`配置跨文件状态 + + ```javascript + // customers.routes.js + angular + .module('app.customers') + .run(appRun); + + /* @ngInject */ + function appRun(routerHelper) { + routerHelper.configureStates(getStates()); + } + + function getStates() { + return [ + { + state: 'customer', + config: { + abstract: true, + template: '', + url: '/customer' + } + } + ]; + } + ``` + + ```javascript + // routerHelperProvider.js + angular + .module('blocks.router') + .provider('routerHelper', routerHelperProvider); + + routerHelperProvider.$inject = ['$locationProvider', '$stateProvider', '$urlRouterProvider']; + /* @ngInject */ + function routerHelperProvider($locationProvider, $stateProvider, $urlRouterProvider) { + /* jshint validthis:true */ + this.$get = RouterHelper; + + $locationProvider.html5Mode(true); + + RouterHelper.$inject = ['$state']; + /* @ngInject */ + function RouterHelper($state) { + var hasOtherwise = false; + + var service = { + configureStates: configureStates, + getStates: getStates + }; + + return service; + + /////////////// + + function configureStates(states, otherwisePath) { + states.forEach(function(state) { + $stateProvider.state(state.state, state.config); + }); + if (otherwisePath && !hasOtherwise) { + hasOtherwise = true; + $urlRouterProvider.otherwise(otherwisePath); + } + } + + function getStates() { return $state.get(); } + } + } + ``` + ###### [Style [Y271](#style-y271)] - Define routes for views in the module where they exist,Each module should contain the routes for the views in the module. From 639834c8e6b32696966e776474847d4b94c7f2b3 Mon Sep 17 00:00:00 2001 From: Michael Seeger Date: Mon, 27 Apr 2015 22:35:45 +0200 Subject: [PATCH 283/567] German translation - initial version. --- i18n/de-DE.md | 3098 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 3098 insertions(+) create mode 100644 i18n/de-DE.md diff --git a/i18n/de-DE.md b/i18n/de-DE.md new file mode 100644 index 00000000..a1acd79b --- /dev/null +++ b/i18n/de-DE.md @@ -0,0 +1,3098 @@ +# Angular Styleguide + +*Dogmatischer Angular Styleguide für Teams von John Papa [@john_papa](//twitter.com/john_papa)* + +Sind Sie auf der Suche nach einem dogmatischen Styleguide zur Syntax, zu Konventionen und zur Struktur von Angular-Anwendungen, dann treten sie näher. Diese Vorlagen basieren auf meinen Erfahrungen mit [Angular](//angularjs.org), Präsentationen, [Pluralsight Trainingskursen](http://pluralsight.com/training/Authors/Details/john-papa) und der Arbeit in Teams. + +Der Zweck dieses Styleguides ist es, eine Anleitung für die Erstellung von Angular-Anwendungen bereitzustellen, indem ich die Konventionen, die ich nutze, zeige und - wichtiger als das - beschreibe, warum ich sie wähle. + +>Wenn Sie diese Anleitung mögen, dann besuchen Sie meinen Kurs [Angular Patterns: Clean Code] (http://jpapa.me/ngclean) auf Pluralsight, der eine Begleitung zu dieser Anleitung dartellt. + + [![AngularJs Patterns: Clean Code](https://raw.githubusercontent.com/johnpapa/angular-styleguide/master/assets/ng-clean-code-banner.png)](http://jpapa.me/ngclean) + +## Außergewöhnliche Community and Anerkennung +Arbeite niemals im leeren Raum. Ich finde, dass die Angular-Community eine unglaubliche Gruppe ist, die ihre Erfahrung mit Leidenschaft teilt. Also haben ein Freund und Angular-Experte, Todd Motto, und ich viele Vorlagen und Konventionen zusammengetragen. Bei den meisten sind wir uns einig, und bei ein paar sind wir verschiedener Meinung. Ich möchte Sie ermutigen, sich [Todd's Guidelines](https://github.com/toddmotto/angularjs-styleguide) anzusehen, um ein Gespühr für seinen Ansatz zu entwickeln und ihn vergleichen zu können. + +Viele meiner Vorlagen entstanden aus Pair-Programming-Sessions, die [Ward Bell](http://twitter.com/wardbell) und ich hatten. Mein Freund Ward hat sicherlich die endgültige Entwicklung dieser Anleitung beeinflusst. + +## Schauen Sie sich die Vorlagen in einer Beispielanwendung an +Während diese Anleitung das *Was*, *Warum* und *Wie* erklärt, finde ich es ebenso hilfreich, sie auch in der Praxis zu sehen. Diese Anleitung wird von einer Beispielanwendung begleitet, die diesen Vorlagen und Mustern folgt. Sie finden die [Beispielanwendung (namens "modular") hier] (https://github.com/johnpapa/ng-demos) im `modular`-Ordner. Fühlen Sie sich frei, sich diese zu holen, indem Sie sie clonen oder einen Fork erstellen.[Anweisungen, sie zum Laufen zu bringen, finden Sie im Readme](https://github.com/johnpapa/ng-demos/tree/master/modular). + +##Übersetzungen +[Übersetzungen dieses Styleguides](https://github.com/johnpapa/angular-styleguide/tree/master/i18n) werden von der Community hier verwaltet. + +## Inhaltsverzeichnis + + 1. [Single Responsibility](#single-responsibility) + 1. [IIFE](#iife) + 1. [Module](#modules) + 1. [Controller](#controllers) + 1. [Services](#services) + 1. [Factories](#factories) + 1. [Dataservices](#data-services) + 1. [Direktiven](#directives) + 1. [Promises für einen Controller auflösen](#resolving-promises-for-a-controller) + 1. [Manuelle Code-Anmerkungen für das Einfügen von Abhängigkeiten (Dependency Injection)](#manual-annotating-for-dependency-injection) + 1. [Minifizierung und Code-Anmerkungen](#minification-and-annotation) + 1. [Fehlerbehandlung](#exception-handling) + 1. [Namensgebung](#naming) + 1. [Anwendungsstruktur: LIFT Prinzip](#application-structure-lift-principle) + 1. [Anwendungsstruktur](#application-structure) + 1. [Modularität](#modularity) + 1. [Startlogik](#startup-logic) + 1. [Angular $ Wrapper Services](#angular--wrapper-services) + 1. [Testen](#testing) + 1. [Animationen](#animations) + 1. [Kommentare](#comments) + 1. [JS Hint](#js-hint) + 1. [JSCS](#jscs) + 1. [Konstanten](#constants) + 1. [Dateitemplates und Snippets](#file-templates-and-snippets) + 1. [Yeoman Generator](#yeoman-generator) + 1. [Routing](#routing) + 1. [Automatisierung von Aufgaben](#task-automation) + 1. [Filter](#filters) + 1. [Angular Dokumentation](#angular-docs) + 1. [Beiträge](#contributing) + 1. [Lizenz](#license) + +## Single Responsibility + +### Rule of 1 +###### [Style [Y001](#style-y001)] + + - Definiere eine Komponente pro Datei. + + Das folgende Beispoiel definiert das `app`-Modul und seine Abhängigkeiten, einen Controller und eine Factory in ein und derselben Datei. + + ```javascript + /* zu vermeiden */ + angular + .module('app', ['ngRoute']) + .controller('SomeController', SomeController) + .factory('someFactory', someFactory); + + function SomeController() { } + + function someFactory() { } + ``` + + Die gleichen Komponenten sind nun in separaten Dateien untergebracht. + + ```javascript + /* empfohlen */ + + // app.module.js + angular + .module('app', ['ngRoute']); + ``` + + ```javascript + /* empfohlen */ + + // someController.js + angular + .module('app') + .controller('SomeController', SomeController); + + function SomeController() { } + ``` + + ```javascript + /* empfohlen */ + + // someFactory.js + angular + .module('app') + .factory('someFactory', someFactory); + + function someFactory() { } + ``` + +**[Zurück zum Anfang](#table-of-contents)** + +## IIFE +### JavaScript Closures +###### [Style [Y010](#style-y010)] + + - Packen sie Angular-Komponenten in eine Funktion, die sich sofort selbst ausführt (Immediately Invoked Function Expression, kurz: IIFE). + + *Warum?*: Eine IIFE entfernt Variablen aus dem Global Scope. Dies verhindert, dass Variablen- und Funktionsdeklarationen länger als erwartet im global scope bleiben. Und es verhindert zusätzlich, Kollisionen bei Variablen zu verhindern. + + *Warum?*: Wird Ihr Code für das Deployment auf einem Produktionsserver minifiziert und in einer einzigen Datei zusammengepackt, kann es zur Kollision von Variablen (auch Globalen) kommen. Eine IIFE schützt Sie hiervor, indem sie den Gültigkeitsbereich der Variablen auf die jeweilige Datei beschränkt. + + ```javascript + /* zu vermeiden */ + // logger.js + angular + .module('app') + .factory('logger', logger); + + // Logger-Funktion wird als globale Variable hinzugefügt + function logger() { } + + // storage.js + angular + .module('app') + .factory('storage', storage); + + // Storage-Funktion wird als globale Variable hinzugefügt + function storage() { } + ``` + + ```javascript + /** + * empfohlen + * + * es verbleiben keine globalen Variablen + */ + + // logger.js + (function() { + 'use strict'; + + angular + .module('app') + .factory('logger', logger); + + function logger() { } + })(); + + // storage.js + (function() { + 'use strict'; + + angular + .module('app') + .factory('storage', storage); + + function storage() { } + })(); + ``` + + - Anmerkung: Nur zur Verkürzung des dargestellten Codes, wird beim Rest dieser Beispiele die IIFE-Syntax ausgelassen. + + - Anmerkung: IIFE's verhindern, dass Testcode private Elemente, wie reguläre Ausdrücke oder Hilfsfunktionen ansprechen können. Diese können oft gut direkt für sich selbst getestet werden. Sie können diese jedoch auch durch zugreifbare Elemente oder durch ihre eigene Komponente zugreifbar machen. Zum Beispiel können Sie Hilfsfunktionen, reguläre Ausdrücke oder Konstanten in ihrer eigenen Factory oder Konstante platzieren. + +**[Zurück zum Anfang](#table-of-contents)** + +## Module + +### Namenskollisionen vermeiden +###### [Style [Y020](#style-y020)] + + - Benutzen sie eindeutige Namenskonventionen mit Trennzeichen für Untermodule. + + *Warum?*: Eindeutige Namen helfen, Kollisionen bei Modulnamen zu verhindern. Trennzeichen helfen, bei der Definition von Modulen und deren Untermodul-Hierarchie. Zum Beispiel kann `app` Ihr Root-Modul sein, während `app.dashboard` und `app.users` Module sein können, die von `app` als Abhängigkeiten genutzt werden. + +### Definitionen (auch: Setter) +###### [Style [Y021](#style-y021)] + + - Deklarieren Sie Module ohne eine Variable, indem Sie die Setter-Syntax verwenden. + + *Warum?*: Bei einer Komponente pro Datei besteht kaum die Notwendigkeit, eine Variable für das Modul einzuführen. + + ```javascript + /* zu vermeiden */ + var app = angular.module('app', [ + 'ngAnimate', + 'ngRoute', + 'app.shared', + 'app.dashboard' + ]); + ``` + + Nutzen Sie stattdessen die einfache Setter-Syntax. + + ```javascript + /* empfohlen */ + angular + .module('app', [ + 'ngAnimate', + 'ngRoute', + 'app.shared', + 'app.dashboard' + ]); + ``` + +### Getter +###### [Style [Y022](#style-y022)] + + - Wenn Sie ein Modul nutzen, vermeiden Sie die Nutzung einer Variablen. Nutzen Sie stattdessen eine Verkettung mit der Getter-Syntax. + + *Warum?*: Dies führt zu mehr lesbarem Code und verhindert Variablenkollistionen oder Leaks. + + ```javascript + /* zu vermeiden */ + var app = angular.module('app'); + app.controller('SomeController', SomeController); + + function SomeController() { } + ``` + + ```javascript + /* empfohlen */ + angular + .module('app') + .controller('SomeController', SomeController); + + function SomeController() { } + ``` + +### Setting vs. Getting +###### [Style [Y023](#style-y023)] + + - Nur einmal setzen und für alle anderen Instanzen lesen (get). + + *Warum?*: Ein Modul sollte nur einmal erstellt werden, ab diesem Punkt an nur noch gelesen werden. + + - Benutzen Sie `angular.module('app', []);` um das Modul zu erzeugen (set). + - Benutzen Sie `angular.module('app');` um das Modul zu erhalten (get). + +### Benannte vs. anonyme Funktionen +###### [Style [Y024](#style-y024)] + + - Benutzen Sie für Callbacks benannte Funktionen, anstatt eine anonyme Funktion zu übergeben. + + *Warum?*: Dies führt zu lesbarerem Code, ist einfach zu debuggen und veringert die Schachtelung des Callback-Codes. + + ```javascript + /* zu vermeiden */ + angular + .module('app') + .controller('Dashboard', function() { }) + .factory('logger', function() { }); + ``` + + ```javascript + /* empfohlen */ + + // dashboard.js + angular + .module('app') + .controller('Dashboard', Dashboard); + + function Dashboard() { } + ``` + + ```javascript + // logger.js + angular + .module('app') + .factory('logger', logger); + + function logger() { } + ``` + +**[Zurück zum Anfang](#table-of-contents)** + +## Controller + +### controllerAs View-Syntax +###### [Style [Y030](#style-y030)] + + - Ziehen Sie die [`controllerAs`](http://www.johnpapa.net/do-you-like-your-angular-controllers-with-or-without-sugar/)-Syntax der `klassischen Controller-Mit-$scope`-Syntax vor. + + *Warum?*: Controller werden immer wieder neu erstellt. Man erhält jedes Mal eine neue Instanz und die `controllerAs`-Syntax ist näher an der eines JavaScript-Konstruktors, als die`klassische Controller-Mit-$scope-Syntax`. + + *Warum?*: Es begünstigt die Bindung von "Punkt-Notierten" Objekten in der View (z. B. `customer.name` statt `name`), was kontextbezogener und einfacher zu lesen ist und Referenzproblemen, die ohne diese "Punkt-Notation" auftreten können, vorbeugt. + + *Warum?*: Hilft, die Nutzung von `$parent`-Aufrufen in Views und geschachtelten Controllern zu vermeiden. + + ```html + +
+ {{ name }} +
+ ``` + + ```html + +
+ {{ customer.name }} +
+ ``` + +### controllerAs Controller Syntax +###### [Style [Y031](#style-y031)] + + - Ziehen Sie die `controllerAs`-Syntax der `klassischen Controller-Mit-$scope-Syntax` vor. + + - Die `controllerAs`-Syntax nutzt `this` innerhalb des Controllers, welches an `$scope` gebunden wird. + + *Warum?*: `controllerAs` stellt eine syntaktische "Versüßung" `$scope` dar. Sie können immer noch Bindungen an die View vornehmen und auf die `$scope`-Methoden zugreifen. + + *Warum?*: Hilft, die verführerische Nutzung von `$scope`-Methoden innerhalb eines Controllers zu unterbinden, wenn es besser wäre, sie zu vermeiden oder in eine Factory auszulagern. Man sollte die Nutzung von `$scope` in einer Factory oder einem Controller nur dann in Erwägung ziehen, wenn es notwendig ist. Wenn zum Beispiel Events mit [`$emit`](https://docs.angularjs.org/api/ng/type/$rootScope.Scope#$emit), [`$broadcast`](https://docs.angularjs.org/api/ng/type/$rootScope.Scope#$broadcast) oder [`$on`](https://docs.angularjs.org/api/ng/type/$rootScope.Scope#$on) abonniert oder publiziert werden, sollte man überlegen, diese nicht in eine Factory auszulagern und vom Controller aus auszulösen. + + ```javascript + /* zu vermeiden */ + function Customer($scope) { + $scope.name = {}; + $scope.sendMessage = function() { }; + } + ``` + + ```javascript + /* empfohlen - schauen Sie aber bitte im nächsten Abschnitt */ + function Customer() { + this.name = {}; + this.sendMessage = function() { }; + } + ``` + +### controllerAs mit vm +###### [Style [Y032](#style-y032)] + + - Benutzen Sie eine Variable, um `this` zu übernehmen, wenn sie die `controllerAs`-Syntax verwenden. Wählen Sie einen konsistenten Variablennanen, wie `vm`, welcher für ViewModel steht. + + *Warum?*: Das `this`-Schlüsselwort ist kontextbezogen und kann diesen Kontext ändern, wenn es innerhalb einer Funktion eines Controllers verwendet wird. Wird der Kontext von `this` übernommen, wird dieses Problem verhindert. + + ```javascript + /* zu vermeiden */ + function Customer() { + this.name = {}; + this.sendMessage = function() { }; + } + ``` + + ```javascript + /* empfohlen */ + function Customer() { + var vm = this; + vm.name = {}; + vm.sendMessage = function() { }; + } + ``` + + Anmerkung: Sie können jegliche [jshint](http://www.jshint.com/)-Warnungen unterbinden, indem sie den Kommentar vor der Codezeile einfügen. Allerdingst ist dies nicht notwendig, wenn die Funktion großgeschrieben ist (UpperCasing). Diese Konvention besagt, dass es sich um eine Kontruktor-Funktion handelt, was einem Controller in Angular entspricht. + + ```javascript + /* jshint validthis: true */ + var vm = this; + ``` + + Anmerkung: Wenn Sie Watches in einem Controller einsetzen, der über `controller as` genutzt wrid, können Sie die `vm.*`-Member über die folgende Syntax überwachen. (Erstellen Sie Watches mit Vorsicht, denn sie belasten den "digest cycle".) + + ```html + + ``` + + ```javascript + function SomeController($scope, $log) { + var vm = this; + vm.title = 'Some Title'; + + $scope.$watch('vm.title', function(current, original) { + $log.info('vm.title was %s', original); + $log.info('vm.title is now %s', current); + }); + } + ``` + +### Zu bindende Bestandteile nach oben +###### [Style [Y033](#style-y033)] + + - Platzieren sie zu bindende Elemente alphabeisch sortiert am Anfang des Controllers und nicht verteilt im Code des Controllers. + + *Warum?*: Die Platzierung von zu bindenden Elementen am Anfang verbessert die Lesbarkeit und hilft Ihnen, die zur Bindung und Nutzung in einer View vorgesehenen Elemente des Controllers schnell zu identifizieren. + + *Warum?*: Anonyme Funktionen einzusetzen kann einfach sein, aber wenn diese Funktionen die Länge von einer Zeile überschreiten, wird die Lesbarkeit des Codes verschlechtert. Die Definition der Funktionen unterhalb der Deklaration der zur Bindung vorgesehenen Elemente verschiebt die Details der Implementierung nach unten, hält die zu Bindenden Elemente ganz oben und macht es lesbarer (die Funktionen werden quasi "hochgezogen"). + + ```javascript + /* zu vermeiden */ + function Sessions() { + var vm = this; + + vm.gotoSession = function() { + /* ... */ + }; + vm.refresh = function() { + /* ... */ + }; + vm.search = function() { + /* ... */ + }; + vm.sessions = []; + vm.title = 'Sessions'; + ``` + + ```javascript + /* empfohlen */ + function Sessions() { + var vm = this; + + vm.gotoSession = gotoSession; + vm.refresh = refresh; + vm.search = search; + vm.sessions = []; + vm.title = 'Sessions'; + + //////////// + + function gotoSession() { + /* */ + } + + function refresh() { + /* */ + } + + function search() { + /* */ + } + ``` + + ![Controller Using "Above the Fold"](https://raw.githubusercontent.com/johnpapa/angular-styleguide/master/assets/above-the-fold-1.png) + + Anmerkung: Falls eine Funktion aus nur einer Zeile bestehen sollte, können Sie sich überlegen, diese nach oben zu verlagen, so lange die Lesbarkeit nicht betroffen ist. + + ```javascript + /* zu vermeiden */ + function Sessions(data) { + var vm = this; + + vm.gotoSession = gotoSession; + vm.refresh = function() { + /** + * lines + * of + * code + * affects + * readability + */ + }; + vm.search = search; + vm.sessions = []; + vm.title = 'Sessions'; + ``` + + ```javascript + /* empfohlen */ + function Sessions(dataservice) { + var vm = this; + + vm.gotoSession = gotoSession; + vm.refresh = dataservice.refresh; // 1 liner is OK + vm.search = search; + vm.sessions = []; + vm.title = 'Sessions'; + ``` + +### Funktionsdeklarationen, um Details der Implementierung zu verbergen +###### [Style [Y034](#style-y034)] + + - Nutzen Sie Funktionsdeklarationen, um Implementierungsdetails zu verbergen. Halten Sie Ihre zur Bindung vorgesehenen Elemente oben. Wenn sie eine Controller-Funktion zur Bindung vorsehen müssen, dann lassen Sie diese auf die Funktionsdeklaration zeigen, die weiter unten erscheint. Diese wird direkt an den Abschnitt mit den zur Bindung vorgesehenen Element geknüpft. Mehr erfahren sie hier in [diesem Beitrag](http://www.johnpapa.net/angular-function-declarations-function-expressions-and-readable-code). + + *Warum?*: Die zur Bindung vorgesehenen Elemente am Anfang zu platzieren, erhöht die Lesbarkeit und hilft Ihnen die Elemente zu identifizieren, die gebunden und in einer View genutzt werden können. (Das Gleiche, wie zuvor.) + + *Warum?*: Das Platzieren der Implementierungsdetails einer Funktion weiter unten in der Datei, hält diese Codemenge außer Sicht und Sie sehen die wichtigen Dinge am Anfang. + + *Warum?*: Funktionsdeklarationen werden "nach oben gezogen" (sog. Hoisting), so dass es keine Probleme damit gibt, ob eine Funktion vor ihrer Benutzung deklariert werden sollte (wie es bei Funktiosausdrücken der Fall wäre). + + *Warum?*: Sie müssen sich niemals Sorgen darum machen, wenn Sie in Funktionsdeklarationen `var a` vor `var b` platzieren, weil `a` von `b` abhängig ist. + + *Warum?*: Die Reihenfolge ist nur kritisch in Funktionsausdrücken. + + ```javascript + /** + * avoid + * Nutzung von Funktionsausdrücken. + */ + function Avengers(dataservice, logger) { + var vm = this; + vm.avengers = []; + vm.title = 'Avengers'; + + var activate = function() { + return getAvengers().then(function() { + logger.info('Activated Avengers View'); + }); + } + + var getAvengers = function() { + return dataservice.getAvengers().then(function(data) { + vm.avengers = data; + return vm.avengers; + }); + } + + vm.getAvengers = getAvengers; + + activate(); + } + ``` + + Berücksichtigen Sie, dass die wichtigen Teile im vorangegangenen Beispiel verstreut sind. Im folgenden Beispiel befindet sich der wichtige Teil ganz oben: Beispielsweise die Elemente, die gebunden werden können, wie `vm.avengers` und `vm.title`. Die Implementierungsdetails befinden sich unterhalb, was eben einfacher zu lesen ist. + + ```javascript + /* + * empfohlen + * Nutzung von Funktionsdeklarationen + * und bindbaren Elementen weiter oben. + */ + function Avengers(dataservice, logger) { + var vm = this; + vm.avengers = []; + vm.getAvengers = getAvengers; + vm.title = 'Avengers'; + + activate(); + + function activate() { + return getAvengers().then(function() { + logger.info('Activated Avengers View'); + }); + } + + function getAvengers() { + return dataservice.getAvengers().then(function(data) { + vm.avengers = data; + return vm.avengers; + }); + } + } + ``` + +### Verlagern Sie Controller-Logik in Services +###### [Style [Y035](#style-y035)] + + - Verlagern Sie die Logik eines Controllers, indem Sie diese in Services oder Factories übertragen. + + *Warum?*: Die Logik kann von mehreren Controllern wiederverwendet werden, wenn sie in einem Service oder einer Factory untergebracht ist und über eine Funktion bereitgestellt wird. + + *Warum?*: Logik in einem Service kann in einem Unit-Test einfacher isoliert werden und die Aufruflogik des Controllers wird einfach simuliert. + + *Warum?*: Beseitigt Abhängigkeiten und versteckt die Implementierungsdetails vor dem Controller. + + *Warum?*: Hält den Controller schlank und richtet ihn auf seine Aufgabe aus. + + ```javascript + + /* zu vermeiden */ + function Order($http, $q, config, userInfo) { + var vm = this; + vm.checkCredit = checkCredit; + vm.isCreditOk; + vm.total = 0; + + function checkCredit() { + var settings = {}; + // Get the credit service base URL from config + // Set credit service required headers + // Prepare URL query string or data object with request data + // Add user-identifying info so service gets the right credit limit for this user. + // Use JSONP for this browser if it doesn't support CORS + return $http.get(settings) + .then(function(data) { + // Unpack JSON data in the response object + // to find maxRemainingAmount + vm.isCreditOk = vm.total <= maxRemainingAmount + }) + .catch(function(error) { + // Interpret error + // Cope w/ timeout? retry? try alternate service? + // Re-reject with appropriate error for a user to see + }); + }; + } + ``` + + ```javascript + /* empfohlen */ + function Order(creditService) { + var vm = this; + vm.checkCredit = checkCredit; + vm.isCreditOk; + vm.total = 0; + + function checkCredit() { + return creditService.isOrderTotalOk(vm.total) + .then(function(isOk) { vm.isCreditOk = isOk; }) + .catch(showServiceError); + }; + } + ``` + +### Halten Sie die Controller auf ihre Aufgabe ausgerichtet +###### [Style [Y037](#style-y037)] + + - Definieren Sie einen Controller für eine View und versuchen Sie nicht, diesen Controller für weitere Views zu verwenden. Verlagern Sie stattdessen wiederzuverwendende Logik in Factories und halten Sie den Controller einfach und ausgerichtet auf seine View. + + *Warum?*: Controller in mehreren Views wiederzuverwenden ist kritisch und bedingt eine gute End-Zu-End (e2e) Testabdeckung, um die Stabilität in großen Anwendungen zu garantieren. + + +### Controller zuweisen +###### [Style [Y038](#style-y038)] + + - Wenn ein Controller mit einer View verbunden werden muss und eine der beiden Komponenten aber von anderen Controllern oder Views wiederverwendet werden muss, dann sollten die Controller bei ihren Routen definiert werden. + + Anmerkung: Sollte eine View in einem anderen Kontext als einer Route geladen werden, dann benutzen Sie die `ng-controller="Avengers as vm"`-Syntax. + + *Warum?*: Wird der Controller inerhalb einer Route verbunden, dann ist es möglich, dass unterschiedliche Routen auch unterschiedliche Controller-View-Bindungen verwenden können. Sind Controller in einer View mit [`ng-controller`](https://docs.angularjs.org/api/ng/directive/ngController) angebunden, dann ist diese View immer mit dem gleichen Controller verbunden. + + ```javascript + /* zu vermeiden - bei Nutzung mit eiuner Route, wenn eine dynamische Verbindung gewünscht ist */ + + // route-config.js + angular + .module('app') + .config(config); + + function config($routeProvider) { + $routeProvider + .when('/avengers', { + templateUrl: 'avengers.html' + }); + } + ``` + + ```html + +
+
+ ``` + + ```javascript + /* empfohlen */ + + // route-config.js + angular + .module('app') + .config(config); + + function config($routeProvider) { + $routeProvider + .when('/avengers', { + templateUrl: 'avengers.html', + controller: 'Avengers', + controllerAs: 'vm' + }); + } + ``` + + ```html + +
+
+ ``` + +**[Zurück zum Anfang](#table-of-contents)** + +## Services + +### Singletons +###### [Style [Y040](#style-y040)] + + - Services werden mit dem `new`-Schlüsselwort Instantiiert, und benutzen `this` für öffentliche Methoden und Variablen. Auch wenn sie den Factories so ähnlich sind, setzen Sie stattdessen aus Konsistenzgründen eine Factory ein. + + Anmerkung: [Alle Angular-Services sind Singletons](https://docs.angularjs.org/guide/services). Das bedeutet, dass es nur eine Instanz eines Services pro Injector gibt. + + ```javascript + // service + angular + .module('app') + .service('logger', logger); + + function logger() { + this.logError = function(msg) { + /* */ + }; + } + ``` + + ```javascript + // factory + angular + .module('app') + .factory('logger', logger); + + function logger() { + return { + logError: function(msg) { + /* */ + } + }; + } + ``` + +**[Zurück zum Anfang](#table-of-contents)** + +## Factories + +### Single Responsibility +###### [Style [Y050](#style-y050)] + + - Factories sollten [eine einzige Verantwortung](http://en.wikipedia.org/wiki/Single_responsibility_principle) haben, die in ihrem Kontext gekapselt ist. Wenn eine Factory einmal über diesen einzigen Zweck hinaus erweitert werden muss, dann sollte eine neue Factory erstellt werden. + +### Singletons +###### [Style [Y051](#style-y051)] + + - Factories sind Singletons und liefern ein Objekt zurück, das die Bestandteile (Elemente) des Service beinhaltet. + + Anmerkung: [Alle Angular-Services sind Singletons](https://docs.angularjs.org/guide/services). + +### Zugreifbare Bestandteile an den Anfang +###### [Style [Y052](#style-y052)] + + - Halten sie die zugreifbaren Bestandteile eines Service (sein Interface) oben, indem Sie eine Technik anwenden, die aus [Revealing Module Pattern](http://addyosmani.com/resources/essentialjsdesignpatterns/book/#revealingmodulepatternjavascript) entlehnt ist. + + *Warum?*: Die zugreifbaren Bestandteile oben zu platzieren, erhöht die Lesbarkeit und hilft Ihnen, schnell zu identifizieren, welche Elemente des Service aufgerufen werden können und getestet (oder simuliert) werden müssen. + + *Warum?*: Dies ist besondert hilfreich, wenn die Datei länger wird, weil ein Scrollen unnötig wird, um zu sehen, was verfügbar ist. + + *Warum?*: Einfach nur Funktionen einzusetzen kann leicht sein. Wenn diese aber den Umfang einer Zeile überschreiben, kann dies die Lesbarkeit verringern und es muss mehr gescrollt werden. Ein aufrufbares Interface im zurückgelieferten Service zu definieren, verlagert die Implementierungsdetails nach unten, hält das aufrufbare Interface ganz oben und macht es lesbarer. + + ```javascript + /* zu vermeiden */ + function dataService() { + var someValue = ''; + function save() { + /* */ + }; + function validate() { + /* */ + }; + + return { + save: save, + someValue: someValue, + validate: validate + }; + } + ``` + + ```javascript + /* empfohlen */ + function dataService() { + var someValue = ''; + var service = { + save: save, + someValue: someValue, + validate: validate + }; + return service; + + //////////// + + function save() { + /* */ + }; + + function validate() { + /* */ + }; + } + ``` + + So spiegeln sich die Bindungen im gesamten (beinhaltenden) Objekt wieder. Werte können nicht selbständig durch die Offenlegung des Modulmusters geändert werden. + + ![Factories Using "Above the Fold"](https://raw.githubusercontent.com/johnpapa/angular-styleguide/master/assets/above-the-fold-2.png) + +### Funktionsdeklarationen, um die Details der Implementierung zu verbergen +###### [Style [Y053](#style-y053)] + + - Benutzen Sie Funktionsdeklarationen, um die Details der Implementierung zu verbergen. Halten Sie Ihre zugreifbaren Bestandteile der Factory ganz oben. Lassen Sie diese auf Funktionsdeklarationen verweisen, die weiter unten in der Datei aufeführt werden. Mehr erfahren sie hier in [diesem Beitrag](http://www.johnpapa.net/angular-function-declarations-function-expressions-and-readable-code). + + *Warum?*: Zugreifbare Elemente am Anfang zu platzieren, erhöht die Lesbarkeit und hilft Ihnen, zu identifizieren, auf welche Funktionen der Factory von außen zugegriffen werden kann. + + *Warum?*: Das Platzieren der Implementierungsdetails einer Funktion weiter unten in der Datei, hält diese Codemenge außer Sicht und Sie sehen die wichtigen Dinge am Anfang. + + *Warum?*: Funktionsdeklarationen werden "nach oben gezogen" (sog. Hoisting), so dass es keine Probleme damit gibt, ob eine Funktion vor ihrer Benutzung deklariert werden sollte (wie es bei Funktiosausdrücken der Fall wäre). + + *Warum?*: Sie müssen sich niemals Sorgen darum machen, wenn Sie in Funktionsdeklarationen `var a` vor `var b` platzieren, weil `a` von `b` abhängig ist. + + *Warum?*: Die Reihenfolge ist kritisch in Funktionsausdrücken. + + ```javascript + /** + * zu vermeiden + * Nutzung von Funktionsausdrücken + */ + function dataservice($http, $location, $q, exception, logger) { + var isPrimed = false; + var primePromise; + + var getAvengers = function() { + // implementation details go here + }; + + var getAvengerCount = function() { + // implementation details go here + }; + + var getAvengersCast = function() { + // implementation details go here + }; + + var prime = function() { + // implementation details go here + }; + + var ready = function(nextPromises) { + // implementation details go here + }; + + var service = { + getAvengersCast: getAvengersCast, + getAvengerCount: getAvengerCount, + getAvengers: getAvengers, + ready: ready + }; + + return service; + } + ``` + + ```javascript + /** + * empfohlen + * Nutzung von Funktionsdeklarationen und den zugreifbaren Elementen ganz oben + */ + function dataservice($http, $location, $q, exception, logger) { + var isPrimed = false; + var primePromise; + + var service = { + getAvengersCast: getAvengersCast, + getAvengerCount: getAvengerCount, + getAvengers: getAvengers, + ready: ready + }; + + return service; + + //////////// + + function getAvengers() { + // implementation details go here + } + + function getAvengerCount() { + // implementation details go here + } + + function getAvengersCast() { + // implementation details go here + } + + function prime() { + // implementation details go here + } + + function ready(nextPromises) { + // implementation details go here + } + } + ``` + +**[Zurück zum Anfang](#table-of-contents)** + +## Datenservices + +### Separate Datenzugriffe +###### [Style [Y060](#style-y060)] + + - Verlagern sie die Datenzugriffslogik und die Operationen mit Daten in eine Factory Machen Sie die Datenservices verantwortlich für die XHR-Aufrufe, die lokale Speicherung, die Ablage im Speicher oder jede andere Datenoperation. + + *Warum?*: Die Verantwortung des Controllers liegt in der Zusammenstellung und Präsentation der Informationen für die und in der View. Er sollte sich nicht darum kümmern müssen, wie er die Daten bekommt, sondern wen er dazu ansprechen muss. Die Datenservices zu trennen verlagert die Logik der Datenermittlung in den Datenservice und belässt den Controller in seiner Einfachheit und seinem Fokus auf die View. + + *Warum?*: Das macht das Testen der Datenabrufe (simuliert oder real) einfacher, wenn man einen Controller testet, der einen Datenservice nutzt. + + *Warum?*: Datenserivce-Implementierungen enthalten spezifischen Code, um die Daten zu handhaben. Dies können bestimmte Header sein, die beschreiben, wie mit den Datenquellen oder anderen Services wie `$http` kommuniziert werden muss. Die Separierung dieser Logik in einem Datenservice kapselt sie an einem einzigen Platz und verbirgt die Implementierung vor den Konsumenten dieses Service (z. B. einem Controller). Das macht es auch einfacher, die Implementierung auszutauschen. + + ```javascript + /* empfohlen */ + + // dataservice factory + angular + .module('app.core') + .factory('dataservice', dataservice); + + dataservice.$inject = ['$http', 'logger']; + + function dataservice($http, logger) { + return { + getAvengers: getAvengers + }; + + function getAvengers() { + return $http.get('/api/maa') + .then(getAvengersComplete) + .catch(getAvengersFailed); + + function getAvengersComplete(response) { + return response.data.results; + } + + function getAvengersFailed(error) { + logger.error('XHR Failed for getAvengers.' + error.data); + } + } + } + ``` + + Anmerkung: Der Datenservice wird von seinen Verbrauchern, wie einem Controller, angesprochen. Wie unten gezeigt, wird seine Implementierung vor den Verbrauchern verborgen. + + ```javascript + /* empfohlen */ + + // controller calling the dataservice factory + angular + .module('app.avengers') + .controller('Avengers', Avengers); + + Avengers.$inject = ['dataservice', 'logger']; + + function Avengers(dataservice, logger) { + var vm = this; + vm.avengers = []; + + activate(); + + function activate() { + return getAvengers().then(function() { + logger.info('Activated Avengers View'); + }); + } + + function getAvengers() { + return dataservice.getAvengers() + .then(function(data) { + vm.avengers = data; + return vm.avengers; + }); + } + } + ``` + +### Rücklieferung eines Versprechens ("Promise") von einem Datenabruf +###### [Style [Y061](#style-y061)] + + - Wenn Sie einen Datenservice ansprechen, der einen Promise wie `$http` zurückliefert, so liefern Sie in Ihrer aufrufenden Funktion ebenso einen Promise zurück. + + *Warum?*: Sie können die Promises aneinanderhängen und weitere Aktionen ausführen, wenn der Datenabruf beendet ist und den Promise im Erfolgsfall entweder auflöst oder bei Fehlschlagen zurückweist. + + ```javascript + /* empfohlen */ + + activate(); + + function activate() { + /** + * Schritt 1 + * Bei der getAvengers Funktion nach den Avenger-Daten + * fragen und auf den Promise warten + */ + return getAvengers().then(function() { + /** + * Schritt 4 + * Aktion ausführen, um den finalen Promise aufzulösen + */ + logger.info('Activated Avengers View'); + }); + } + + function getAvengers() { + /** + * Schritt 2 + * Beim Datenservice nach den Daten fragen und + * auf den Promise warten + */ + return dataservice.getAvengers() + .then(function(data) { + /** + * Schritt 3 + * ermittelte Daten einsetzen und den Promise auflösen + */ + vm.avengers = data; + return vm.avengers; + }); + } + ``` + +**[Zurück zum Anfang](#table-of-contents)** + +## Direktiven +### Begrenzung auf Eine pro Datei +###### [Style [Y070](#style-y070)] + + - Erstellen Sie eine Direktive pro Datei. Benennen Sie die Datei nach der Direktive. + + *Warum?*: Es ist einfach, alle Direktiven in einer Datei zu halten, aber schwer, sie dann wieder herauszulösen sodass sie zwischen Anwendungen oder Modulen ausgetauscht werden können oder einfach nur in einem Modulzu genutzt werden. + + *Warum?*: Eine Direktive pro Datei ist einfach zu warten. + + > Anmerkung: "**Best Practice**: Direktiven sollten aufräumen. Sie können `element.on('$destroy', ...)` oder `scope.$on('$destroy', ...)` nutzen, um eine Bereinigungsfunktion auszuführen, wenn die Direktive entfernt wird." ... aus der Angular-Dokumentation. + + ```javascript + /* zu vermeiden */ + /* directives.js */ + + angular + .module('app.widgets') + + /* Bestell-Direktive, die für das Bestell-Modul spezifisch ist */ + .directive('orderCalendarRange', orderCalendarRange) + + /* Verkaufs-Direktive, die überall in der Verkaufsanwendung genutzt werden kann */ + .directive('salesCustomerInfo', salesCustomerInfo) + + /* "Spinner"-Direktive, die in verschiedenen Anwendungen verwendet werden kann */ + .directive('sharedSpinner', sharedSpinner); + + function orderCalendarRange() { + /* Implementierungsdetails */ + } + + function salesCustomerInfo() { + /* Implementierungsdetails */ + } + + function sharedSpinner() { + /* Implementierungsdetails */ + } + ``` + + ```javascript + /* empfohlen */ + /* calendarRange.directive.js */ + + /** + * @desc Bestell-Direktive, die speziell für das Bestell-Modul der Firma Acme bestimmt ist. + * @example
+ */ + angular + .module('sales.order') + .directive('acmeOrderCalendarRange', orderCalendarRange); + + function orderCalendarRange() { + /* Implementierungsdetails */ + } + ``` + + ```javascript + /* empfohlen */ + /* customerInfo.directive.js */ + + /** + * @desc Verkaufs-Direktive, die überall innerhalb der Verkaufsanwendung der Firma Acme genutzt werden kann + * @example
+ */ + angular + .module('sales.widgets') + .directive('acmeSalesCustomerInfo', salesCustomerInfo); + + function salesCustomerInfo() { + /* Implementierungsdetails */ + } + ``` + + ```javascript + /* empfohlen */ + /* spinner.directive.js */ + + /** + * @desc "Spinner"-Direktive, die in jeder Anwendung der Firma Acme genutzt werden kann. + * @example
+ */ + angular + .module('shared.widgets') + .directive('acmeSharedSpinner', sharedSpinner); + + function sharedSpinner() { + /* Implementierungsdetails */ + } + ``` + + Anmerkung: Es gibt viele Bennennungsmöglichkeiten für Direktiven, weil sie in einem schmalen oder weiten Gültigkeitsbereich genutzt werden können. Wählen sie eine, die den Namen der Direktive und ihren Dateinamen eindeutig und klar verständlich macht. Einige Beispiele befinden sich weiter unten, aber schauen Sie sich den Abschnitt zur [Namensgebung](#naming) an, um weitere Empfehlungen zu sehen. + +### DOM-Maniuplation in einer Directive +###### [Style [Y072](#style-y072)] + + - Benutzen Sie zur direkten Manipulation des DOM eine Direktive. Wenn es alternative Wege gibt, wie zum Beispiel CSS, um Stile zu setzen oder [Animation Services](https://docs.angularjs.org/api/ngAnimate), Angular Templates, [`ngShow`](https://docs.angularjs.org/api/ng/directive/ngShow) oder [`ngHide`](https://docs.angularjs.org/api/ng/directive/ngHide), dann nutzen sie diese anstatt. Wenn die Direktive zum Beispiel einfach nur etwas versteckt oder zeigt, dann benutzen Sie ngHide/ngShow. + + *Warum?*: DOM-Manipulationen können schwer zu testen oder zu debuggen sein und es gibt oftmals bessere Wege (z. B. CSS, Animationen oder Templates) + +### Vergeben sie einen eindeutigen Prefix für eine Direktive +###### [Style [Y073](#style-y073)] + + - Vergeben sie einen kurzen, eindeutigen und beschreibenden Prefix für die Direktive, wie `acmeSalesCustomerInfo`. Dieser würde in HTML als `acme-sales-customer-info` genutzt. + + *Warum?*: Der eindeutige kurze Prefix gibt den Kontext und den Ursprung der Direktive wieder. Ein Prefix wie `cc-` könnte ausweisen, dass die Direktive Teil einer "CodeCamper"-Anwendung ist, wohingegegen `acme-` auf eine Direktive der Firma Acme hinweisen könnte. + + Anmerkung: Vermeiden Sie `ng-`, weil dieser Präfix für Angular-Direktiven reserviert ist. Recherchieren Sie viel genutzte Direktiven, um einem Namenskonflikt wie zum Beispiel mit `ion-` für das [Ionic Framework](http://ionicframework.com/) vorzubeugen. + +### Beschränken Sie Direktiven auf Elemente und Attribute +###### [Style [Y074](#style-y074)] + + - Beim Erstellen einer Direktive, die sinnvollerweise als alleinstehendes Element entwickelt werden kann, sollten Sie diese auf `E` (Custom Element) und optional auf `A` (Custom Attribute) beschränken. Wenn die Direktive ihr eigenes Control sein könnte, ist `E` generell angebracht. Die allgemeine Anweisung lautet, `EA` zu erlauben. Aber man sollte so entwickeln, als würde man ein alleinstehendes Element entwickeln, ein Attribut nur dann, wenn es ein existierendes DOM-Element erweitert. + + *Warum?*: Es macht Sinn. + + *Warum?*: Auch wenn wir es zulassen können, eine Direktive als Klasse zu verwenden: Wenn die Direktive tatsächlich wie ein Element agiert, macht es mehr Sinn, diese auch als Element zu entwickeln - oder gegebenenfalls als Attribut. + + Anmerkung: EA ist der Standard für Angular 1.3 + + + ```html + +
+ ``` + + ```javascript + /* zu vermeiden */ + angular + .module('app.widgets') + .directive('myCalendarRange', myCalendarRange); + + function myCalendarRange() { + var directive = { + link: link, + templateUrl: '/template/is/located/here.html', + restrict: 'C' + }; + return directive; + + function link(scope, element, attrs) { + /* */ + } + } + ``` + + ```html + + +
+ ``` + + ```javascript + /* empfohlen */ + angular + .module('app.widgets') + .directive('myCalendarRange', myCalendarRange); + + function myCalendarRange() { + var directive = { + link: link, + templateUrl: '/template/is/located/here.html', + restrict: 'EA' + }; + return directive; + + function link(scope, element, attrs) { + /* */ + } + } + ``` + +### Direktiven und ControllerAs +###### [Style [Y075](#style-y075)] + + - Benutzen Sie die `controller as`-Syntax bei einer Direktive, um `controller as` stimmig mit einer View-Controller-Zuweisung einsetzen zu können. + + *Warum?*: Es macht Sinn und ist nicht schwer. + + Anmerkung: Die folgende Direktive demonstriert einige Arten, in denen man "scope" innerhalb von "link"-Direktiven-Controllern einsetzt, die "controllerAs" nutzen. Ich habe das Template eingebunden, nur um alles an einem Platz zu haben. + + Anmerkung: Bezüglich Dependency Injection, schauen Sie sich bitte [Manually Identify Dependencies](#manual-annotating-for-dependency-injection) an. + + Anmerkung: Berücksichtigen Sie, dass sich der Controller einer Direktive außerhalb der "Closure" der Direktive befindet. Diese Richtlinie verhindert Probleme, bei denen die eingefügten Abhängigkeiten als nicht erreichbarer Code nach einem `return` generiert werden. + + ```html +
+ ``` + + ```javascript + angular + .module('app') + .directive('myExample', myExample); + + function myExample() { + var directive = { + restrict: 'EA', + templateUrl: 'app/feature/example.directive.html', + scope: { + max: '=' + }, + link: linkFunc, + controller: ExampleController, + controllerAs: 'vm', + bindToController: true // because the scope is isolated + }; + + return directive; + + function linkFunc(scope, el, attr, ctrl) { + console.log('LINK: scope.min = %s *** should be undefined', scope.min); + console.log('LINK: scope.max = %s *** should be undefined', scope.max); + console.log('LINK: scope.vm.min = %s', scope.vm.min); + console.log('LINK: scope.vm.max = %s', scope.vm.max); + } + } + + ExampleController.$inject = ['$scope']; + + function ExampleController($scope) { + // $scope wird nur zum Vergleich eingefügt (injiziert) + var vm = this; + + vm.min = 3; + + console.log('CTRL: $scope.vm.min = %s', $scope.vm.min); + console.log('CTRL: $scope.vm.max = %s', $scope.vm.max); + console.log('CTRL: vm.min = %s', vm.min); + console.log('CTRL: vm.max = %s', vm.max); + } + ``` + + ```html + +
hello world
+
max={{vm.max}}
+
min={{vm.min}}
+ ``` + + Bemerkung Note: Sie können auch den Controller benennen, wenn Sie ihn in die link-Funktion einfügen und Attribute der Direktive als Properties des Controllers nutzen. + + ```javascript + // Alternative zum obigen Beispiel + function linkFunc(scope, el, attr, vm) { + console.log('LINK: scope.min = %s *** should be undefined', scope.min); + console.log('LINK: scope.max = %s *** should be undefined', scope.max); + console.log('LINK: vm.min = %s', vm.min); + console.log('LINK: vm.max = %s', vm.max); + } + ``` + +###### [Style [Y076](#style-y076)] + + - Benutzen Sie `bindToController = true` wenn Sie die `controller as`-Syntax mit einer Direktive nutzen wollen und Sie das äußere Scope an das Scope des Controllers der Direktive binden wollen. + + *Warum?*: Es erleichtert die Bindung des äußeren Scope an das Scope des Controllers der Direktive. + + Anmerkung: `bindToController` wurde mit Angular 1.3.0 eingeführt. + + ```html +
+ ``` + + ```javascript + angular + .module('app') + .directive('myExample', myExample); + + function myExample() { + var directive = { + restrict: 'EA', + templateUrl: 'app/feature/example.directive.html', + scope: { + max: '=' + }, + controller: ExampleController, + controllerAs: 'vm', + bindToController: true + }; + + return directive; + } + + function ExampleController() { + var vm = this; + vm.min = 3; + console.log('CTRL: vm.min = %s', vm.min); + console.log('CTRL: vm.max = %s', vm.max); + } + ``` + + ```html + +
hello world
+
max={{vm.max}}
+
min={{vm.min}}
+ ``` + +**[Zurück zum Anfang](#table-of-contents)** + +## Promises für einen Controller auflösen +### Promises beim Aktivieren eines Controllers +###### [Style [Y080](#style-y080)] + + - Verlagern sie die Start-Logik eines Controllers in eine `activate`-Funktion. + + *Warum?*: Ist die Start-Logik an einem einheitlichen Platz innerhalb des Controllers, wird ihr Auffinden vereinfacht, sie ist besser zu testen und diese Methode hilft dabei, zu verhindern, dass die Startlogik überall im Controller verteilt ist. + + *Warum?*: Das `activate` ist eine komfortable Art und Weise, diese Logik für einen Refresh des Controllers / der View zu nutzen. Es hält die Logik zusammen, liefert die View schneller an den Benutzer, erleichtert Animationen mit `ng-view` oder `ui-view`, und macht auch einen flotteren Eindruck beim Benutzer. + + Anmerkung: Wenn Sie die Routennavigation bedingt abbrechen müssen, bevor der Controller gestartet wird, dann sollten sie stattdessen ein [route resolve](#style-y081) nutzen. + + ```javascript + /* zu vermeiden */ + function Avengers(dataservice) { + var vm = this; + vm.avengers = []; + vm.title = 'Avengers'; + + dataservice.getAvengers().then(function(data) { + vm.avengers = data; + return vm.avengers; + }); + } + ``` + + ```javascript + /* empfohlen */ + function Avengers(dataservice) { + var vm = this; + vm.avengers = []; + vm.title = 'Avengers'; + + activate(); + + //////////// + + function activate() { + return dataservice.getAvengers().then(function(data) { + vm.avengers = data; + return vm.avengers; + }); + } + } + ``` + +### Promises für Routen auflösen +###### [Style [Y081](#style-y081)] + + - Ist ein Controller abhängig von der Auflösung eines Promise, der vor der Aktivierung des Controllers aufgelöst sein muss, dann muss diese Abhängigkeit im `$routeProvider` aufgelöst werden, und zwar bevor die Controller-Logik ausgeführt wird. Wenn Sie eine Routen-Navigation bedingt abbrechen müssen, bevor der Controller aktiviert ist, nutzen Sie einen Route-Resolver. + + - Nutzen Sie ein "route resolve" wenn Sie bestimmen wollen, ob eine Routennavigation abgebrochen werden soll, bevor die View eingeblendet wird. + + *Warum?*: Es kann sein, dass ein Controller Daten benötigt, noch bevor er geladen wird. Diese Daten können von einem Promise aus einer Factory oder über [$http](https://docs.angularjs.org/api/ng/service/$http) kommen. Ein ["route resolve"](https://docs.angularjs.org/api/ngRoute/provider/$routeProvider) zu benutzen, ermöglicht, dass der Promise aufgelöst wird, bevor die Controller-Logik ausgeüfhrt wird. Also kann es notwendig werden, eine Aktion aufgrund der Daten aus dem Promis auszuführen. + + *Warum?*: Der Code wird nach den Routennavigation innerhalb der activate-Funktion des Controllers ausgeführt. Der View wird ebenso geladen. Die Datenbindung steht, wenn der aktive Promise aufgelöst ist. Eine "Busy-Animation" kann während der Einblendung des views (via `ng-view` oder `ui-view`) angezeigt werden. + + Anmerkung: Der Code wird vor der Routennavigation über einen Promise ausgeführt. Wird der Promise zurückgewiesen, wird die Navigation abgebrochen. Resolve bewirkt, dass die neue View auf die Auflösung der Route wartet. Ein "Busy-Indikator" kann vor dem Auflösen und während der Einblendung des Views angezeigt werden. Wenn Sie die View schneller einblenden wollen und keinen Kontrollpunkt benötigen, an dem geprüft wird, ob die View überhaupt zur Verfügung steht, sollten Sie die [Controller `activate` Technik](#style-y080) in Betracht ziehen. + + ```javascript + /* zu vermeiden */ + angular + .module('app') + .controller('Avengers', Avengers); + + function Avengers(movieService) { + var vm = this; + // unresolved + vm.movies; + // resolved asynchronously + movieService.getMovies().then(function(response) { + vm.movies = response.movies; + }); + } + ``` + + ```javascript + /* besser */ + + // route-config.js + angular + .module('app') + .config(config); + + function config($routeProvider) { + $routeProvider + .when('/avengers', { + templateUrl: 'avengers.html', + controller: 'Avengers', + controllerAs: 'vm', + resolve: { + moviesPrepService: function(movieService) { + return movieService.getMovies(); + } + } + }); + } + + // avengers.js + angular + .module('app') + .controller('Avengers', Avengers); + + Avengers.$inject = ['moviesPrepService']; + function Avengers(moviesPrepService) { + var vm = this; + vm.movies = moviesPrepService.movies; + } + ``` + + Anmerkung: Das untenstehende Beispiel zeigt die Stellen, an denen die Route mit einer benannten Funktion aufgelöst wird. Das ist einfacher zu debuggen und vereinfacht auch die Handhabung von Dependency Injection. + + ```javascript + /* noch besser */ + + // route-config.js + angular + .module('app') + .config(config); + + function config($routeProvider) { + $routeProvider + .when('/avengers', { + templateUrl: 'avengers.html', + controller: 'Avengers', + controllerAs: 'vm', + resolve: { + moviesPrepService: moviesPrepService + } + }); + } + + function moviesPrepService(movieService) { + return movieService.getMovies(); + } + + // avengers.js + angular + .module('app') + .controller('Avengers', Avengers); + + Avengers.$inject = ['moviesPrepService']; + function Avengers(moviesPrepService) { + var vm = this; + vm.movies = moviesPrepService.movies; + } + ``` + Anmerkung: Die Abhängigkeit von `movieService` im Code ist bei einer Minifizierung nicht sicher. Um Details zu sehen, wie dieser Code für eine sichere Minifizierung vorbereitet wird, schauen Sie sich den Abschnitt über [Dependency Injection](#manual-annotating-for-dependency-injection) und über [Minifizierung und Code-Anmerkungen](#minification-and-annotation) an. + +**[Zurück zum Anfang](#table-of-contents)** + +## Manuelle Code-Anmerkungen für das Einfügen von Abhängigkeiten (Dependency Injection) + +### Unsichere Minifizierung +###### [Style [Y090](#style-y090)] + + - Vermeiden Sie es, die kurze Deklarationssyntax für Ahängigkeiten ohne einen für die Minifizierung sicheren Ansatz zu verwenden. + + *Warum?*: Die Parameter der Komponente (z. B. Controller, Factory, etc.) werden in abgekürzte Variablen gewandelt. So kann zum Beispiel aus `common` und `dataservice` ein `a` oder `b` werden, was von Angular nicht gefunden wird. + + ```javascript + /* zu vermeiden - nicht sicher bei Minifizierung */ + angular + .module('app') + .controller('Dashboard', Dashboard); + + function Dashboard(common, dataservice) { + } + ``` + + Dieser Code wird abgekürzte Variablen ergeben, wenn er minifiziert wird und deshalb Laufzeitfehler verursachen. + + ```javascript + /* zu vermeiden - nicht sicher bei Minifizierung */ + angular.module('app').controller('Dashboard', d);function d(a, b) { } + ``` + +### Abhängigkeiten manuell identifizieren +###### [Style [Y091](#style-y091)] + + - Benutzen Sie `$inject` um Ihre Abhängigkeiten für Angular-Komponenten manuell zu identifizieren. + + *Warum?*: Dieses Verfahren spiegelt die Technik wieder, die von [`ng-annotate`](https://github.com/olov/ng-annotate) genutzt wird, welche ich für die Automatisierung der Erstellung von minifikationssicheren Abhängigkeiten empfehleh. Wenn `ng-annotate` erkennt, dass eine solche Deklaration vorgenommen wurde, wird diese nicht dupliziert. + + *Warum?*: Dies bewahrt Ihre Abhängigkeiten vor Problemen bei einer Minifizierung, bei der die Parameter abgekürzt werden. Zum Beispiel wird aus `common` und `dataservice` ein `a` oder `b`, was von Angular nicht gefunden wird. + + *Warum?*: Vermeiden Sie Abhängigkeiten direkt im Code in Form von langen Listen, da diese in Form eines Arrays schwer zu lesen sind. Dies kann auch zu Verwirrungen führen, weil dieses Array eine Liste von Strings ist, das letzte Element aber die Funktion der Komponente. + + ```javascript + /* zu vermeiden */ + angular + .module('app') + .controller('Dashboard', + ['$location', '$routeParams', 'common', 'dataservice', + function Dashboard($location, $routeParams, common, dataservice) {} + ]); + ``` + + ```javascript + /* zu vermeiden */ + angular + .module('app') + .controller('Dashboard', + ['$location', '$routeParams', 'common', 'dataservice', Dashboard]); + + function Dashboard($location, $routeParams, common, dataservice) { + } + ``` + + ```javascript + /* empfohlen */ + angular + .module('app') + .controller('Dashboard', Dashboard); + + Dashboard.$inject = ['$location', '$routeParams', 'common', 'dataservice']; + + function Dashboard($location, $routeParams, common, dataservice) { + } + ``` + + Anmerkung: Wenn sich Ihre Funktion unterhalb eines returns befindet, kann `$inject` unerreichbar werden (das kann in einer Direktive passieren). Sie können dies vermeiden, indem sie den Controller aus der Direktive herauslösen. + + ```javascript + /* zu vermeiden */ + // inside a directive definition + function outer() { + var ddo = { + controller: DashboardPanelController, + controllerAs: 'vm' + }; + return ddo; + + DashboardPanelController.$inject = ['logger']; // Unreachable + function DashboardPanelController(logger) { + } + } + ``` + + ```javascript + /* empfohlen */ + // outside a directive definition + function outer() { + var ddo = { + controller: DashboardPanelController, + controllerAs: 'vm' + }; + return ddo; + } + + DashboardPanelController.$inject = ['logger']; + function DashboardPanelController(logger) { + } + ``` + +### Route Resolver Abhängigkeiten manuell identifizieren +###### [Style [Y092](#style-y092)] + + - Benutzen Sie `$inject` um die Abhängigkeiten in Ihrem Route Resolver für Angular-Komponenten zu identifizieren. + + *Warum?*: Diese Technik löst eine anonyme Funktion aus dem Route Resolver heraus und macht sie lesbarer. + + *Warum?*: Eine `$inject`-Anweisung kann einfach einem Resolver vorangestellt werden, um Abhängigkeiten bei Minifizierung sicher zu machen. + + ```javascript + /* empfohlen */ + function config($routeProvider) { + $routeProvider + .when('/avengers', { + templateUrl: 'avengers.html', + controller: 'AvengersController', + controllerAs: 'vm', + resolve: { + moviesPrepService: moviesPrepService + } + }); + } + + moviesPrepService.$inject = ['movieService']; + function moviesPrepService(movieService) { + return movieService.getMovies(); + } + ``` + +**[Zurück zum Anfang](#table-of-contents)** + +## Minifizierung und Code-Anmerkungen + +### ng-annotate +###### [Style [Y100](#style-y100)] + + - Benutzen Sie [ng-annotate](//github.com/olov/ng-annotate) für [Gulp](http://gulpjs.com) oder [Grunt](http://gruntjs.com) und versehen Sie die Funktionen mit den notwendigen `/** @ngInject */`-Kommentaren, die für die "automatische" Dependency Injection genutzt werden sollen. + + *Warum?*: Dies schützt Ihren Code vor Abhängigkeiten, die keiner minifizierungssicheren Technik entsprechen. + + *Warum?*: [`ng-min`](https://github.com/btford/ngmin) wird nicht mehr unterstützt. + + >Ich bevorzuge Gulp, weil es gefühlt einfacher zu schreiben, zu lesen und zu debuggen ist. + + Der folgende Code nutzt keine minifizierungssicheren Abhängigkeiten. + + ```javascript + angular + .module('app') + .controller('Avengers', Avengers); + + /* @ngInject */ + function Avengers(storageService, avengerService) { + var vm = this; + vm.heroSearch = ''; + vm.storeHero = storeHero; + + function storeHero() { + var hero = avengerService.find(vm.heroSearch); + storageService.save(hero.name, hero); + } + } + ``` + + Wird der obenstehende Code durch ng-annotate geschickt, wird folgende Ausgabe mit der `$inject`-Anmerkung erstellt und der Code wird minifizerungssicher. + + ```javascript + angular + .module('app') + .controller('Avengers', Avengers); + + /* @ngInject */ + function Avengers(storageService, avengerService) { + var vm = this; + vm.heroSearch = ''; + vm.storeHero = storeHero; + + function storeHero() { + var hero = avengerService.find(vm.heroSearch); + storageService.save(hero.name, hero); + } + } + + Avengers.$inject = ['storageService', 'avengerService']; + ``` + + Anmerkung: Entdeckt `ng-annotate` bereits vorhandene Kommentare (z. B. bei erkanntem `@ngInject`), werden die `$inject`-Befehle nicht dupliziert. + + Anmerkung: Wenn Sie einen Route Resolver nutzen, können sie die Funktion des Resolvers mit `/* @ngInject */` markieren, und es wird eine korrekte Code-Anmerkung erstellt, die alle eingefügten Abhängigkeiten minifizierungssicher hält. + + ```javascript + // Using @ngInject annotations + function config($routeProvider) { + $routeProvider + .when('/avengers', { + templateUrl: 'avengers.html', + controller: 'Avengers', + controllerAs: 'vm', + resolve: { /* @ngInject */ + moviesPrepService: function(movieService) { + return movieService.getMovies(); + } + } + }); + } + ``` + + > Anmerkung: Ab der 1.3er Version von Angular können Sie den `ngStrictDi` Parameter der [`ngApp`](https://docs.angularjs.org/api/ng/directive/ngApp)-Direktive nutzen, um potentiell minfizierungsunsichere Abhängigkeiten aufzuspühren. Wurde eine solche Abhängigkeit entdeckt, dann wird der Injector im "strict-di"-Modus erstellt und verursacht Fehler beim Ausfüren von Funktionen, die keine explizite Code-Anmerkung besitzen (was nicht minifizerungssicher ist). Debug-Informationen werden in der Konsole ausgegeben, um den betreffenden Code nachvollziehen zu können. Ich bevorzuge die Nutzung von `ng-strict-di` für das Debugging. + `` + +### Gulp oder Grunt für ng-annotate nutzen +###### [Style [Y101](#style-y101)] + + - Benutzen Sie [gulp-ng-annotate](https://www.npmjs.org/package/gulp-ng-annotate) oder [grunt-ng-annotate](https://www.npmjs.org/package/grunt-ng-annotate) in einer autmatisierten Build-Task. Fügen sie `/* @ngInject */` vor jeder Funktion ein, die Abhängigkeiten hat. + + *Warum?*: ng-annotate erkennt die meisten Abhängigkeiten automatisch, benötigt manchmal aber Hinweise durch die `/* @ngInject */`-Syntax. + + Der folgende Code ist ein Beispiel für die Nutzung von ngAnnotage in einer Gulp-Task. + + ```javascript + gulp.task('js', ['jshint'], function() { + var source = pkg.paths.js; + + return gulp.src(source) + .pipe(sourcemaps.init()) + .pipe(concat('all.min.js', {newLine: ';'})) + // Code-Anmerkung vor dem "Uglifying" einfügen, damit der Code korrekt minifiziert wird. + .pipe(ngAnnotate({ + // "true" hilft dort eine Anmerkung einzufügen, wo @ngInject nicht genutzt wird. Die Notwendigkeit wird aus dem Code-Kontext geschlossen. + // Funktioniert nicht bei "resolve", muss für diesen Fall also explizit gesetzt werden. + add: true + })) + .pipe(bytediff.start()) + .pipe(uglify({mangle: true})) + .pipe(bytediff.stop()) + .pipe(sourcemaps.write('./')) + .pipe(gulp.dest(pkg.paths.dev)); + }); + + ``` + +**[Zurück zum Anfang](#table-of-contents)** + +## Fehlerbehandlung + +### Decorator +###### [Style [Y110](#style-y110)] + + - Benutzen Sie einen [Decorator](https://docs.angularjs.org/api/auto/service/$provide#decorator) während der Konfiguration, indem Sie den [`$provide`](https://docs.angularjs.org/api/auto/service/$provide)-Service im [`$exceptionHandler`](https://docs.angularjs.org/api/ng/service/$exceptionHandler)-Service ansprechen, um eigene Aktionen bei einem auftauchenden Fehler (einer Ausnahme) auszuführen. + + *Warum?*: Dies bietet einen einen stimmigen Weg, unbehandelte Angular-Fehler während der Entwicklung oder zur Laufzeit abzufangen. + + Anmerkung: Eine weitere Option neben der Benutzung eines Decorators, stellt das Überschreiben des Service dar. Diese Möglichkeit ist gut, wenn Sie aber das Standardverhalten beibehalten wollen, dann ist die Erweiterung mit einem Decorator angebracht. + + ```javascript + /* empfohlen */ + angular + .module('blocks.exception') + .config(exceptionConfig); + + exceptionConfig.$inject = ['$provide']; + + function exceptionConfig($provide) { + $provide.decorator('$exceptionHandler', extendExceptionHandler); + } + + extendExceptionHandler.$inject = ['$delegate', 'toastr']; + + function extendExceptionHandler($delegate, toastr) { + return function(exception, cause) { + $delegate(exception, cause); + var errorData = { + exception: exception, + cause: cause + }; + /** + * Der Fehler könnte zu einer Liste im Service oder + * zum $rootScope hinzugefügt werden oder bei einem + * Remote-Webserver oder lokal protokolliert oder + * einfach wieder hart "geworfen" werden. Es obliegt + * ganz Ihnen. + * + * throw exception; + */ + toastr.error(exception.msg, errorData); + }; + } + ``` + +### Komponente zum Abfangen von Fehlern (Ausnahmen) +###### [Style [Y111](#style-y111)] + + - Erstellen Sie eine Factory, die ein Inferface bereitstellt, mit dem Sie Fehler elegant abfangen und behandeln. + + *Warum?*: Dies bietet eine konsistente Methode, Fehler abzufangen, die in Ihrem Code geworfen werden (z. B. während eines XHR-Aufrufs oder bei Fehlern in einem Promise). + + Anmerkung: Eine Komponente, die die Fehler abfängt stellt eine gute Möglichkeit dar, Fehler an den Stellen abzufangen, von denen Sie wissen, dass sie auftreten können. Zum Beispiel, wenn Sie Daten über einen XHR-Aufruf von einem Webservice anfragen und Sie jegliche Art von Fehler, die von diesem Service zurück kommen, speziell behandeln wollen. + + ```javascript + /* empfohlen */ + angular + .module('blocks.exception') + .factory('exception', exception); + + exception.$inject = ['logger']; + + function exception(logger) { + var service = { + catcher: catcher + }; + return service; + + function catcher(message) { + return function(reason) { + logger.error(message, reason); + }; + } + } + ``` + +### Routenfehler +###### [Style [Y112](#style-y112)] + + - Behandeln und protokollieren Sie alle Routingfehler mit [`$routeChangeError`](https://docs.angularjs.org/api/ngRoute/service/$route#$routeChangeError). + + *Warum?*: Bietet einen stimmigen Weg, um alle Routingfehler zu behandeln. + + *Warum?*: Bietet potentiell die Möglichkeit die Akzeptanz beim Benutzer zu steigern, wenn ein Routingfehler autftritt und dieser auf informative Weise mit Möglichkeiten zur Behebung am Bildschirm angezeigt wird. + + ```javascript + /* empfohlen */ + var handlingRouteChangeError = false; + + function handleRoutingErrors() { + /** + * Abbruch des Routings: + * Gehe bei einem Routingfehler zurück zum Dashboard. + * Biete eine Möglichkeit wieder auszusteigen, wenn dies + * zweimal versucht wird. + */ + $rootScope.$on('$routeChangeError', + function(event, current, previous, rejection) { + if (handlingRouteChangeError) { return; } + handlingRouteChangeError = true; + var destination = (current && (current.title || + current.name || current.loadedTemplateUrl)) || + 'unknown target'; + var msg = 'Error routing to ' + destination + '. ' + + (rejection.msg || ''); + + /** + * Optionales protokollieren über einen Logging-Service oder $log. + * (Der Logging-Service muss als Abhängigkeit eingefügt werden.) + */ + logger.warning(msg, [current]); + + /** + * Gehe bei einem Routingfehler zu einer anderen Route oder anderem Status. + */ + $location.path('/'); + + } + ); + } + ``` + +**[Zurück zum Anfang](#table-of-contents)** + +## Namensgebung + +### Richtlinien der Namensgebung +###### [Style [Y120](#style-y120)] + + - Benutzen sie stimmige Namen für alle Komponenten, einem Muster folgend, welches die Hauptfunktionen (Features) einer Komponente und dann (optional) ihren Typ beschreibt. + Meine empfohlenes Muster ist `feature.typ.js`. Es gibt zwei zu vergebene Namen für die meisten Komponenten: + * der Dateiname (`avengers.controller.js`) + * der Name der bei Angular zu registrierenden Komponente (`AvengersController`) + + *Warum?*: Richtlinien der Namensgebung bieten einen stimmigen Weg, Inhalte auf einen Blick zu finden. Dabei ist die Stimmigkeit dieser Namensgebung innerhalb des Projekts auschlaggebend. Die Stimmigkeit innerhalb des Teams ist wichtig. Die Stimmigkeit innerhalb einer Firma bedeutet enorme Effizienz. + + *Warum?*: Die Konventionen der Namensgebung sollen helfen, Ihren Code schneller wiederzufinden und einfacher zu verstehen. + +### Dateinamen von Features (Komponenten) +###### [Style [Y121](#style-y121)] + + - Benutzen Sie stimmige Namen für alle Komponenten, die einem Muster folgen: Hauptfunktion einer Komponente, und dann (optional) gefolgt vom Typ. Mein empfohlenes Muster ist `feature.typ.js`. + + *Warum?*: Bietet einen stimmigen Weg, Komponenten schnell zu identifizeren. + + *Warum?*: Bietet ein Suchmuster für alle automatisierten Aufgaben. + + ```javascript + /** + * allgemeine Optionen + */ + + // Controllers + avengers.js + avengers.controller.js + avengersController.js + + // Services/Factories + logger.js + logger.service.js + loggerService.js + ``` + + ```javascript + /** + * empfohlen + */ + + // Controller + avengers.controller.js + avengers.controller.spec.js + + // Services / Factories + logger.service.js + logger.service.spec.js + + // Konstanten + constants.js + + // Moduldefinitionen + avengers.module.js + + // Routen + avengers.routes.js + avengers.routes.spec.js + + // Konfiguration + avengers.config.js + + // Direktiven + avenger-profile.directive.js + avenger-profile.directive.spec.js + ``` + + Anmerkung: Eine weitere allgemeine Konvention ist die Benennung einer Controller-Datei ohne das Wort `controller`, wie `avengers.js` anstelle von `avengers.controller.js`. Bei allen anderen Konventionen bleibt aber der Typ-Suffix. Da die Controller das Gros der Komponenten ausmacht, spart dies Tipparbeit und sie sind trotzdem einfach zu identifizieren. Ich empfehle Ihnen, dass Sie eine Konvention für sich auswählen, und diese im Team strikt anwenden. Ich bevorzuge `avengers.controller.js`. + + ```javascript + /** + * empfohlen + */ + // Controller + avengers.js + avengers.spec.js + ``` + +### Name von Dateien für Tests +###### [Style [Y122](#style-y122)] + + - Benennen Sie Testspezifikationen gemäß der Komponente, die getestet werden soll, gefolgt vom Suffix `spec`. + + *Warum?*: Bietet einen stimmigen Weg, Komponenten schnell zu indentifizieren. + + *Warum?*: Bietet ein Suchmuster für [karma](http://karma-runner.github.io/) oder andere Testrunner. + + ```javascript + /** + * empfohlen + */ + avengers.controller.spec.js + logger.service.spec.js + avengers.routes.spec.js + avenger-profile.directive.spec.js + ``` + +### Namen für Controller +###### [Style [Y123](#style-y123)] + + - Nutzen Sie stimmige Namen für alle Controller und bennenen Sie diese nach ihrem Hauptmerkmal. Benutzen Sie UpperCamelCase für Controller, weil sie Konstruktoren sind. + + *Warum?*: Bietet einen stimmigen Weg, Controller schnell zu indentifizieren und zu referenzieren. + + *Warum?*: UpperCamelCase ist eine Konvention, ein Objekt zu identifizieren, welches über einen Konstruktor instantiiert werden kann. + + ```javascript + /** + * empfohlen + */ + + // avengers.controller.js + angular + .module + .controller('HeroAvengersController', HeroAvengersController); + + function HeroAvengersController() { } + ``` + +### Namens-Suffix für Controller +###### [Style [Y124](#style-y124)] + + - Hängen Sie an einen Controllernamen den Suffix `Controller`. + + *Warum?*: Der `Controller`-Suffix ist üblich und explizit. + + ```javascript + /** + * empfohlen + */ + + // avengers.controller.js + angular + .module + .controller('AvengersController', AvengersController); + + function AvengersController() { } + ``` + +### Namen für Factories +###### [Style [Y125](#style-y125)] + + - Nutzen Sie stimmige Namen für alle Factories und vergeben sie diese nach deren Hauptfunktion. Benutzen Sie Camel-Casing für Services und Factroies. Vermeiden Sie es, einer Factory oder einem Service ein `$` voranzutellen. + + *Warum?*: Bietet einen stimmigen Weg, Factories schnell zu identifizeren und zu referenzieren. + + *Warum?*: Verhindert Namenskollisionen mit eingebauten Factories und Serivces, die `$` als Präfix nutzen. + + ```javascript + /** + * empfohlen + */ + + // logger.service.js + angular + .module + .factory('logger', logger); + + function logger() { } + ``` + +### Namen für Direktiven +###### [Style [Y126](#style-y126)] + + - Benutzen Sie stimmige Namen für alle Direktiven gemäß der Camel-Case-Regel. Nutzen Sie einen kurzen Präfix, um den Bereich zu beschreiben, zu dem die Direktive gehört (Firmen- oder Projekt-Präfix). + + *Warum?*: Bietet einen stimmigen Weg, Direktiven schnell zu identifizeren und zu referenzieren. + + ```javascript + /** + * empfohlen + */ + + // avenger-profile.directive.js + angular + .module + .directive('xxAvengerProfile', xxAvengerProfile); + + // usage is + + function xxAvengerProfile() { } + ``` + +### Module +###### [Style [Y127](#style-y127)] + + - Beim Vorhandensein von mehreren Modulen, wird die Datei des Hauptmoduls `app.module.js` genannt, während Andere oder Module in Abhängigkeit nach dem benannt werden, was sie repräsentieren. Ein Admin-Modul wird zum Beispiel `admin.module.js` genannt. Die zugehörigen Namen für die Registrierung dieser Module wären `app` und `admin`. + + *Warum?*: Bietet Stimmigkeit bei Anwendungen mit mehreren Modulen und beim Erweitern zu einer größeren Anwendungen. + + *Warum?*: Bietet einen einfachen Weg, bei einer Automatisierung von Aufgaben, alle Moduldefinitionen zuerst zu laden, und dann erst die anderen Angular-Dateien (z. B. zum Packen (Bundling)). + +### Konfiguration +###### [Style [Y128](#style-y128)] + + - Trennen Sie die Konfiguration vom Modul und lagern sie diese in eine eigene Datei aus, die nach dem Modul benannt wird. Eine Konfigurationsdatei für das Hauptmodul `app` wird `app.config.js` genannt (oder einfach `config.js`). Eine Konfigurationsdatei für ein Modul namens `admin.module.js` wird `admin.config.js` genannt. + + *Warum?*: Trennt Konfiguration von der Moduldefinition, den Komponenten und dem "aktiven" Code. + + *Warum?*: Bietet einen leicht zu identifizierenden Platz, um die Kofiguration eines Moduls vorzunehmen. + +### Routen +###### [Style [Y129](#style-y129)] + + - Verlagern Sie die Routenkonfiguration in eine separate Datei. Ein Beispiel könnte `app.route.js` für das Hauptmodul und `admin.route.js` für das `admin`-Modul sein. Auch in kleineren Anwendungen bevorzuge ich diese Trennung vom Rest der Konfiguration. + +**[Zurück zum Anfang](#table-of-contents)** + +## Anwendungsstruktur: Das LIFT-Prinzip +### LIFT +###### [Style [Y140](#style-y140)] + + - LIFT steht für `L`ocate (auffinden), `I`dentify (identifizieren), `F`lat (flach), T`ry to stay DRY` (versuchen Sie, Ihren Code nicht zu wiederholen). Das bedeutet also, sie sollten Ihre Anwendung so strukturieren, dass sie Ihren Code schnell auffinden und auf einen Blick identifizieren können, für was der Code gut ist. Dabei sollten Sie die Struktur so flach wie möglich halten. Vermeiden Sie es unbedingt, Ihren Code zu wiederholen. + + *Warum LIFT?*: Bietet eine konsistente und gut skalierbare Stuktur, ist modular und macht es einfacher die Effizienz eines Entwicklers zu steigern, weil er seinen Code schneller finden kann. Prüfen Sie Ihre Andwendungsstruktur, indem Sie sich fragen: Wie schnell kann ich all die Dateien, die zu einem Feature gehören öffnen und mit ihnen arbeiten?" + + Falls ich mich mit meiner nicht mehr wohl fühle, dann schaue ich mir die LIFT-Anweisungen an: + + 1. `L`ocating - Finde Deinen Code auf einfache und schnelle Art + 2. `I`dentify - Identifiziere Deinen Code auf einen Blick + 3. `F`lat - Halte die Struktur so flach wie möglich, solange es geht + 4. `T`ry to stay DRY (Don’t Repeat Yourself) - Versuche Deinen Code nicht zu wiederholen + +### Locate (Code auffinden) +###### [Style [Y141](#style-y141)] + + - Gestalten Sie das Auffinden Ihres Codes intuitiv, einfach und schnell. + + *Warum?*: Ich finde diesen Punkt sehr wichtig für ein Projekt. Wenn ein Team die Dateien, an denen es dringend arbeiten muss, nicht ebenso schnell findet, kann es nicht effizient genug arbeiten. Die Struktur muss geändert werden. Zusammengehörende Dateien an der intuitivsten Stelle nahe beieinander zu platzieren, spart Ihnen einen Haufen Zeit. Eine beschreibende Struktur kann dabei helfen. + + ``` + /bower_components + /client + /app + /avengers + /blocks + /exception + /logger + /core + /dashboard + /data + /layout + /widgets + /content + index.html + .bower.json + ``` + +### Identify (Code identifizieren) +###### [Style [Y142](#style-y142)] + + - Wenn Sie einen Dateinamen sehen, sollten sie sofort wissen, was die Datei beinhaltet und für was sie steht. + + *Warum?*: Sie brauchen weniger Zeit, um nach Ihrem Code zu suchen und werden so effizienter. Wenn das bedeutet, dass Sie längere Dateinamen brauchen, dann sei es so. Seien Sie beschreibend bei der Namensvergabe und sorgen Sie dafür, dass eine Datei nur eine Komponente enthält. Vermeiden Sie Dateien mir mehreren Controllern, Services oder gar mit beidem. Ich weiche von dieser Regel ab, wenn ich sehr kleine Features habe, die alle miteinander verbunden und leicht identifizierbar sind. + +### Flat (flache Struktur) +###### [Style [Y143](#style-y143)] + + - Halten Sie die Verzeichnisstruktur so lange es geht so flach wie möglich. Sollten mehr als sieben Dateien in einem Verzeichnis stehen, denken Sie über eine Neuaufteilung nach. + + *Warum?*: Niemand will Dateien in einer Verzeichnisstruktur über sieben Ebenen suchen. Denken Sie an Menüs von Webseiten ... Alles, was über mehr als zwei Ebenen geht, sollte ernsthaft überdacht werden. Für eine Verzeichnisstruktur gibt es keine feste Regelung, aber sollte ein Verzeichnis sieben bis zehn Dateien enthalten, dann ist es vielleicht an der Zeit, Unterverzeichnisse einzurichten. Machen Sie es für sich selbst an Ihrem Wohlbefinden mit der Struktur fest. Benutzen sie eine flachere Struktur, bis Sie den Punkt erreichen, an dem es Sinn macht, ein neues Verzeichnis zu erstellen. + +### T-DRY (Versuchen Sie Ihren Code nicht zu wiederholen) +###### [Style [Y144](#style-y144)] + + - Seien Sie "DRY": Versuchen Sie Ihren Code nicht zu wiederholen. Aber übertreiben Sie es nicht, indem Sie die Lesbarkeit Ihres Codes dafür opfern. + + *Warum?*: Sich nicht ständig zu wiederholen ist wichtig, aber nicht entscheident, wenn Sie dafür andere Punkte von LIFT opfern. Ich möchte für eine View nicht session-view.html tippen, da es ja offentlichtlich eine View ist. Wenn etwas nicht offensichtlich oder einer Konvention unterliegt, dann benenne ich es. + +**[Zurück zum Anfang](#table-of-contents)** + +## Anwendungsstruktur + +### Allgemeine Richtlinien +###### [Style [Y150](#style-y150)] + + - Sie sollten eine kurzfristige und langfristive Sicht auf Ihre Implemtierung haben. Das bedeutet: Fangen Sie klein an, behalten Sie dabei aber im Auge, wohin Sie mir Ihrer Anwendung wollen. Jeder Code der Anwendung wird in einem Stammverzeichnis namens `app` abgelegt. Für den Inhalt gilt: Ein Feature pro Datei. Jeder Controller, Service, jedes Modul, jede View befindet sich in ihrer/seiner eigenen Datei. Alle externen Scripts (3rd Party Bibliotheken) werden in einem anderen Stammverzeichnis, nicht aber im `app`-Verzeichnis abgelegt. Ich habe sie nicht geschrieben und ich möchte nicht, dass sie meine Anwendung durcheinander bringen.(`bower_components`, `scripts`, `lib`). + + Anmerkung: Sie finden mehr Details und Gründe für diese Struktur in [diesem Originalbeitrag zur Anwendungsstruktur](http://www.johnpapa.net/angular-app-structuring-guidelines/). + +### Layout +###### [Style [Y151](#style-y151)] + + - Platzieren Sie Komponenten, die das allgemeingültige Layout der Anwendung ausmachen, in einem Verzeichnis namens `layout`. Dieses sollte eine Shell-View mit Controller enthalten. Die View agiert als Container für die Anwendung und enthält die Anwendung an sich: Navigation, Menüs, Bereiche für die Inhalte und andere Bereiche. + + *Warum?*: Organzisieren Sie das Layout an einem einzigen Ort, damit es innerhalb der Anwendung von überall her genutzt werden kann. + +### Vezeichnisse nach Hauptmerkmalen +###### [Style [Y152](#style-y152)] + + - Erstellen Sie Verzeichnisse gemäß der Hauptmerkmale, die sie darstellen. Wenn der Inhalt eines Verzeichnisse wächst und mehr als sieben Dateien fasst, sollten Sie darüber nachdenken, ein neues Verzeichnis zu erstellen. Dabei ist der Grenzwert aber individuell. + + *Warum?*: En Entwickler kann den gesuchten Code schnell auffinden, auf einen Blick identifizieren für was jede Datei steht, die Struktur ist so flach wie möglich und es gibt keine redundanten Namen. + + *Warum?*: Die LIFT-Richtlinien sind alle erfüllt. + + *Warum?*: Hilft zu verhindern, dass die Anwendung durcheinander gerät, weil der Inhalt nach den LIFT-Richtlinien organisiert ist. + + *Warum?*: Gibt es viele Dateien (mehr als zehn), ist es einfach, sie in einer konsistenten Verzeichnisstruktur zu finden, als in einer flachen Struktur. + + ```javascript + /** + * empfohlen + */ + + app/ + app.module.js + app.config.js + components/ + calendar.directive.js + calendar.directive.html + user-profile.directive.js + user-profile.directive.html + layout/ + shell.html + shell.controller.js + topnav.html + topnav.controller.js + people/ + attendees.html + attendees.controller.js + people.routes.js + speakers.html + speakers.controller.js + speaker-detail.html + speaker-detail.controller.js + services/ + data.service.js + localstorage.service.js + logger.service.js + spinner.service.js + sessions/ + sessions.html + sessions.controller.js + sessions.routes.js + session-detail.html + session-detail.controller.js + ``` + + ![Sample App Structure](https://raw.githubusercontent.com/johnpapa/angular-styleguide/master/assets/modularity-2.png) + + Anmerkung: Strukturieren Sie Ihre Verzeichnisse nicht nach Typ. Das hat zur Folge, dass Sie sich in vielen Verzeichnissen bewegen müssen, um ein einziges Feature bearbeiten zu wollen. Vergrößert sich die Anwendung auf fünf, zehn oder gar mehr als 25 Views und Controller (und andere Features), wird es sehr schnell unhandlich, im Gegensatz zur Organisation der Verzeichnisse nach Features. + + ```javascript + /* + * zu vermeiden + * Verzeichnisse-Nach-Typ-Alternativefolders-by-type. + * Ich empfehle stattdessen "Verzeichnisse-Nach-Feature". + */ + + app/ + app.module.js + app.config.js + app.routes.js + directives.js + controllers/ + attendees.js + session-detail.js + sessions.js + shell.js + speakers.js + speaker-detail.js + topnav.js + directives/ + calendar.directive.js + calendar.directive.html + user-profile.directive.js + user-profile.directive.html + services/ + dataservice.js + localstorage.js + logger.js + spinner.js + views/ + attendees.html + session-detail.html + sessions.html + shell.html + speakers.html + speaker-detail.html + topnav.html + ``` + +**[Zurück zum Anfang](#table-of-contents)** + +## Modularität + +### Viele kleine, eigentsändige Module +###### [Style [Y160](#style-y160)] + + - Erstellen Sie kleine Module, die für eine einzige Aufgabe zuständig sind und diese in sich kapseln. + + *Warum?*: Modulare Anwendungen machen es möglich, dass Funktionsmerkmale (Features) einfach eingeklinkt werden können. Somit kann ein Entwicklungsteam vertikale Stücke einer Applikation sukzessive ausrollen. Das bedeutet, dass neue Funtionsmerkmale nach ihrer Entwicklung einfach eingeklink werden können. + +### Erstellen Sie ein Modul für die Hauptanwendung (App-Modul) +###### [Style [Y161](#style-y161)] + + - Erstellen Sie ein Hauptmodul für die Anwendung, dessen Rolle es ist, alle Module und Funktionen der Anwendung zusammenzutragen. Nennen Sie das Modul nach Ihrer Anwendung. + + *Warum?*: Angular begünstigt Modularität und Muster für die Aufteilung von Code. Ein Hauptmodul für eine Anwendung zu erstellen, die andere Module zusammenzieht, ist ein einfacher Weg, um Module in eine Anwendung einzuklinken oder aus ihr auskzuklinken. + +### Halten Sie das App-Modul klein +###### [Style [Y162](#style-y162)] + + - Stellen Sie nur Logik ins App-Modul, die dazu dient, die Anwendungsbestandteile zusammenzuziehen. Features bleiben in ihren eigenen Feature-Modulen. + + *Warum?*: Weitere Logik außerhalb der ursprünglichen Aufgabe ins Hauptmodul einzubinden, wie zum Beispiel Datenabfragen, darstellen von Views, oder eine Logik, die nicht zum zusammenziehen der Module dient, bringt Verwirrung. Es wird schwierig, diese Features zu verwalten und auch zu testen. + + *Warum?*: Das App-Modul wird zum Manifest, welches die Module aufführt, die die Applikation ausmachen. + +### Funktionsbereiche sind Module +###### [Style [Y163](#style-y163)] + + - Erstellen Sie Module, die Funktionsbereiche darstellen, wie zum Beispiel das Layout, wiederverwendbare und allgemein verfügbare Services, Dashboards, und anwendungsspezifische Funktionsmerkmale (z. B. Kunden, Admin, Verkauf). + + *Warum?*: Eigenständige Module können reibungslos zur Anwendung hinzugefügt werden. + + *Warum?*: Sprints oder Iterationen können sich auf Funktionsbereiche beziehen. Diese können am Ende eines Sprints oder einer Iteration eingebunden werden. + + *Warum?*: Die Trennung von Funkstionsbereichen in Module erleichtert das isolierte Testen der Module und deren Wiederverwengung. + +### Wiederverwendbare Bausteine sind Module +###### [Style [Y164](#style-y164)] + + - Erstellen sie Module, die wiederverwendbare Applikationsbausteine für allgemeingültige Services, wie Fehlerbehandlung, Logging, Diagnostik, Sicherheit und lokale Datenablage, darstellen. + + *Warum?*: Diese Arten von Funktionen werden in vielen Anwendungen benötigt. Also können Sie durch die Trennung in ihre jeweiligen Module und aufgrund ihrer generischen Natur, von anderen Anwendungen verwendet werden. + +### Modulabhängigkeiten +###### [Style [Y165](#style-y165)] + + - Das Hauptmodul einer Applikation ist abhängig von den applikationsspezifischen Funktionsmodulen und den allgemeingültigen oder wiedervendbaren Modulen. + + ![Modularität und Abhängigkeiten](https://raw.githubusercontent.com/johnpapa/angular-styleguide/master/assets/modularity-1.png) + + *Warum?*: Das Hauptmodul der Applikation enthält ein schnell ersichtliches Manifest der Anwendungsfunktionen. + + *Warum?*: Jeder Funktionsbereich enthält ein Manifest, aus dem ersichtlich wird, von was er abhängig ist. Der Inhalt dieses Manifests kann also als Abhängigkeit in andere Anwendungen eingebunden werden, wo er dann auch funktioniert. + + *Warum?*: Interne Anwendungsfunktionen wie allgemeingültige Datenservices werden einfach aufgefunden und innerhalb von `app.core` (wählen Sie ihren Lieblingsnamen für diese Modul) genutzt. + + Anmerkung: Dies ist eine Strategie, die die Konstistenz innerhalb einer Anwendung begünstigt. Es gibt hierzu viele gute Möglichkeiten. Wählen Sie eine für sich aus, die stimmig ist, den Regeln von Angular in Puncto Abhängigkeiten folgt und einfach zu verwalten und zu skalieren ist. + + > Meine Strukturen unterscheiden sich von Projekt zu Projekt, aber sie folgen allesamt diesen Richtlinien zur Struktur und Modularität. Auch die Implementierung kann sich in Abhängigkeit der benötigten Funktionen und dem Team unterscheiden. Mit anderen Worten: Bestehen Sie nicht auf die exakte Nachbildung der hier vorgestellten Struktur, sondern passen Sie sie Ihren Gegebenheiten an. Behalten Sie dabei Konsistenz, Wartbarkeit und Effizienz im Hinterkopf. + + > In einer kleinen Anwendung können Sie darüber nachdenken, alle allgemeinen Abhängigkeiten im Hauptmodul unterzubringen, in dem die Funktionsmodule dann keine direkten Abhängigkeiten haben. Das erleichtert die Wartung kleinerer Anwendungen, erschwert aber die Wiederverwendbarkeit von Modulen außerhalb der Anwendung. + +**[Zurück zum Anfang](#table-of-contents)** + +## Startlogik + +### Konfiguration +###### [Style [Y170](#style-y170)] + + - Fügen Sie Ihren Code in die [Modulkonfiguration](https://docs.angularjs.org/guide/module#module-loading-dependencies) ein, die vor dem Start der Angular-Anwendung konfiguriert sein muss. Ideale Kandidaten hierfür sind Provider und Konstanten. + + *Warum?*: Es schränkt die Stellen ein, an denen konfiguriert wird. + + ```javascript + angular + .module('app') + .config(configure); + + configure.$inject = + ['routerHelperProvider', 'exceptionHandlerProvider', 'toastr']; + + function configure (routerHelperProvider, exceptionHandlerProvider, toastr) { + exceptionHandlerProvider.configure(config.appErrorPrefix); + configureStateHelper(); + + toastr.options.timeOut = 4000; + toastr.options.positionClass = 'toast-bottom-right'; + + //////////////// + + function configureStateHelper() { + routerHelperProvider.configure({ + docTitle: 'NG-Modular: ' + }); + } + } + ``` + +### Run-Block +###### [Style [Y171](#style-y171)] + + - Jeder Code, der laufen muss, wenn eine Anwendung startet, sollte in einer Factory implementiert, über eine Funktion im Zugriff und in den sog. [Run-Block](https://docs.angularjs.org/guide/module#module-loading-dependencies) eingebunden sein. + + *Warum?*: Code, der sich direkt in einem Run-Block befindet, ist schwer testbar. Wird er in eine Factory ausgelagert, ist er besser zu abstrahieren und zu simulieren. + + ```javascript + angular + .module('app') + .run(runBlock); + + runBlock.$inject = ['authenticator', 'translator']; + + function runBlock(authenticator, translator) { + authenticator.initialize(); + translator.initialize(); + } + ``` + +**[Zurück zum Anfang](#table-of-contents)** + +## Angular $ Wrapper Services + +### $document und $window +###### [Style [Y180](#style-y180)] + + - Benutzen Sie [`$document`](https://docs.angularjs.org/api/ng/service/$document) und [`$window`](https://docs.angularjs.org/api/ng/service/$window) anstelle von `document` und `window`. + + *Warum?*: Diese Services werden von Angular umschlossen und sind somit besser zu testen als wenn document und window in Tests benutzt wird. Dies hilft zu vermeiden, document und windows simulieren zu müssen. + +### $timeout and $interval +###### [Style [Y181](#style-y181)] + + - Benutzen Sie [`$timeout`](https://docs.angularjs.org/api/ng/service/$timeout) und [`$interval`](https://docs.angularjs.org/api/ng/service/$interval) anstelle von `setTimeout` und `setInterval` . + + *Warum?*: Diese Services werden von Angular umschlossen und sind besser zutesten. Sie nutzen Angulars "Digest-Cycle" und halten somit die Datenbindung synchron. + +**[Zurück zum Anfang](#table-of-contents)** + +## Testen +Unit-Tests tragen dazu bei, sauberen Code zu erhalten. Daher habe ich einige meiner Empfehlungen zu Unit-Test-Grundlagen als Links zur weiteren Information beigefügt. + +### Schreiben Sie Tests pro Anforderung +###### [Style [Y190](#style-y190)] + + - Schreiben Sie Ihre Tests für jede Anforderung. Beginnen Sie mit einem leeren Test und füllen Sie diesen, während Sie den Code für die Anforderung schreiben. + + *Warum?*: Testbeschreibungen zu zu verfassen, hilft dabei festzulegen, was in der Anforderung passiert, was nicht passiert und wie ein Testerfolg gemessen werden kann. + + ```javascript + it('Soll einen Avengers-Controller enthalten', function() { + // TODO + }); + + it('Soll einen Avenger enthalten, wenn nach Namen gefiltert wird', function() { + // TODO + }); + + it('Soll 10 Avengers enthalten', function() { + // TODO (mock data?) + }); + + it('Soll Avengers über XHR zurückliefern', function() { + // TODO ($httpBackend?) + }); + + // und so weiter + ``` + +### Testbibliotheken +###### [Style [Y191](#style-y191)] + + - Nutzen Sie [Jasmine](http://jasmine.github.io/) oder [Mocha](http://mochajs.org) für Unit-Tests. + + *Warum?*: Die Nutzung von Jasmin und Mocha ist sehr verbreitet in der Angular-Community. Beide sind stabil, gut gepflegt und liefern robuste Testfunktionen. + + Anmerkung: Wenn Sie Moche nutzen, sollten Sie in Erwägung ziehen, eine sogenannte Assert-Library, wie [Chai](http://chaijs.com) zu nutzen. Ich ziehe dem Mocha vor. + +### Testrunner +###### [Style [Y192](#style-y192)] + + - Benutzen Sie [Karma](http://karma-runner.github.io) als Testrunner. + + *Warum?*: Karma lässt sich leicht konfigurieren, um einzeln oder automatisch bei Codeänderungen aufgerufen zu werden. + + *Warum?*: Karma hängt sich leicht von allein in einen CI-Prozess (in Grunt oder Gulb) ein. + + *Warum?*: Verschiedene IDE'n wie [WebStorm](http://www.jetbrains.com/webstorm/) und [Visual Studio](http://visualstudiogallery.msdn.microsoft.com/02f47876-0e7a-4f6c-93f8-1af5d5189225) haben damit begonnen, Karma einzubinden. + + *Warum?*: Karma arbeitet wunderbar mit Task-Managern für Automatisierte Aufgaben wie [Grunt](http://www.gruntjs.com) (with [grunt-karma](https://github.com/karma-runner/grunt-karma)) und [Gulp](http://www.gulpjs.com) (with [gulp-karma](https://github.com/lazd/gulp-karma)) zusammen. + +### Simulation durch "Stubbing" und "Spying" +###### [Style [Y193](#style-y193)] + + - Benutzen Sie [Sinon](http://sinonjs.org/) um Komponenten im Rahmen von "Stubbing" und "Spying" (Mocking) zu simulieren. + + *Warum?*: Sinon arbeitet wunderbar mit Jasmine und Mocha zusammen und erweitert deren Fähigkeiten der Simulation von Komponenten. + + *Warum?*: Sinon erleichtert den Wechsel zwischen Jasmine and Mocha, wenn Sie beide ausprobieren möchten. + + *Warum?*: Sinon liefert gut verständliche, beschreibende Meldung, für den Fall, dass ein Test fehlschlägt. + +### Browser ohne Userinterface (Headless Browser) +###### [Style [Y194](#style-y194)] + + - Nutzen Sie [PhantomJS](http://phantomjs.org/), um Ihre Browsertests auf einem Server laufen zu lassen. + + *Warum?*: PhantomJS ist ein Browser, der kein Userinterface hat. Dies befähigt Sie, Browsertests ohne "sichtbaren" Browser durchzuführen. Sie müssen weder Chrome, noch Safari oder IE oder andere Browser auf Ihrem Server installieren. + + Anmerkung: Sie sollten trotzdem Tests auf allen Browsern in Ihrer Umgebung für Ihr Zielpublikum durchführen. + +### Codeanalyse +###### [Style [Y195](#style-y195)] + + - Lassen Sie JSHint über ihre Tests laufen. + + *Warum?*: Tests sind Code. JSHint prüft die Codequalität und kann Qualitätsprobleme aufdecken, die dazu führen können, dass Tests nicht saber laufen. + +### Erleichternde Rahmenbedingungen for JSHint und Regeln für Tests +###### [Style [Y196](#style-y196)] + + - Lockern sie die JSHint-Regeln für Ihren Testcode, damit `describe` und `expect` erlaubt werden. Lockern sie die Regeln auch für Ausdrücke, da Mocha diese benutzt. + + *Warum?*: Ihre Tests sind codiert und somit sollten Sie ihnen die gleiche Aufmerksamkeit in Puncto Codequalität widmen, wie Ihrem Produktionscode. Die Lockerung der Regeln für globale Variablen, die von Ihrem Test-Framework genutzt werden, erzielen Sie, wenn sie folgendes in Ihren Testcode einbinden. + + ```javascript + /* jshint -W117, -W030 */ + ``` + oder Sie fügen folgendes in die Datei mit Ihren JSHint Optionen ein. + + ```javascript + "jasmine": true, + "mocha": true, + ``` + + ![Testing Tools](https://raw.githubusercontent.com/johnpapa/angular-styleguide/master/assets/testing-tools.png) + +### Tests organisieren +###### [Style [Y197](#style-y197)] + + - Halten Sie Unit-Tests bei Ihrem Client-Programmcode. Die Testspezifikationen für die Server-Integrationstests oder die Tests für mehrere Komponenten platzieren Sie am besten in einem separaten `tests`-Verzeichnis. + + *Warum?*: Unit-Tests stehen in direktem Bezug zu einer spezifischen Komponente und Datei im Quellcode. + + *Warum?*: Es ist einfacher, sie auf dem neuesten Stand zu halten, weil Sie sie immer im Blick haben. Während Sie programmieren (ob Sie jetzt TDD betreiben oder während oder nach der Entwicklung testen), sind die Testspezifikationen weder aus der Sicht noch aus Ihren Gedanken. Deshalt ist es wahrscheinlicher, dass sie auch gepflegt werden, das dazu beiträgt, die Abdeckung des Codes durch Tests zu verbessern. + + *Warum?*: Wenn Sie Code aktualisieren ist es einfacher, auch die Tests im gleichen Zuge zu aktualisieren. + + *Warum?*: Code und Tests nebeneinander zu halten erleichtert es, sie zu finden und beide bei Bedarf zu verschieben. + + *Warum?*: Werden die Testspezifikationen neben dem Code gehalten, wird es einem Leser leichter gemacht zu verstehen, wie die Komponente eingesetzt werden soll und er entdeckt ihre bekannten Einschränkungen. + + *Warum?*: Die Testspezifikationen beim Erstellen eines Installationspakets für die Anwendung vom restlichen Code zu trennen, erledigt man einfach mit grunt oder gulp. + + ``` + /src/client/app/customers/customer-detail.controller.js + /customer-detail.controller.spec.js + /customers.controller.spec.js + /customers.controller-detail.spec.js + /customers.module.js + /customers.route.js + /customers.route.spec.js + ``` + +**[Zurück zum Anfang](#table-of-contents)** + +## Animationen + +### Anwendung +###### [Style [Y210](#style-y210)] + + - Benutzen Sie die ["subtle" Animationen von Angular](https://docs.angularjs.org/guide/animations) um zwischen Stati, Views oder primären sichtbaren Elementen hin und her zu wechseln. Binden Sie das [ngAnimate-Modul](https://docs.angularjs.org/api/ngAnimate) ein. Die drei Schlüssel hierzu sind "subtle", "smooth", "seamless". + + *Warum?*: Angulars "subtle" Animationen können die User-Experience erhöhen, wenn sie entsprechend eingesetzt werden. + + *Warum?*: Angulars "subtle" Animationen können die wahrgenommene Performance von View-Wechseln verbessern. + +### Sub Second +###### [Style [Y211](#style-y211)] + + - Nutzen Sie eine Kurze Dauer für Animationen. Ich starte immer bei 300ms und passe diese dann entsprechend an. + + *Warum?*: Lange Animationen können sich negativ auf die wahrgenomme Performance auswirken und einen gegentiligen Einfluss auf die User Experience haben und die Anwendung langsam aussehen lassen. + +### animate.css +###### [Style [Y212](#style-y212)] + + - Benutzen Sie [animate.css](http://daneden.github.io/animate.css/) für konventielle Animationen. + + *Warum?*: Die Animationen von animate.css sind schnell, sanft und einfach zu Ihrer Anwendung hinzuzufügen. + + *Warum?*: Bietet Konsistenz Ihrer Animationen. + + *Warum?*: animate.css ist weit verbeitet und gut getestet. + + Anmerkung: Schauen Sie sich diesen [tollen Beitrag von Matias Niemelä über Angular Animationen](http://www.yearofmoo.com/2013/08/remastered-animation-in-angularjs-1-2.html) an. + +**[Zurück zum Anfang](#table-of-contents)** + +## Kommentare + +### jsDoc +###### [Style [Y220](#style-y220)] + + - Wenn sie eine Dokumentation planen, dann nutzen Sie die [`jsDoc`](http://usejsdoc.org/)-Syntax, um Funktionsnamen, Beschreibungen, Parameter und Rückgabewerte zu dokumentieren. Benutzen Sie `@namespace` und `@memberOf`, um Ihre Anwendungsstruktur mit abzubilden. + + *Warum?*: Sie können die Dokumentation immer wieder aus ihrem Code generieren, statt sie neu zu schreiben. + + *Warum?*: Bietet die Konsistenz eines Industriewerkzeugs. + + ```javascript + /** + * Logger Factory + * @namespace Factories + */ + (function() { + angular + .module('app') + .factory('logger', logger); + + /** + * @namespace Logger + * @desc Anwendungsweiter Logger + * @memberOf Factories + */ + function logger($log) { + var service = { + logError: logError + }; + return service; + + //////////// + + /** + * @name logError + * @desc Protokolliert Fehler + * @param {String} Meldung, die protokolliert wird + * @returns {String} + * @memberOf Factories.Logger + */ + function logError(msg) { + var loggedMsg = 'Error: ' + msg; + $log.error(loggedMsg); + return loggedMsg; + }; + } + })(); + ``` + +**[Zurück zum Anfang](#table-of-contents)** + +## JS Hint + +### Nutzen Sie eine Optionsdatei +###### [Style [Y230](#style-y230)] + + - Benutzen Sie JS Hint um Ihren JavaScript-Code zu prüfen (Linting) und versichern Sie sich, dass sie die Prüffunktion für sich angepasst haben und die Optionsdatei in Ihrer Quellcodeverwaltung abgelegt haben. Schauen Sie sich die [JS Hint Dokumentation](http://www.jshint.com/docs/) an, um mehr über die Optionen zu erfahren. + + *Warum?*: Erstattet erste Meldung, bevor Sie den Code in die Quellcodeverwaltung übertragen. + + *Warum?*: Bietet Konsistenz im ganzen Team. + + ```javascript + { + "bitwise": true, + "camelcase": true, + "curly": true, + "eqeqeq": true, + "es3": false, + "forin": true, + "freeze": true, + "immed": true, + "indent": 4, + "latedef": "nofunc", + "newcap": true, + "noarg": true, + "noempty": true, + "nonbsp": true, + "nonew": true, + "plusplus": false, + "quotmark": "single", + "undef": true, + "unused": false, + "strict": false, + "maxparams": 10, + "maxdepth": 5, + "maxstatements": 40, + "maxcomplexity": 8, + "maxlen": 120, + + "asi": false, + "boss": false, + "debug": false, + "eqnull": true, + "esnext": false, + "evil": false, + "expr": false, + "funcscope": false, + "globalstrict": false, + "iterator": false, + "lastsemic": false, + "laxbreak": false, + "laxcomma": false, + "loopfunc": true, + "maxerr": false, + "moz": false, + "multistr": false, + "notypeof": false, + "proto": false, + "scripturl": false, + "shadow": false, + "sub": true, + "supernew": false, + "validthis": false, + "noyield": false, + + "browser": true, + "node": true, + + "globals": { + "angular": false, + "$": false + } + } + ``` + +**[Zurück zum Anfang](#table-of-contents)** + +## JSCS + +### Nutzung und Optionsdatei +###### [Style [Y235](#style-y235)] + + - Benutzen Sie JSCS um die Anwendung von Programmier-Richtlinien in Ihrem JavaScript-Code zu prüfen und versichern Sie sich, dass Sie die Prüffunktion für sich angepasst haben und die Optionsdatei in Ihrer Quellcodeverwaltung abgelegt haben. Schauen Sie sich die [JS Hint Dokumentation](http://www.jshint.com/docs/) an, um mehr über die Optionen zu erfahren. + + *Warum?*: Erstattet erste Meldung, bevor Sie den Code in die Quellcodeverwaltung übertragen. + + *Warum?*: Bietet Konsistenz im ganzen Team. + + ```javascript + { + "excludeFiles": ["node_modules/**", "bower_components/**"], + + "requireCurlyBraces": [ + "if", + "else", + "for", + "while", + "do", + "try", + "catch" + ], + "requireOperatorBeforeLineBreak": true, + "requireCamelCaseOrUpperCaseIdentifiers": true, + "maximumLineLength": { + "value": 100, + "allowComments": true, + "allowRegex": true + }, + "validateIndentation": 4, + "validateQuoteMarks": "'", + + "disallowMultipleLineStrings": true, + "disallowMixedSpacesAndTabs": true, + "disallowTrailingWhitespace": true, + "disallowSpaceAfterPrefixUnaryOperators": true, + "disallowMultipleVarDecl": null, + + "requireSpaceAfterKeywords": [ + "if", + "else", + "for", + "while", + "do", + "switch", + "return", + "try", + "catch" + ], + "requireSpaceBeforeBinaryOperators": [ + "=", "+=", "-=", "*=", "/=", "%=", "<<=", ">>=", ">>>=", + "&=", "|=", "^=", "+=", + + "+", "-", "*", "/", "%", "<<", ">>", ">>>", "&", + "|", "^", "&&", "||", "===", "==", ">=", + "<=", "<", ">", "!=", "!==" + ], + "requireSpaceAfterBinaryOperators": true, + "requireSpacesInConditionalExpression": true, + "requireSpaceBeforeBlockStatements": true, + "requireLineFeedAtFileEnd": true, + "disallowSpacesInsideObjectBrackets": "all", + "disallowSpacesInsideArrayBrackets": "all", + "disallowSpacesInsideParentheses": true, + + "validateJSDoc": { + "checkParamNames": true, + "requireParamTypes": true + }, + + "disallowMultipleLineBreaks": true, + + "disallowCommaBeforeLineBreak": null, + "disallowDanglingUnderscores": null, + "disallowEmptyBlocks": null, + "disallowMultipleLineStrings": null, + "disallowTrailingComma": null, + "requireCommaBeforeLineBreak": null, + "requireDotNotation": null, + "requireMultipleVarDecl": null, + "requireParenthesesAroundIIFE": true + } + ``` + +**[Zurück zum Anfang](#table-of-contents)** + +## Konstanten + +### Globale Drittanbieter-Konstanten +###### [Style [Y240](#style-y240)] + + - Erstellen Sie eine Angular-Konstante für die globalen Variablen aus Bibliotheken von Drittanbietern. + + *Warum?*: Bietet einen Weg, Bibliotheken von Drittanbietern in einem sicheren Umfeld anzubieten, die andererseits "Globals" wären. Dies verbessert die Testbarkeit, weil Sie so einfacher die Abhängigkeiten Ihres Codes erfahren (verindert lückenhafte Abstraktionen). Auch die Simulation dieser Abhängigkeiten wird zugelassen, wo sie Sinn macht. + + ```javascript + // constants.js + + /* global toastr:false, moment:false */ + (function() { + 'use strict'; + + angular + .module('app.core') + .constant('toastr', toastr) + .constant('moment', moment); + })(); + ``` + +###### [Style [Y241](#style-y241)] + + - Benutzen Sie Konstanten für Wete, die sich nicht ändern und nicht aus einem anderen Service kommen. Wenn Konstanten nur für ein bestimmtes Modul gebraucht werden, welches zudem wiederverwendbar sein soll, dann platzieren Sie die Konstanten in einer Datei (pro Modul) und benennen Sie die Datei nach dem Modul. Bis dahin halten Sie die Konstanten im Hauptmodul in einer `constants.js`-Datei. + + *Warum?*: Ein Wert, der sich ändert - wenn auch nur unregelmäßig - sollte von einem Service ermittelt werden, so dass er nicht im Quellcode geändert werden muss. Zum Beispiel könnte eine URL für einen Datenservice in einer Konstanten abgelegt werden. Besser wäre es aber, diesen Wert über einen WebService zu ermitteln. + + *Warum?*: Konstanten können in jede Angular-Komponente (auch in einen Provider) eingefügt werden. + + *Warum?*: Ist eine Anwendung in Module unterteilt, die in anderen Anwendungen genutzt werden können, so solte jedes alleinstehende Modul für sich selbst funktionieren, eingeschlossen seiner Konstanten. + + ```javascript + // Konstanten für die gesamte Anwendung + angular + .module('app.core') + .constant('moment', moment); + + // Konstanten, die nur vom Verkaufsmodul genutzt werden + angular + .module('app.sales') + .constant('events', { + ORDER_CREATED: 'event_order_created', + INVENTORY_DEPLETED: 'event_inventory_depleted' + }); + ``` + +**[Zurück zum Anfang](#table-of-contents)** + +## Dateitemplates und Snippets +Nutzen Sie Templates oder Snippets, um stimmigen Richtlinien und Mustern zu folgen. Hier sind Templates oder Snippets für einige Editoren und IDE'n zur Webentwicklung. + +### Sublime Text +###### [Style [Y250](#style-y250)] + + - Angular Snippets, die diesen Mustern und Richtlinien folgen. + + - Laden Sie die [Sublime Angular Snippets](assets/sublime-angular-snippets?raw=true) heruntern + - Platzieren Sie sie in Ihrem Package-Ordner + - Starten Sie Sublime neu + + - Schreiben Sie einen dieser Befehle in einer JavaScript-Datei, gefolgt von einem `TAB`: + + ```javascript + ngcontroller // erstellt einen Angular Controller + ngdirective // erstellt eine Angular Direktive + ngfactory // erstellt eine Angular Factory + ngmodule // erstellt ein Angular Modul + ngservice // erstellt einen Angular Service + ngfilter // erstellt einen Angular Filter + ``` + +### Visual Studio +###### [Style [Y251](#style-y251)] + + - Angular Dateitemplates, die diesen Mustern und Richtlinien folgen, finden Sie unter [SideWaffle](http://www.sidewaffle.com) + + - Laden Sie die [SideWaffle](http://www.sidewaffle.com) Visual Studio Erweiterung (vsix file) herunter + - Starten Sie die vsix-Datei + - Starten Sie Visual Studio neu + +### WebStorm +###### [Style [Y252](#style-y252)] + + - Angular Dateitemplates, die diesen Mustern und Richtlinien folgen. Sie können sie in Ihre WebStorm-Einstellungen importieren: + + - Laden Sie die [WebStorm Angular Dateitemplates und Snippets](assets/webstorm-angular-file-template.settings.jar?raw=true) herunter + - Öffnen Sie WebStorm and gehen Sie ins `File`-Menü + - Wählen Sie die `Import Settings` Menüoption + - Wählen Sie die Datei aus und klicken Sie `OK` + + - Schreiben Sie einen dieser Befehle in einer JavaScript-Datei, gefolgt von einem `TAB`: + + ```javascript + ng-c // erstellt einen Angular Controller + ng-f // erstellt eine Angular Factory + ng-m // erstellt ein Angular Modul + ``` + +### Atom +###### [Style [Y253](#style-y253)] + + - Angular Dateitemplates, die diesen Mustern und Richtlinien folgen + ``` + apm install angularjs-styleguide-snippets + ``` + oder + - Öffnen Sie Atom und öffnen Sie die Paketverwaltung (Packages -> Settings View -> Install Packages/Themes) + - Suchen Sie nach dem Paket 'angularjs-styleguide-snippets' + - Klicken Sie `Install`, um das Paket zu installieren + + - Schreiben Sie einen dieser Befehle in einer JavaScript-Datei, gefolgt von einem `TAB`: + + ```javascript + ngcontroller // erstellt einen Angular Controller + ngdirective // erstellt eine Angular Direktive + ngfactory // erstellt eine Angular Factory + ngmodule // erstellt ein Angular Modul + ngservice // erstellt einen Angular Service + ngfilter // erstellt einen Angular Filter + ``` + +### Brackets +###### [Style [Y254](#style-y254)] + + - Angular Dateitemplates, die diesen Mustern und Richtlinien folgen + - Laden Sie die [Brackets Angular snippets](assets/brackets-angular-snippets.yaml?raw=true) herunter + - Brackets Extension Manager ( File > Extension manager ) + - Installieren Sie die ['Brackets Snippets (by edc)'](https://github.com/chuyik/brackets-snippets) + - Klicken Sie die Glühbirne am rechten Rand vom "Gutter" in Brackets + - Klicken Sie `Settings` und dann `Import` + - Wählen Sie die Datei und danach `skip` oder `override` + - Klicken Sie `Start Import` + + - Schreiben Sie einen dieser Befehle in einer JavaScript-Datei, gefolgt von einem `TAB`: + + ```javascript + // Dies sind vollwertige Dateisnippets mit einer IIFE + ngcontroller // erstellt einen Angular Controller + ngdirective // erstellt eine Angular Direktive + ngfactory // erstellt eine Angular Factory + ngapp // erstellt einen Angular Modul-Setter + ngservice // erstellt einen Angular Service + ngfilter // erstellt einen Angular Filter + + // Dies sind Teilsnippets, die zum Verketten gedacht sind: + ngmodule // erstellt einen Angular module getter + ngstate // erstellt eine Angular UI Router State-Defintion + ngconfig // definiert eine Funktion für die Konfigurationsphase + ngrun // definiert eine Funktion für die Run-Phase + ngroute // definiert eine Angular ngRoute 'when'-Definition + ngtranslate // nutzt den $translate Service mit seinem Promise + ``` + +### vim +###### [Style [Y255](#style-y255)] + + - vim-Snippets die diesen Mustern und Richtlinien folgen. + + - Laden Sie die [vim Angular snippets](assets/vim-angular-snippets?raw=true) herunter + - Setzen Sie [neosnippet.vim](https://github.com/Shougo/neosnippet.vim) + - Kopieren Sie die Snippets ins Snippet-Verzeichnis + + ```javascript + ngcontroller // erstellt einen Angular Controller + ngdirective // erstellt eine Angular Direktive + ngfactory // erstellt eine Angular Factory + ngmodule // erstellt ein Angular Modul + ngservice // erstellt einen Angular Service + ngfilter // erstellt einen Angular Filter + ``` +**[Zurück zum Anfang](#table-of-contents)** + +## Yeoman Generator +###### [Style [Y260](#style-y260)] + +Sie können den [HotTowel Yeoman Generator](http://jpapa.me/yohottowel) nutzen, um eine Anwendung als Startpunkt zu erstellen, die diesen Mustern und Richtlinien folgt. + +1. Installieren Sie generator-hottowel + + ``` + npm install -g generator-hottowel + ``` + +2. Erstellen Sie ein neues Verzeichnis und wechseln sie dort hin + + ``` + mkdir myapp + cd myapp + ``` + +3. Starten die den Generator + + ``` + yo hottowel helloWorld + ``` + +**[Zurück zum Anfang](#table-of-contents)** + +## Routing +Das Routing auf der Client-Seite ist für die Erstellung eines Navigationsflusses zwischen den Views und den zusammengestellten Views, die aus mehreren kleineren Vorlagen und Direktiven bestehen. + +###### [Style [Y270](#style-y270)] + + - Benutzen Sie den [AngularUI Router](http://angular-ui.github.io/ui-router/) für das clientseitige Routing. + + *Warum?*: Der UI Router bietet alle Funktionen des Angular Routers und zusätzlich Weitere, wie geschachtelte Routen und Stati. + + *Warum?*: Die Syntax ähnelt der des Angular Routers und ist einfach auf den UI Router umzustellen. + + - Anmerkung: Sie können einen Provider, wie den unten angeführten `routerHelperProvider` nutzen, um die Stati während der Startphase der Anwendung dateiübergreifend zu konfigurieren. + + ```javascript + // customers.routes.js + angular + .module('app.customers') + .run(appRun); + + /* @ngInject */ + function appRun(routerHelper) { + routerHelper.configureStates(getStates()); + } + + function getStates() { + return [ + { + state: 'customer', + config: { + abstract: true, + template: '', + url: '/customer' + } + } + ]; + } + ``` + + ```javascript + // routerHelperProvider.js + angular + .module('blocks.router') + .provider('routerHelper', routerHelperProvider); + + routerHelperProvider.$inject = ['$locationProvider', '$stateProvider', '$urlRouterProvider']; + /* @ngInject */ + function routerHelperProvider($locationProvider, $stateProvider, $urlRouterProvider) { + /* jshint validthis:true */ + this.$get = RouterHelper; + + $locationProvider.html5Mode(true); + + RouterHelper.$inject = ['$state']; + /* @ngInject */ + function RouterHelper($state) { + var hasOtherwise = false; + + var service = { + configureStates: configureStates, + getStates: getStates + }; + + return service; + + /////////////// + + function configureStates(states, otherwisePath) { + states.forEach(function(state) { + $stateProvider.state(state.state, state.config); + }); + if (otherwisePath && !hasOtherwise) { + hasOtherwise = true; + $urlRouterProvider.otherwise(otherwisePath); + } + } + + function getStates() { return $state.get(); } + } + } + ``` + +###### [Style [Y271](#style-y271)] + + - Definieren sie die Routen für die Views in den Modulen, in denen sie enthalten sind. Jedes Modul sollte die Routen seiner Views enthalten. + + *Warum?*: Jedes Modul sollte für sich allein lauffähig sein. + + *Warum?*: Wird ein Modul zur Anwendung hinzugefügt oder aus ihr ausgeklinkt, enthält die Anwendung nur Routen, die zu vorhanden Views führen. + + *Warum?*: Dies erleichtert es, Teile eine Anwendung zu aktivieren oder zu deaktiveren, ohne dass man sich um verwaiste Routen Sorgen machen muss. + +**[Zurück zum Anfang](#table-of-contents)** + +## Automatisierung von Aufgaben +Nutzen Sie [Gulp](http://gulpjs.com) oder [Grunt](http://gruntjs.com), um Aufgaben zu automatisieren. Bei Gulp geht der Code vor Konfiguration, bei Grund Konfiguration vor Code. Ich persönlich bevorzuge Gulp, weil ich denke, es ist einfacher zu lesen und zu schreiben, aber beide sind erstklassig. + +> Erfahren Sie mehr über Gulp und Muster für die Automatisierung von Aufgabenin meinem [Gulp Pluralsight Kurs](http://jpapa.me/gulpps) + +###### [Style [Y400](#style-y400)] + + - Nutzen sie die Automatisierung von Aufgaben, um die Moduldefinitionsdateien `*.module.js` vor allen anderen JavaScript-Dateien in der Anwendung aufzulisten. + + *Warum?*: Angular muss die Moduldefinitionen registrieren, bevor die Module benutzt werden können. + + *Warum?*: Das Benennen der Module gemäß des Musters `*.module.js`, vereinfacht es, diese zu filtern und zuerst aufzulisten. + + ```javascript + var clientApp = './src/client/app/'; + + // Immer zuerst die Moduldateien + var files = [ + clientApp + '**/*.module.js', + clientApp + '**/*.js' + ]; + ``` + +**[Zurück zum Anfang](#table-of-contents)** + +## Filter + +###### [Style [Y420](#style-y420)] + + - Vermeiden Sie es, Filter dazu zu nutzen, alle Eigenschaften in einem komplexen Objektgraphen zu prüfen. Nutzen Sie Filter um Eigenschaften auszuwählen. + + *Warum?*: Filter können sehr leicht missbraucht werden und dann die Performance einer Anwendung negativ beeinflussen, wenn sie nicht überlegt eingesetzt werden. Zum Beispiel: Wenn ein Filter auf einen großen und tief geschachtelten Objektgraphen angewendet wird. + +**[Zurück zum Anfang](#table-of-contents)** + +## Angular Dokumentation +Für alles Andere und die, API-Referenz, schauen Sie bitte in der [Angular-Dokumentation](//docs.angularjs.org/api) nach. + +## Beiträge + +Öffnen Sie erst einen "Issue", um eventuelle Änderungen oder Erweiterungen zu diskutieren. Sollten Sie Fragen zu den Richtlinien haben, können Sie diese selbstverständlich als "Issue" im Repository hinterlassen. Wenn Sie einen Tippfehler finden, erstellen Sie ein Pull-Request. Die Idee ist es, den Inhalt aktuell zu halten und GitHubs Möglichkeiten zu nutzen, die Nachricht über "Issues" und PRs zu verbreiten, die über Google gefunden werden können. Warum? Weil es sein kann, dass nicht nur Sie, sondern auch andere die gleichen Fragen haben. Hier erfahren Sie mehr darüber, wie Sie beitragen können. + +*Wenn Sie zu diesem Repository beitragen, erklären Sie sich damit einverstanden, dass Ihr Beitrag unter die Lizenz dieses Repository fällt.* + +### Prozess + 1. Diskutieren Sie die Änderungen in einem GitHub-"Issue". + 2. Erstellen Sie in Pull-Request, beziehen Sie sich auf den "Issue" und erklären Sie die Änderung und warum sie Mehrwert bringt. + 3. Der Pull-Request wird geprüft und entweder aufgenommen oder abgelehnt. + +## Lizenz + +_tldr; Wenden Sie diese Richtlinien an. Beiträge sind willkommen._ + +### Copyright + +Copyright (c) 2014-2015 [John Papa](http://johnpapa.net) + +### (Die MIT-Lizenz) +Hiermit wird unentgeltlich jeder Person, die eine Kopie der Software und der zugehörigen Dokumentationen (die "Software") erhält, die Erlaubnis erteilt, sie uneingeschränkt zu benutzen, inklusive und ohne Ausnahme dem Recht, sie zu verwenden, kopieren, ändern, fusionieren, verlegen, verbreiten, unterlizenzieren und/oder zu verkaufen, und Personen, die diese Software erhalten, diese Rechte zu geben, unter den folgenden Bedingungen: + +Der obige Urheberrechtsvermerk und dieser Erlaubnisvermerk sind in allen Kopien oder Teilkopien der Software beizulegen. + +DIE SOFTWARE WIRD OHNE JEDE AUSDRÜCKLICHE ODER IMPLIZIERTE GARANTIE BEREITGESTELLT, EINSCHLIESSLICH DER GARANTIE ZUR BENUTZUNG FÜR DEN VORGESEHENEN ODER EINEM BESTIMMTEN ZWECK SOWIE JEGLICHER RECHTSVERLETZUNG, JEDOCH NICHT DARAUF BESCHRÄNKT. IN KEINEM FALL SIND DIE AUTOREN ODER COPYRIGHTINHABER FÜR JEGLICHEN SCHADEN ODER SONSTIGE ANSPRÜCHE HAFTBAR ZU MACHEN, OB INFOLGE DER ERFÜLLUNG EINES VERTRAGES, EINES DELIKTES ODER ANDERS IM ZUSAMMENHANG MIT DER SOFTWARE ODER SONSTIGER VERWENDUNG DER SOFTWARE ENTSTANDEN. + +**[Zurück zum Anfang](#table-of-contents)** From 40250124c25b4ca404285cfa35f87776d6869a7e Mon Sep 17 00:00:00 2001 From: Johnson Page Date: Mon, 4 May 2015 14:22:55 +1000 Subject: [PATCH 284/567] Fix minification typo --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index e58e2b88..a78edbdb 100644 --- a/README.md +++ b/README.md @@ -1674,7 +1674,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see } ``` - > Note: Starting from Angular 1.3 you can use the [`ngApp`](https://docs.angularjs.org/api/ng/directive/ngApp) directive's `ngStrictDi` parameter to detect any potentially missing magnification safe dependencies. When present the injector will be created in "strict-di" mode causing the application to fail to invoke functions which do not use explicit function annotation (these may not be minification safe). Debugging info will be logged to the console to help track down the offending code. I prefer to only use `ng-strict-di` for debugging purposes only. + > Note: Starting from Angular 1.3 you can use the [`ngApp`](https://docs.angularjs.org/api/ng/directive/ngApp) directive's `ngStrictDi` parameter to detect any potentially missing minification safe dependencies. When present the injector will be created in "strict-di" mode causing the application to fail to invoke functions which do not use explicit function annotation (these may not be minification safe). Debugging info will be logged to the console to help track down the offending code. I prefer to only use `ng-strict-di` for debugging purposes only. `` ### Use Gulp or Grunt for ng-annotate From fdf058e3ace5be5453c09c0712dd6cb3224b94c7 Mon Sep 17 00:00:00 2001 From: noritamago Date: Mon, 4 May 2015 15:51:30 +0900 Subject: [PATCH 285/567] follow latest master branch change in ja-JP --- i18n/ja-JP.md | 139 +++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 121 insertions(+), 18 deletions(-) diff --git a/i18n/ja-JP.md b/i18n/ja-JP.md index 3ad709cf..46c9e982 100644 --- a/i18n/ja-JP.md +++ b/i18n/ja-JP.md @@ -898,7 +898,7 @@ *なぜ ?*: データサービスを用いるコントローラをテストする際に、(モックまたは本物の)データの呼び出しを容易にテストできます。 - *なぜ ?*: データサービスの実装は、データリポジトリを取り扱う非常にスペシフィックなコードとなります。 このコードには、ヘッダ、データリポジトリの利用方法、もしくは$httpのような他のサービスを含むでしょう。そのようなロジックをデータサービスへ分割し、他のconsumers (おそらくコントローラ) から実装の詳細を隠すように一つの場所へカプセル化します。そうすることで、実装の変更も容易になります + *なぜ ?*: データサービスの実装は、データリポジトリを取り扱う非常にスペシフィックなコードとなります。 このコードには、ヘッダ、データリポジトリの利用方法、もしくは`$http`のような他のサービスを含むでしょう。そのようなロジックをデータサービスへ分割し、他のconsumers (おそらくコントローラ) から実装の詳細を隠すように一つの場所へカプセル化します。そうすることで、実装の変更も容易になります ```javascript /* recommended */ @@ -1010,7 +1010,7 @@ } ``` - **[Back to top](#table-of-contents)** +**[Back to top](#table-of-contents)** ## Directives ### Limit 1 Per File @@ -1022,8 +1022,7 @@ *なぜ ?*: ファイル毎に一つのディレクティブにすることで、メンテナンスが容易になります。 - Note: "**Best Practice**: Directives should clean up after themselves. You can use `element.on('$destroy', ...)` or `scope.$on('$destroy', ...)` to run a clean-up function when the directive is removed" ... from the Angular documentation - Note: "**Best Practice**: ディレクティブは自身でクリーンナップされるべきです。ディレクティブが削除されたときにクリーンナップの関数を実行するために、`element.on('$destroy', ...)` や `scope.$on('$destroy', ...)`" ... Angularのドキュメンテーションより + Note: "**Best Practice**: ディレクティブは自身でクリーンナップされるべきです。ディレクティブが削除されたときにクリーンナップの関数を実行するために、`element.on('$destroy', ...)` や `scope.$on('$destroy', ...)`"を用いて下さい ... Angularのドキュメンテーションより。 ```javascript @@ -1253,6 +1252,18 @@
min={{vm.min}}
``` + Note: コントローラをlink関数に注入して、ディレクティブの属性をコントローラのプロパティとしてアクセスすることも可能です。 + + ```javascript + // Alternative to above example + function linkFunc(scope, el, attr, vm) { + console.log('LINK: scope.min = %s *** should be undefined', scope.min); + console.log('LINK: scope.max = %s *** should be undefined', scope.max); + console.log('LINK: vm.min = %s', vm.min); + console.log('LINK: vm.max = %s', vm.max); + } + ``` +z ###### [Style [Y076](#style-y076)] - `controller as`シンタックスをディレクティブで用い、外側のscopeをディレクティブのコントローラのscopeにバインドしたいときは `bindToController = true` を使って下さい。 @@ -1303,7 +1314,6 @@ **[Back to top](#table-of-contents)** ## Resolving Promises for a Controller - ### Controller Activation Promises ###### [Style [Y080](#style-y080)] @@ -1408,8 +1418,8 @@ Avengers.$inject = ['moviesPrepService']; function Avengers(moviesPrepService) { - var vm = this; - vm.movies = moviesPrepService.movies; + var vm = this; + vm.movies = moviesPrepService.movies; } ``` @@ -1436,7 +1446,7 @@ }); } - function moviePrepService(movieService) { + function moviesPrepService(movieService) { return movieService.getMovies(); } @@ -1576,13 +1586,13 @@ controller: 'AvengersController', controllerAs: 'vm', resolve: { - moviesPrepService: moviePrepService + moviesPrepService: moviesPrepService } }); } - moviePrepService.$inject = ['movieService']; - function moviePrepService(movieService) { + moviesPrepService.$inject = ['movieService']; + function moviesPrepService(movieService) { return movieService.getMovies(); } ``` @@ -1967,10 +1977,12 @@ ### Factory Names ###### [Style [Y125](#style-y125)] - - 全てのファクトリに対して、機能に沿った一貫性の取れた名前を用いて下さい。サービスやファクトリ名にはキャメルケースを用いて下さい。 + - 全てのファクトリに対して、機能に沿った一貫性の取れた名前を用いて下さい。サービスやファクトリ名にはキャメルケースを用いて下さい。`$`から始まるファクトリやサービス名を避けて下さい。 *なぜ ?*: 参照するべきファクトリを素早く特定する一貫性の取れた方法を与えます。 + *なぜ ?*: ビルトインされている`$`から始まるファクトリやサービス名との衝突を避けられます。 + ```javascript /** * recommended @@ -2177,6 +2189,7 @@ app.module.js app.config.js app.routes.js + directives.js controllers/ attendees.js session-detail.js @@ -2317,12 +2330,12 @@ .module('app') .run(runBlock); - runBlock.$inject = ['authenticator', 'translator']; + runBlock.$inject = ['authenticator', 'translator']; - function runBlock(authenticator, translator) { - authenticator.initialize(); - translator.initialize(); - } + function runBlock(authenticator, translator) { + authenticator.initialize(); + translator.initialize(); + } ``` **[Back to top](#table-of-contents)** @@ -2840,13 +2853,15 @@ ngdirective // creates an Angular directive ngfactory // creates an Angular factory ngmodule // creates an Angular module + ngservice // creates an Angular service + ngfilter // creates an Angular filter ``` ### Brackets ###### [Style [Y254](#style-y254)] - 本スタイルとガイドラインに沿ったAngularのスニペット - + - [Brackets Angular snippets](assets/brackets-angular-snippets.yaml?raw=true)をダウンロード - Brackets Extension マネージャー ( File > Extension manager ) - ['Brackets Snippets (by edc)'](https://github.com/chuyik/brackets-snippets)をインストール - bracketsの右側にある電球をクリック @@ -2870,8 +2885,27 @@ ngstate // creates an Angular UI Router state defintion ngconfig // defines a configuration phase function ngrun // defines a run phase function + ngroute // defines an Angular ngRoute 'when' definition + ngtranslate // uses $translate service with its promise ``` +### vim +###### [Style [Y255](#style-y255)] + + - 本スタイルやガイドラインに沿ったvimのスニペット + + - [vim Angular snippets](assets/vim-angular-snippets?raw=true)をダウンロード + - [neosnippet.vim](https://github.com/Shougo/neosnippet.vim)をセット + - スニペットをsnippetディレクトリにコピー + + ```javascript + ngcontroller // creates an Angular controller + ngdirective // creates an Angular directive + ngfactory // creates an Angular factory + ngmodule // creates an Angular module + ngservice // creates an Angular service + ngfilter // creates an Angular filter + ``` **[Back to top](#table-of-contents)** ## Yeoman Generator @@ -2910,6 +2944,75 @@ *なぜ ?*: UI RouterはAngularのルーターが持つ全ての機能プラス、ネスト化されたルーティングやステートなどいくつかの追加機能があります。 *なぜ ?*: シンタックスはAngularのルータと非常に似ており、UI Routerへ容易に移行できます。 + - Note: 以下に示されるように`routerHelperProvider`のようなプロバイダーを用いることができます。それはrunフェーズでファイルを跨ってstateを設定する際に役立ちます。 + + ```javascript + // customers.routes.js + angular + .module('app.customers') + .run(appRun); + + /* @ngInject */ + function appRun(routerHelper) { + routerHelper.configureStates(getStates()); + } + + function getStates() { + return [ + { + state: 'customer', + config: { + abstract: true, + template: '', + url: '/customer' + } + } + ]; + } + ``` + + ```javascript + // routerHelperProvider.js + angular + .module('blocks.router') + .provider('routerHelper', routerHelperProvider); + + routerHelperProvider.$inject = ['$locationProvider', '$stateProvider', '$urlRouterProvider']; + /* @ngInject */ + function routerHelperProvider($locationProvider, $stateProvider, $urlRouterProvider) { + /* jshint validthis:true */ + this.$get = RouterHelper; + + $locationProvider.html5Mode(true); + + RouterHelper.$inject = ['$state']; + /* @ngInject */ + function RouterHelper($state) { + var hasOtherwise = false; + + var service = { + configureStates: configureStates, + getStates: getStates + }; + + return service; + + /////////////// + + function configureStates(states, otherwisePath) { + states.forEach(function(state) { + $stateProvider.state(state.state, state.config); + }); + if (otherwisePath && !hasOtherwise) { + hasOtherwise = true; + $urlRouterProvider.otherwise(otherwisePath); + } + } + + function getStates() { return $state.get(); } + } + } + ``` ###### [Style [Y271](#style-y271)] From 79df75d8e2c2a463c2242f3e6c2762aa09e7019c Mon Sep 17 00:00:00 2001 From: jody tate Date: Mon, 4 May 2015 08:53:36 -0700 Subject: [PATCH 286/567] fix typo and clarify sentence The sentence had a redundant "use" and it wasn't quite clear if "structure" or "structuring" was the intended wording. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index e58e2b88..58dc2fb1 100644 --- a/README.md +++ b/README.md @@ -2174,7 +2174,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see ![Sample App Structure](https://raw.githubusercontent.com/johnpapa/angular-styleguide/master/assets/modularity-2.png) - Note: Do not use structuring using folders-by-type. This requires moving to multiple folders when working on a feature and gets unwieldy quickly as the app grows to 5, 10 or 25+ views and controllers (and other features), which makes it more difficult than folder-by-feature to locate files. + Note: Do not structure your app using folders-by-type. This requires moving to multiple folders when working on a feature and gets unwieldy quickly as the app grows to 5, 10 or 25+ views and controllers (and other features), which makes it more difficult than folder-by-feature to locate files. ```javascript /* From af7851d877375f2570e5234e7fd4d10553af8e81 Mon Sep 17 00:00:00 2001 From: jody tate Date: Mon, 4 May 2015 08:59:31 -0700 Subject: [PATCH 287/567] use hyphenated "end-to-end" "end-to-end" is more common, see https://docs.angularjs.org/guide/e2e-testing and https://angular.github.io/protractor/ --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index e58e2b88..6d1b0f12 100644 --- a/README.md +++ b/README.md @@ -618,7 +618,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see - Define a controller for a view, and try not to reuse the controller for other views. Instead, move reusable logic to factories and keep the controller simple and focused on its view. - *Why?*: Reusing controllers with several views is brittle and good end to end (e2e) test coverage is required to ensure stability across large applications. + *Why?*: Reusing controllers with several views is brittle and good end-to-end (e2e) test coverage is required to ensure stability across large applications. ### Assigning Controllers ###### [Style [Y038](#style-y038)] From 4da7111ee9e2518ea072caaba782c8d4aea619bb Mon Sep 17 00:00:00 2001 From: Sander Boom Date: Tue, 12 May 2015 14:30:26 +0200 Subject: [PATCH 288/567] Removed redundant disallowMultipleLineStrings declaration --- README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/README.md b/README.md index d7e3c045..3f8605c9 100644 --- a/README.md +++ b/README.md @@ -2722,7 +2722,6 @@ Unit testing helps maintain clean code, as such I included some of my recommenda "disallowCommaBeforeLineBreak": null, "disallowDanglingUnderscores": null, "disallowEmptyBlocks": null, - "disallowMultipleLineStrings": null, "disallowTrailingComma": null, "requireCommaBeforeLineBreak": null, "requireDotNotation": null, From 94523fef5a28737e5c13986bf1772f8782298e64 Mon Sep 17 00:00:00 2001 From: MofeLee Date: Thu, 14 May 2015 17:21:38 +0800 Subject: [PATCH 289/567] Update README.md fix name error --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 3f8605c9..351d6a23 100644 --- a/README.md +++ b/README.md @@ -2474,8 +2474,8 @@ Unit testing helps maintain clean code, as such I included some of my recommenda ``` /src/client/app/customers/customer-detail.controller.js /customer-detail.controller.spec.js + /customers.controller.js /customers.controller.spec.js - /customers.controller-detail.spec.js /customers.module.js /customers.route.js /customers.route.spec.js From bcfa2076342c07f2034129f686c955182b3f9a88 Mon Sep 17 00:00:00 2001 From: Ewerton Date: Fri, 15 May 2015 10:54:58 -0300 Subject: [PATCH 290/567] Update PT-BR.md Translate Feature File Names --- i18n/PT-BR.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/i18n/PT-BR.md b/i18n/PT-BR.md index fbb661d6..4b8e0ec1 100644 --- a/i18n/PT-BR.md +++ b/i18n/PT-BR.md @@ -1687,11 +1687,11 @@ ou *Coletores de exceção* ### Feature File Names - - Use consistent names for all components following a pattern that describes the component's feature then (optionally) its type. My recommended pattern is `feature.type.js`. + - Use nomes consistentes para todos os componentes seguindo um padrão que descreve a funcionalidade do componente e, em seguida, (opcionalmente) o seu tipo. Meu padrão recomendado é `feature.type.js`. - *Why?*: Provides a consistent way to quickly identify components. + *Por que?*: Fornece uma maneira consistente para identificar components mais rapidamente. - *Why?*: Provides pattern matching for any automated tasks. + *Por que?*: Fornece um padrão apropriado pra qualquer tarefa automatizada. ```javascript /** @@ -1740,7 +1740,7 @@ ou *Coletores de exceção* avenger-profile.directive.spec.js ``` - Note: Another common convention is naming controller files without the word `controller` in the file name such as `avengers.js` instead of `avengers.controller.js`. All other conventions still hold using a suffix of the type. Controllers are the most common type of component so this just saves typing and is still easily identifiable. I recommend you choose 1 convention and be consistent for your team. + Nota: Outra convenção comum é nomear arquivos dos controladores sem a palavra `controller` no nome do arquivo como` avengers.js` em vez de `avengers.controller.js`. Todas as outras convenções ainda detêm usando um sufixo do tipo. Controladores são o tipo mais comum de componente para isso só economiza digitação e ainda é facilmente identificável. Eu recomendo que você escolha uma convenção que seja mais coerente para sua equipe. ```javascript /** From 61bb464105457e1a7d293f3ab5f0cd359d01cad8 Mon Sep 17 00:00:00 2001 From: Ewerton Date: Sun, 17 May 2015 11:30:32 -0300 Subject: [PATCH 291/567] #404 Translate Feature File Names to pt-br --- i18n/PT-BR.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/i18n/PT-BR.md b/i18n/PT-BR.md index 4b8e0ec1..5cd3e353 100644 --- a/i18n/PT-BR.md +++ b/i18n/PT-BR.md @@ -1689,7 +1689,7 @@ ou *Coletores de exceção* - Use nomes consistentes para todos os componentes seguindo um padrão que descreve a funcionalidade do componente e, em seguida, (opcionalmente) o seu tipo. Meu padrão recomendado é `feature.type.js`. - *Por que?*: Fornece uma maneira consistente para identificar components mais rapidamente. + *Por que?*: Fornece uma maneira consistente para identificar componentes mais rapidamente. *Por que?*: Fornece um padrão apropriado pra qualquer tarefa automatizada. @@ -1740,7 +1740,7 @@ ou *Coletores de exceção* avenger-profile.directive.spec.js ``` - Nota: Outra convenção comum é nomear arquivos dos controladores sem a palavra `controller` no nome do arquivo como` avengers.js` em vez de `avengers.controller.js`. Todas as outras convenções ainda detêm usando um sufixo do tipo. Controladores são o tipo mais comum de componente para isso só economiza digitação e ainda é facilmente identificável. Eu recomendo que você escolha uma convenção que seja mais coerente para sua equipe. + Nota: Outra convenção comum é nomear arquivos dos controllers sem a palavra `controller` no nome do arquivo como` avengers.js` em vez de `avengers.controller.js`. Todas as outras convenções ainda mantem o uso de um sufixo do tipo. Controllers são o tipo mais comum de componente, portanto isso só economiza digitação e ainda é facilmente identificável. Eu recomendo que você escolha uma convenção que seja mais coerente para sua equipe. ```javascript /** From eb5df0b55bb0dae9dd9535d7f31298f71b306c01 Mon Sep 17 00:00:00 2001 From: angelochiello Date: Mon, 18 May 2015 09:12:17 +0200 Subject: [PATCH 292/567] [it-IT] Complete Review (till Services) This is a complete review. Reviewed till Services (excluded). --- i18n/it-IT.md | 106 +++++++++++++++++++++++++------------------------- 1 file changed, 53 insertions(+), 53 deletions(-) diff --git a/i18n/it-IT.md b/i18n/it-IT.md index 6cb815eb..e58b99e9 100644 --- a/i18n/it-IT.md +++ b/i18n/it-IT.md @@ -8,22 +8,22 @@ Se stai cercando una guida stilistica dogmatica per le sintassi, convenzioni e struttura di applicazioni AngularJS, allora questo fa per te. Gli stili sono basati sulla mia esperienza di sviluppo con [AngularJS](//angularjs.org), presentazioni, [corsi di formazioni di Pluralsight](http://pluralsight.com/training/Authors/Details/john-papa) e del lavoro in team. -L'obbiettivo di questa guida stilistica è di fare da vademecum alla costruzione di applicazioni con AngularJS mostrando le convenzioni che uso e, più importante, perché le uso. +L'obbiettivo di questa guida stilistica è di fare da vademecum alla costruzione di applicazioni con Angular mostrando le convenzioni che uso e, più importante, perché le uso. ->Se ti piace questa guida, dai un'occhiata al mio corso [AngularJS Patterns: Clean Code](http://jpapa.me/ngclean) (in inglese) su Pluralsight. +>Se ti piace questa guida, dai un'occhiata al mio corso [AngularJS Patterns: Clean Code](http://jpapa.me/ngclean) (in inglese) su Pluralsight come complemento a questa guida. [![AngularJs Patterns: Clean Code](https://raw.githubusercontent.com/johnpapa/angularjs-styleguide/master/assets/ng-clean-code-banner.png)](http://jpapa.me/ngclean) ## Eccezionalità della comunità e riconoscimenti -Mai lavorare nel vuoto. Ritengo che la comunità intorno ad AngularJS sia un gruppo incredibile con la passione di condividere le esperienze. Perciò, Todd Motto, un amico ed un esperto di AngularJS, ed io abbiamo collaborato su molti stili e convenzioni. Su molto siamo d'accordo, su altro meno. Ti invito a controllare le [linee guida di Todd](https://github.com/toddmotto/angularjs-styleguide) per avere cognizione del suo approccio e di come paragonarle. +Mai lavorare nel vuoto. Ritengo che la comunità intorno ad Angular sia un gruppo incredibile con la passione di condividere le esperienze. Perciò, Todd Motto, un amico ed un esperto di Angular, ed io abbiamo collaborato su molti stili e convenzioni. Su molto siamo d'accordo, su altro meno. Ti invito a controllare le [linee guida di Todd](https://github.com/toddmotto/angularjs-styleguide) per avere cognizione del suo approccio e di come paragonarle. -Molti dei mie stili sono frutto di parecchie sessioni di pair programming che [Ward Bell](http://twitter.com/wardbell) ed io abbiamo avuto. Seppur non sempre in sintonia, il mio amico Ward ha di certo una influenza sull'evoluzione finale di questa guida. +Molti dei mie stili sono frutto di parecchie sessioni di pair programming che [Ward Bell](http://twitter.com/wardbell) ed io abbiamo avuto. Il mio amico Ward ha di certo una influenza sull'evoluzione finale di questa guida. ## Guarda gli stili in una App di Esempio -Nonostante questa guida spieghi i *cosa*, *come* e *perché*, trovo che sia di aiuto vederle in pratica. Questa guida è accompagnata da una applicazione di esempio che segue questi stili e schemi. Troverai l'[applicazione di esempio (chiamata modular) qui](https://github.com/johnpapa/ng-demos) nella cartella `modular`. Prendila, clonala o fanne un fork liberamente. [Le istruzioni su come eseguirla sono nel proprio readme](https://github.com/johnpapa/ng-demos/tree/master/modular). +Nonostante questa guida spieghi i *cosa*, *come* e *perché*, trovo che sia di aiuto vederle in pratica. Questa guida è accompagnata da una applicazione di esempio che segue questi stili e schemi. Puoi trovare l'[applicazione di esempio (chiamata modular) qui](https://github.com/johnpapa/ng-demos) nella cartella `modular`. Prendila, clonala o fanne un fork liberamente. [Le istruzioni su come eseguirla sono nel proprio readme](https://github.com/johnpapa/ng-demos/tree/master/modular). ##Traduzioni -[Traduzioni di questa guida stilistica ad AngularJS](https://github.com/johnpapa/angularjs-styleguide/tree/master/i18n) sono gestite dalla comunità e possono essere trovate qui. +[Traduzioni di questa guida stilistica ad Angular](https://github.com/johnpapa/angularjs-styleguide/tree/master/i18n) sono gestite dalla comunità e possono essere trovate qui. ## Tavola dei contenuti @@ -56,7 +56,7 @@ Nonostante questa guida spieghi i *cosa*, *come* e *perché*, trovo che sia di a 1. [Routing](#routing) 1. [Automazione dei processi](#automazione-dei-processi) 1. [Filtri](#filtri) - 1. [Documentazione di AngularJS](#documentazione-di-angularjs) + 1. [Documentazione di Angular](#documentazione-di-angularjs) 1. [Contribuire](#contribuire) 1. [Licenza](#licenza) @@ -72,16 +72,16 @@ Nonostante questa guida spieghi i *cosa*, *come* e *perché*, trovo che sia di a ```javascript /* evitare */ angular - .module('app', ['ngRoute']) - .controller('SomeController', SomeController) - .factory('someFactory', someFactory); + .module('app', ['ngRoute']) + .controller('SomeController', SomeController) + .factory('someFactory', someFactory); function SomeController() { } function someFactory() { } ``` - Gli stessi componenti sono ora separati nei loro file. + Gli stessi componenti sono ora separati nei propri file. ```javascript /* consigliato */ @@ -116,12 +116,12 @@ Nonostante questa guida spieghi i *cosa*, *come* e *perché*, trovo che sia di a **[Torna all'inizio](#tavola-dei-contenuti)** ## IIFE -### JavaScript Closures +### Closures di JavaScript ###### [Stile [Y010](#stile-y010)] - - Racchiudi i componenti di AngularJS in una Immediately Invoked Function Expression (IIFE) (Espressione di funzione immediatamente chiamata). + - Racchiudi i componenti di Angular in una Immediately Invoked Function Expression (IIFE) (Espressione di funzione immediatamente chiamata). - *Perché?*: Una IIFFE rimuove le variabili dallo scope globale. Questo aiuta a prevenire che variabili e funzioni vivano più del previsto nello scope globale, che inoltre aiuta ad evitare la collisione di variabili. + *Perché?*: Una IIFE rimuove le variabili dallo scope globale. Questo aiuta a prevenire che variabili e dichiarazioni di funzione vivano più del previsto nello scope globale, inoltre aiuta ad evitare la collisione di variabili. *Perché?*: Quando il tuo codice è minificato e raggruppato in un file singolo per il rilascio ad un server di produzione, potresti avere collisioni di variabili e parecchie variabili globali. Una IIFE ti protegge in entrambi i casi fornendo uno scope variabile per ogni file. ```javascript @@ -176,7 +176,7 @@ Nonostante questa guida spieghi i *cosa*, *come* e *perché*, trovo che sia di a - Nota: Per essere più coincisi, il resto degli esempi in questa guida potrebbe omettere l'uso della sintassi IIFE. - - Nota: Le IIFE evitano che il codice di test possa raggiungere membri privati come regular expression o funzioni di supporto le quali sono spesso oggetto dei propri unit test. In ogni caso, queste possono essere testate per mezzo di membri accessibili o attraverso l'esposizione di propri componenti. Per esempio ponendo funzioni di supporto, regular expression o costanti nelle proprie factory o costanti. + - Nota: Le IIFE evitano che il codice di test possa raggiungere membri privati come regular expression o funzioni di supporto le quali sono spesso oggetto di propri unit test. In ogni caso, queste possono essere testate per mezzo di membri accessibili o attraverso l'esposizione di propri componenti. Per esempio ponendo funzioni di supporto, regular expression o costanti nelle proprie factory o costanti. **[Torna all'inizio](#tavola-dei-contenuti)** @@ -206,7 +206,7 @@ Nonostante questa guida spieghi i *cosa*, *come* e *perché*, trovo che sia di a ]); ``` - Invece usa la più semplice sintassi setter. +Invece usa la più semplice sintassi setter. ```javascript /* consigliato */ @@ -224,7 +224,7 @@ Nonostante questa guida spieghi i *cosa*, *come* e *perché*, trovo che sia di a - Usando un modulo, evita l'uso di una variabile e piuttosto usa la concatenazione con la sintassi getter. - *Perché?* : Ciò produce un codice maggiormente leggibile ed evita la collisione di variabili o buchi. + *Perché?*: Ciò produce un codice maggiormente leggibile ed evita la collisione di variabili o buchi. ```javascript /* evitare */ @@ -248,17 +248,17 @@ Nonostante questa guida spieghi i *cosa*, *come* e *perché*, trovo che sia di a - Setta solo una volta e prendi (get) per tutte le altre istanze. - *Perché?*: Un modulo dovrebbe essere creato solamente una volta, quindi recuperato da lì in avanti. - - - Usa `angular.module('app', []);` per settare un modulo. - - Usa `angular.module('app');` per prendere (get) un modulo. + *Perché?*: Un modulo dovrebbe essere creato solamente una volta, quindi recuperato da lì in avanti. + + - Usa `angular.module('app', []);` per settare un modulo. + - Usa `angular.module('app');` per prendere (get) un modulo. ### Funzioni con un nome vs funzioni anonime ###### [Stile [Y024](#stile-y024)] - Usa funzioni che hanno un nome piuttosto che passare una funzione anonima come in una callback. - *Perché?*: Ciò produce codice maggiormente leggibile, è più facile farne il debug, e riduce la quantità di codice posto dentro una callback. + *Perché?*: Ciò produce codice maggiormente leggibile, è più facile farne il debug, e riduce la quantità di codice posto dentro una callback. ```javascript /* evitare */ @@ -297,11 +297,11 @@ Nonostante questa guida spieghi i *cosa*, *come* e *perché*, trovo che sia di a - Usa la sintassi [`controllerAs`](http://www.johnpapa.net/do-you-like-your-angular-controllers-with-or-without-sugar/) al posto della sintassi `classico controller con $scope`. - *Perché?*: I controller sono costruiti, fatti nuovi e forniti con un nuova istanza singola, inoltre la sintassi `controllerAs` è più somigliante ad un costruttore JavaScript che la `sintassi classica con $scope`. + *Perché?*: I controller sono costruiti, creati con "new" e forniti con un nuova istanza singola, inoltre la sintassi `controllerAs` è più somigliante ad un costruttore JavaScript rispetto alla `sintassi classica con $scope`. - *Perché?*: Promuove l'uso del binding ad un oggetto che "usa il punto" nella View (p.e. `customer.name` invece di `name`), il quale è più contestuale, facile da leggere ed evita qualunque questione di riferimenti che potrebbe accadere senza "uso del punto". + *Perché?*: Promuove l'uso del binding ad un oggetto che "usa il punto" nella View (p.e. `customer.name` invece di `name`), il quale è più contestuale, più facile da leggere ed evita qualunque questione di riferimenti che potrebbe accadere senza "uso del punto". - *Perché?*: Aiuta ad evitare l'uso di chiamate a `$parent` nelle View che hanno controller nidificati. + *Perché?*: Aiuta ad evitare l'uso di chiamate a `$parent` nelle View che hanno controller nidificati. ```html @@ -368,14 +368,14 @@ Nonostante questa guida spieghi i *cosa*, *come* e *perché*, trovo che sia di a } ``` - Nota: Puoi evitare ogni warning di [jshint](http://www.jshint.com/) ponendo il commento sotto riportato al di sopra della linea di codice. Comunque ciò non è richiesto quando la funzione è nominata usando le Maiuscole, la convenzione è intesa come la funzione costruttore che è ciò che un controller è in Angular. + Nota: Puoi evitare ogni warning di [jshint](http://www.jshint.com/) ponendo il commento sotto riportato al di sopra della linea di codice. Comunque ciò non è richiesto quando la funzione è nominata ConUsoMaiuscole, dal momento che questa convenzione è intesa come funzione costruttore ovvero ciò che un controller è in Angular. ```javascript /* jshint validthis: true */ var vm = this; ``` - Nota: Quando di creano watch in un controller usando `controller as`, puoi fare il watch del membro `vm.*` usando la seguente sintassi. (Crea watch con cautela poiché aggiungono carico al ciclo di digest.) + Nota: Quando di creano watch in un controller usando `controller as`, puoi fare il watch del membro `vm.*` usando la seguente sintassi. (Crea watch con cautela poiché aggiungono più carico al ciclo di digest.) ```html @@ -393,14 +393,14 @@ Nonostante questa guida spieghi i *cosa*, *come* e *perché*, trovo che sia di a } ``` -### Membri che possono fare il bind in cima +### Membri che possono fare il bind posti in alto ###### [Stile [Y033](#stile-y033)] - - Poni i membri che possono fare il bind in cima al controller, in ordine alfabetico, piuttosto che dispersi in tutto il codice del controller. + - Poni i membri che possono fare il bind in alto nll controller, in ordine alfabetico, piuttosto che dispersi in tutto il codice del controller. - *Perché?*: Porre i membri che posso fare il bind in cima rende semplice la lettura e aiuta l'istantanea identificazione di quali membri del controller possono essere collegati ed usati in una View. + *Perché?*: Porre i membri che posso fare il bind in alto rende semplice la lettura e aiuta l'istantanea identificazione di quali membri del controller possono essere collegati ed usati in una View. - *Perché?*: Settare funzioni anonime nella medesima linea è semplice, tuttavia quando queste funzioni sono più lunghe di 1 linea di codice possono ridurre la leggibilità. Definire le funzione al di sotto i membri che possono fare il bind (funzioni che saranno chiamate) spostano l'implementazione in basso, tengono i membri che possono fare il bind in cima e rendono il codice più facile da leggere. + *Perché?*: Settare funzioni anonime nella medesima linea è semplice, tuttavia quando queste funzioni sono più lunghe di 1 linea di codice possono ridurre la leggibilità. Definire le funzione al di sotto i membri che possono fare il bind (funzioni che saranno chiamate) spostano i dettagli di implementazione in basso, tengono i membri che possono fare il bind in alto e rendono il codice più facile da leggere. ```javascript /* evitare */ @@ -448,7 +448,7 @@ Nonostante questa guida spieghi i *cosa*, *come* e *perché*, trovo che sia di a ![Controller che usa "Above the Fold"](https://raw.githubusercontent.com/johnpapa/angularjs-styleguide/master/assets/above-the-fold-1.png) - Nota: Se la funzione è di 1 linea considera di poterla lasciare in cima fino a che la leggibilità non ne è compromessa. + Nota: Se la funzione è di 1 linea considera di poterla lasciare in alto fino a che la leggibilità non ne è compromessa. ```javascript /* evitare */ @@ -458,11 +458,11 @@ Nonostante questa guida spieghi i *cosa*, *come* e *perché*, trovo che sia di a vm.gotoSession = gotoSession; vm.refresh = function() { /** - * lines - * of - * code - * affects - * readability + * linee + * di + * codice + * che peggiorano + * leggibilità */ }; vm.search = search; @@ -476,7 +476,7 @@ Nonostante questa guida spieghi i *cosa*, *come* e *perché*, trovo che sia di a var vm = this; vm.gotoSession = gotoSession; - vm.refresh = dataservice.refresh; // 1 liner is OK + vm.refresh = dataservice.refresh; // codice di 1 liena è OK vm.search = search; vm.sessions = []; vm.title = 'Sessions'; @@ -485,15 +485,15 @@ Nonostante questa guida spieghi i *cosa*, *come* e *perché*, trovo che sia di a ### Dichiarazioni di funzione per nascondere i dettagli di implementazione ###### [Stile [Y034](#stile-y034)] - - Usa le dichiarazioni di funzione per nascondere i dettagli di implementazione. Tieni i membri che possono fare il binding in cima. Quando necessiti di fare binding a una funzione nel controller, puntalo ad una dichiarazione di funzione che compaia dopo nel file. Questo è direttamente collegabile con la sezione Membri che possono fare il binding in cima. Per ulteriori dettagli guarda [questo post](http://www.johnpapa.net/angular-function-declarations-function-expressions-and-readable-code) (in inglese). + - Usa le dichiarazioni di funzione per nascondere i dettagli di implementazione. Tieni i membri che possono fare il binding in alto. Quando necessiti di fare binding a una funzione nel controller, puntalo ad una dichiarazione di funzione che compaia dopo nel file. Questo è direttamente collegabile con la sezione Membri che possono fare il bind posti in alto. Per ulteriori dettagli guarda [questo post](http://www.johnpapa.net/angular-function-declarations-function-expressions-and-readable-code) (in inglese). - *Perché?*: Porre i membri che possono fare il binding in cima rende semplice la lettura ed aiuta l'immediata identificazione dei membri del controller che possono fare il binding ed usati nella View. (Come sopra.) + *Perché?*: Porre i membri che possono fare il binding in alto rende semplice la lettura ed aiuta l'immediata identificazione dei membri del controller che possono fare il binding ed usati nella View. (Come sopra.) - *Perché?*: Porre i dettagli di implementazione di una funzione in seguito nel file sposta la complessità fuori dalla vista così che puoi vedere le cose importanti in cima. + *Perché?*: Porre i dettagli di implementazione di una funzione in seguito nel file sposta la complessità fuori dalla vista così che puoi vedere le cose importanti in alto. *Perché?*: Dichiarazioni di funzioni che sono chiamate così che non c'è rischio dell'uso di una funzione prima che sia definita (come sarebbe in caso di espressioni di funzione). - *Perché?*: Non ti devi preoccupare di dichiarazioni di funzione che sposta `var a` prima di `var b` che romperà il codice perché `a` dipende da `b`. + *Perché?*: Non ti devi preoccupare di dichiarazioni di funzione che sposta `var a` prima di `var b` romperà il codice perché `a` dipende da `b`. *Perché?*: Con le espressioni di funzione l'ordine è critico. @@ -526,13 +526,13 @@ Nonostante questa guida spieghi i *cosa*, *come* e *perché*, trovo che sia di a } ``` - Nota come le cose importanti, nell'esempio precedente, sono disseminate. Nell'esempio sotto, nota che le cose importanti sono in cima. Per esempio, i membri collegati al controller come `vm.avengers` e `vm.title`. I dettagli di implementazione sono in fondo. Questo è certamente più facile da leggere. + Nota come le cose importanti, nell'esempio precedente, sono disseminate. Nell'esempio sotto, nota che le cose importanti sono in alto. Per esempio, i membri collegati al controller come `vm.avengers` e `vm.title`. I dettagli di implementazione sono in fondo. Questo è certamente più facile da leggere. ```javascript /* * consigliato * Usare dichiarazione di funzione - * e mebri che fanno in binding in cima. + * e membri che fanno in binding in alto. */ function Avengers(dataservice, logger) { var vm = this; @@ -557,16 +557,16 @@ Nonostante questa guida spieghi i *cosa*, *come* e *perché*, trovo che sia di a } ``` -### Rimandare la logica del Controller +### Rimandare la logica del Controller ad un Service ###### [Stile [Y035](#stile-y035)] - Rimandare la logica in un controller delegandola ai service e factory. *Perché?*: La logica può essere riutilizzata da più controller quando posta in un service ed esposta tramite una funzione. - *Perché?*: La logica posta in un service può essere più facilmente isolata in una unit test, mentre la call della logica nel controller può essere più facile di farne un mock. + *Perché?*: La logica posta in un service può essere più facilmente isolata in una unit test inoltre la chiamata della logica nel controller può essere oggetto di un mock con più facilità. - *Perché?*: Rimuove dipendenze e nasconde dettagli di implementazione dal controller. + *Perché?*: Rimuove dipendenze e nasconde i dettagli di implementazione dal controller. ```javascript @@ -586,8 +586,8 @@ Nonostante questa guida spieghi i *cosa*, *come* e *perché*, trovo che sia di a // Usare JSONP per questo browser se CORS non è supportato return $http.get(settings) .then(function(data) { - // Unpack JSON data in the response object - // to find maxRemainingAmount + // Spacchetta i dati JSON nell'ogetto di risposta + // per trovare maxRemainingAmount vm.isCreditOk = vm.total <= maxRemainingAmount }) .catch(function(error) { @@ -619,7 +619,7 @@ Nonostante questa guida spieghi i *cosa*, *come* e *perché*, trovo che sia di a ### Tenere i controller "a fuoco" ###### [Stile [Y037](#stile-y037)] - - Definisci un controller per vista e prova a non utilizzare il controller per altre view. Piuttosto, sposta la logica riutilizzabile alle factory e mantieni il controller semplice ed a fuoco sulla propria view. + - Definisci un controller per vista e prova a non riutilizzare il controller per altre view. Piuttosto, sposta la logica riutilizzabile alle factory e mantieni il controller semplice ed a fuoco sulla propria view. *Perché?*: Riutilizzare i controller con diverse view è precario e sono necessari dei buoni test end to end (e2e) per assicurarne la stabilità in applicazioni su larga scala. @@ -627,13 +627,13 @@ Nonostante questa guida spieghi i *cosa*, *come* e *perché*, trovo che sia di a ###### [Stile [Y038](#stile-y038)] - Quando un controller deve essere accoppiato ad una view ed un componente può essere riutilizzato da altri controller o view, definisci i controller insieme alle loro route. - + Nota: Se una View è caricata attraverso altri mezzi che una route, allora usa la sintassi `ng-controller="Avengers as vm"`. - *Perché?*: Accoppiare il controller in una route consente a route diverse di invocare diversi accoppiamenti di controller e view. Quando i controller sono assegnati in una view usando [`ng-controller`](https://docs.angularjs.org/api/ng/directive/ngController), quella view sarà sempre associata al medesimo controller. + *Perché?*: Accoppiare il controller in una route consente a route diverse di invocare diversi accoppiamenti di controller e view. Quando i controller sono assegnati in una view usando [`ng-controller`](https://docs.angularjs.org/api/ng/directive/ngController) quella view sarà sempre associata al medesimo controller. ```javascript - /* evitare - quando usato con una route ed è desiderata una dinamicità negli accoppiamenti */ + /* evitare - quando usato con una route e si desidera una dinamicità negli accoppiamenti */ // route-config.js angular From 6133070f45734e13ed1892f984836f146ac804ae Mon Sep 17 00:00:00 2001 From: angelochiello Date: Mon, 18 May 2015 10:35:48 +0200 Subject: [PATCH 293/567] [it-IT] Complete Review (till R. P. C.) This is a complete review. Reviewed till "Resolving Promises for a Controller". --- i18n/it-IT.md | 62 +++++++++++++++++++++++++-------------------------- 1 file changed, 31 insertions(+), 31 deletions(-) diff --git a/i18n/it-IT.md b/i18n/it-IT.md index e58b99e9..504b118c 100644 --- a/i18n/it-IT.md +++ b/i18n/it-IT.md @@ -393,10 +393,10 @@ Invece usa la più semplice sintassi setter. } ``` -### Membri che possono fare il bind posti in alto +### Membri che possono fare il bind in alto ###### [Stile [Y033](#stile-y033)] - - Poni i membri che possono fare il bind in alto nll controller, in ordine alfabetico, piuttosto che dispersi in tutto il codice del controller. + - Poni i membri che possono fare il bind in alto nel controller, in ordine alfabetico, piuttosto che dispersi in tutto il codice del controller. *Perché?*: Porre i membri che posso fare il bind in alto rende semplice la lettura e aiuta l'istantanea identificazione di quali membri del controller possono essere collegati ed usati in una View. @@ -687,7 +687,7 @@ Invece usa la più semplice sintassi setter. - I Service sono istanziati con la keyword `new`, usa `this` per metodi e variabili pubbliche. Dal momento che sono molto simili alle factory, usa queste ultime per consistenza. - Nota: [Tutti i servizi di AngularJS sono singleton](https://docs.angularjs.org/guide/services). Questo significa che c'è soltanto una istanza di un dato servizio per iniettore. + Nota: [Tutti i servizi di Angular sono singleton](https://docs.angularjs.org/guide/services). Questo significa che c'è soltanto una istanza di un dato servizio per iniettore. ```javascript // service @@ -724,25 +724,25 @@ Invece usa la più semplice sintassi setter. ### Singola responsabilità ###### [Stile [Y050](#stile-y050)] - - Le factory dovrebbero avere la [singola responsabilità](http://en.wikipedia.org/wiki/Single_responsibility_principle) che è incapsulata nel proprio contesto. Una volta che una factory eccede quello che è un singolo scopo, una nuova factory dovrebbe essere creata. + - Le factory dovrebbero avere la [singola responsabilità](http://en.wikipedia.org/wiki/Single_responsibility_principle) che è incapsulata nel proprio contesto. Una volta che una factory eccede quello che è un singolo scopo, dovrebbe essere creata una nuova factory. ### Singleton ###### [Stile [Y051](#stile-y051)] - Le factory sono singleton e ritornano un oggetto che contiene i membri del servizio. - Nota: [Tutti i servizi di AngularJS sono singleton](https://docs.angularjs.org/guide/services). + Nota: [Tutti i servizi di Angular sono singleton](https://docs.angularjs.org/guide/services). -### Membri accessibili in cima +### Membri accessibili in alto ###### [Stile [Y052](#stile-y052)] - - Esponi tutti i membri richiamabili del servizio (l'interfaccia) in cima, usando una tecnica derivata dal [Revealing Module Pattern](http://addyosmani.com/resources/essentialjsdesignpatterns/book/#revealingmodulepatternjavascript). + - Esponi tutti i membri richiamabili del servizio (l'interfaccia) in alto, usando una tecnica derivata dal [Revealing Module Pattern](http://addyosmani.com/resources/essentialjsdesignpatterns/book/#revealingmodulepatternjavascript). - *Perché?*: Porre i membri richiamabili in cima lo rende semplice da leggere e aiuta ad identificare istantaneamente quali membri del servizio possono essere richiamati ed essere oggetto di unit test (e/o simulati). + *Perché?*: Porre i membri richiamabili in alto lo rende semplice da leggere e aiuta ad identificare istantaneamente quali membri del servizio possono essere chiamati ed essere oggetto di unit test (e/o simulati). - *Perché?*: Questo è particolarmente utile quando i file iniziano ad allungarsi così come aiuta la necessità di scorrere per leggere cosa è esposto. + *Perché?*: Questo è particolarmente utile quando i file iniziano ad allungarsi così da evitare la necessità di scorrere per leggere cosa è esposto. - *Perché?*: Settare funzioni mentre procedi può essere facile ma quando tali funzioni sono più lunghe di 1 linea di codice possono ridurre la leggibilità e causare maggiore scorrimento. Definire l'interfaccia richiamabile attraverso i servizi ritornati sposta i dettagli di implementazione in basso, tiene l'interfaccia richiamabile in cima e rende più facile al lettura. + *Perché?*: Settare funzioni mentre procedi può essere facile ma quando tali funzioni sono più lunghe di 1 linea di codice possono ridurre la leggibilità e causare maggiore scorrimento. Definire l'interfaccia richiamabile attraverso i servizi ritornati sposta i dettagli di implementazione in basso, tiene l'interfaccia richiamabile in alto e rende più facile la lettura. ```javascript /* evitare */ @@ -794,11 +794,11 @@ Invece usa la più semplice sintassi setter. ### Dichiarazioni di funzione per nascondere i dettagli di implementazione ###### [Stile [Y053](#stile-y053)] - - Usa le dichiarazioni di funzioni per nascondere i dettagli di implementazione. Tieni i membri accessibili della factory in cima. Puntali alle dichiarazioni di funzioni che compaiono dopo nel file. Per ulteriori dettagli guarda [questo post](http://www.johnpapa.net/angular-function-declarations-function-expressions-and-readable-code) (in inglese). + - Usa le dichiarazioni di funzioni per nascondere i dettagli di implementazione. Tieni i membri accessibili della factory in alto. Puntali alle dichiarazioni di funzioni che compaiono dopo nel file. Per ulteriori dettagli guarda [questo post](http://www.johnpapa.net/angular-function-declarations-function-expressions-and-readable-code) (in inglese). - *Perché?*: Porre i membri richiamabili in cima lo rende semplice da leggere e aiuta ad identificare istantaneamente quali funzioni della factory possono accessibili esternamente. + *Perché?*: Porre i membri richiamabili in alto la rende semplice da leggere e aiuta ad identificare istantaneamente quali funzioni della factory possono accessibili esternamente. - *Perché?*: Porre i dettagli di implementazione di una funzione dopo nel file sposta la complessità fuori dalla vista così che puoi vedere le cose importanti in cima. + *Perché?*: Porre i dettagli di implementazione di una funzione dopo nel file sposta la complessità fuori dalla vista così che puoi vedere le cose importanti prima. *Perché?*: Le dichiarazioni di funzione sono richiamate così da non avere preoccupazioni circa l'uso di una funzione prima della sua definizione (come sarebbe nel caso di espressioni di funzione). @@ -850,7 +850,7 @@ Invece usa la più semplice sintassi setter. /** * consigliato * Uso di dichiarazioni di funzioni - * e membri accessibili in cima. + * e membri accessibili in alto. */ function dataservice($http, $location, $q, exception, logger) { var isPrimed = false; @@ -896,14 +896,14 @@ Invece usa la più semplice sintassi setter. ### Separare le chiamate ai dati ###### [Stile [Y060](#stile-y060)] - - Rivedi la logica per gestire le operazioni con i dati e con la loro interazione delegandola ad una factory. + - Rivedi la logica per gestire le operazioni con i dati e con la loro interazione delegandola ad una factory. Rendi il servizio di accesso ai dati responsabile per le chiamate XHR, conservazione locale, lo stashing in memoria o qualunque altra operazione sui dati. - *Perché?*: La responsabilità del controller è per la presentazione e raccolta di informazioni dalla view. Non dovrebbe occuparsi di come recuperare i dati, soltanto sapere a chi chiederli. La separazione dei servizi per i dati sposta la logica su come reperirli al servizio dei dati, rendendo il controller più semplice e più focalizzato sulla view. + *Perché?*: La responsabilità del controller è la presentazione e raccolta di informazioni dalla view. Non dovrebbe occuparsi di come recuperare i dati, soltanto sapere a chi chiederli. La separazione dei servizi per i dati sposta la logica su come reperirli al servizio dei dati, rendendo il controller più semplice e più focalizzato sulla view. *Perché?*: Ciò rende più semplice da testare (vere o simulate) le chiamate ai dati quando si testa un controller che usa un servizio ai dati. - *Perché?*: L'implementazione di un servizio ai dati può avere del codice molto specifico su come trattare i repository dei dati. Questo può includere header, come comunicare con i dati o altri servizi quali `$http`. Separare la logica in un servizio ai dati incapsula questa logica in un posto unico nascondendo l'implementazione ai consumatori esterni (forse un controller), rendendo inoltre più semplice cambiarne l'implementazione. + *Perché?*: L'implementazione di un servizio ai dati può avere del codice molto specifico su come trattare i repository dei dati. Questo può includere header, come comunicare con i dati o altri servizi quali `$http`. Separare la logica in un servizio ai dati incapsula questa logica in un posto unico nascondendo l'implementazione a consumatori esterni (forse un controller), rendendo inoltre più semplice cambiarne l'implementazione. ```javascript /* consigliato */ @@ -930,7 +930,7 @@ Invece usa la più semplice sintassi setter. } function getAvengersFailed(error) { - logger.error('XHR Failed for getAvengers.' + error.data); + logger.error('XHR fallita per getAvengers.' + error.data); } } } @@ -973,7 +973,7 @@ Invece usa la più semplice sintassi setter. ### Ritornare una promessa dalle chiamate ai dati ###### [Stile [Y061](#stile-y061)] - - Quando si chiama un servizio ai dati che ritorna una promessa come $http, ritorna a tua volta una promessa nella tua funzione di chiamata. + - Quando si chiama un servizio ai dati che ritorna una promessa come `$http`, ritorna a tua volta una promessa nella funzione di chiamata. *Perché?*: Puoi concatenare le promesse insieme e prendere ulteriori azioni dopo che la chiamata ai dati è completata e risolvere o rigettare la promessa. @@ -1007,7 +1007,7 @@ Invece usa la più semplice sintassi setter. .then(function(data) { /** * Passo 3 - * set the data and resolve the promise setta i dati e risolvi la promessa + * setta i dati e risolvi la promessa */ vm.avengers = data; return vm.avengers; @@ -1018,12 +1018,12 @@ Invece usa la più semplice sintassi setter. **[Torna all'inizio](#tavola-dei-contenuti)** ## Directive -### Limite di 1 per file +### Limita 1 per file ###### [Stile [Y070](#stile-y070)] - Crea una directive per file. Nomina il file per la directive. - *Perché?*: È facile mescolare tutte le directive in un unico file ma difficoltoso da separarle così che alcune siano condivise tra le applicazioni, alcune tra moduli, altre solo per un module. + *Perché?*: È facile mescolare tutte le directive in un unico file ma difficoltoso da separare così che alcune siano condivise tra le applicazioni, alcune tra moduli, altre solo per un module. *Perché?*: Una directive per file è semplice da manutenere. @@ -1110,12 +1110,12 @@ Invece usa la più semplice sintassi setter. } ``` - Nota: Ci sono molte opzioni per i nomi delle directive, in particolare dal momento che possono essere usate in ambiti stretti o larghi. Scegline uno che sia chiaro e distino che dia senso alla directive e il suo nome del file. Alcuni esempi sono sotto ma vedi la sezione sulla [Nomenclatura](#nomenclatura) per maggiori raccomandazioni. + Nota: Ci sono molte opzioni per i nomi delle directive, in particolare dal momento che possono essere usate in ambiti stretti o larghi. Scegline uno che sia chiaro e distino per la directive e il suo nome del file. Alcuni esempi sono sotto ma vedi la sezione sulla [Nomenclatura](#nomenclatura) per ulteriori suggerimenti. ### Manipolare il DOM in una Directive ###### [Stile [Y072](#stile-y072)] - - Quando devi manipolare direttamente il DOM, usa una directive. Se possono essere usate delle alternative come settare stili CSS o i [servizi di animazione](https://docs.angularjs.org/api/ngAnimate), templating di Angular, [`ngShow`](https://docs.angularjs.org/api/ng/directive/ngShow) oppure [`ngHide`](https://docs.angularjs.org/api/ng/directive/ngHide), piuttosto usa questi. Per esempio, se la directive semplicemente nasconde e mostra, usa ngHide/ngShow. + - Quando devi manipolare direttamente il DOM, usa una directive. Se possono essere usate delle alternative come usare CSS per settare stili o i [servizi di animazione](https://docs.angularjs.org/api/ngAnimate), templating di Angular, [`ngShow`](https://docs.angularjs.org/api/ng/directive/ngShow) oppure [`ngHide`](https://docs.angularjs.org/api/ng/directive/ngHide), allora usa questi. Per esempio, se la directive deve semplicemente nascondere e mostrare, usa ngHide/ngShow. *Perché?*: Manipolare il DOM può essere difficoltoso da testare, debuggare e spesso ci sono modi migliori (p.e. CSS, animazioni, template) @@ -1126,7 +1126,7 @@ Invece usa la più semplice sintassi setter. *Perché?*: L'unico breve prefisso identifica il contesto delle directive e l'origine. Per esempio un prefisso `cc-` potrebbe indicare che la directive è parte di una app CodeCamper mentre `acme-` potrebbe indicare una direttiva per l'azienda Acme. - Nota: Evita `ng-` poiché queste sono riservate per le directive di AngularJS. Cerca directive che sono largamente utilizzate per evitare il conflitto di nomi, come `ion-` per il [Framework Ionic ](http://ionicframework.com/). + Nota: Evita `ng-` poiché queste sono riservate per le directive di Angular. Cerca directive che sono largamente utilizzate per evitare il conflitto di nomi, come `ion-` per il [Framework Ionic ](http://ionicframework.com/). ### Restringi a Elementi and Attributi ###### [Stile [Y074](#stile-y074)] @@ -1135,9 +1135,9 @@ Invece usa la più semplice sintassi setter. *Perché?*: È sensato. - *Perché?*: Mentre è possibile consentire che la directive sia usata come una classe, se questa agisce davvero con un elemento è più sensato usarla un elemento o al meno come un attributo. + *Perché?*: È possibile consentire che sia usata come una classe ma se la directive agisce davvero come un elemento è più sensato che sia un elemento o al meno un attributo. - Nota: EA è il default per AngularJS 1.3 e successivi + Nota: EA è il default per Angular 1.3 e successivi ```html @@ -1193,14 +1193,14 @@ Invece usa la più semplice sintassi setter. ### Directive e ControllerAs ###### [Stile [Y075](#stile-y075)] - - Usa la sintassi `controller as` con una directive per essere consistente con l'utilizzo di `controller as` con una coppia di view e controller. + - Usa la sintassi `controller as` con una directive per essere consistente con l'utilizzo di `controller as` con un accoppiamento view/controller. *Perché?*: È sensato e non è difficile. - Nota: Le directive sotto dimostrano alcuni dei modi in cui puoi usare lo scope all'interno di link e controller di directive usando controllerAs. Ho usato sulla stessa linea il template solo per mettere tutto in un unico posto. + Nota: La directive sotto dimostra alcuni dei modi in cui puoi usare lo scope all'interno di link e controller di directive usando controllerAs. Ho usato sulla stessa linea il template solo per mettere tutto in un unico posto. Nota: In relazione alla dependency injection, guarda [Annotazioni manuali per la Dependency Injection](#annotazioni-manuali-per-la-dependency-injection). - + Nota: Notare che il controller della directive è al di fuori della closure della directive. Questo stile elimina problematiche dove l'iniezione viene creata come codice non raggiungibile dopo un `return`. ```html @@ -1222,7 +1222,7 @@ Invece usa la più semplice sintassi setter. link: linkFunc, controller : ExampleController, controllerAs: 'vm', - bindToController: true // because the scope is isolated + bindToController: true // perché lo scope è isolato }; return directive; From ccbb654a42fdc01b5aecd0f9767241ada4c2486b Mon Sep 17 00:00:00 2001 From: angelochiello Date: Mon, 18 May 2015 18:06:52 +0200 Subject: [PATCH 294/567] [it-IT] Complete Review (LIFT Principle) This is a complete review. Reviewed till Application Structure LIFT Principle excluded. --- i18n/it-IT.md | 113 +++++++++++++++++++++++--------------------------- 1 file changed, 51 insertions(+), 62 deletions(-) diff --git a/i18n/it-IT.md b/i18n/it-IT.md index 504b118c..828b0122 100644 --- a/i18n/it-IT.md +++ b/i18n/it-IT.md @@ -1322,7 +1322,7 @@ Invece usa la più semplice sintassi setter. - Risolvi la logica di start-up per un controller in una funzione `activate`. - *Perché?*: Porre la logica di start-up in una posizione consistente nel controller la rende semplice da localizzare, più consistente da testare e aiuta a prevenire la diffusione di logica su tutto il controller. + *Perché?*: Porre la logica di start-up in una posizione consistente nel controller la rende semplice da localizzare, più consistente da testare e aiuta a prevenire la diffusione della logica di attivazione su tutto il controller. *Perché?*: La funzione `activate` del controller rende il riuso della logica adatto in caso di un refresh del controller/view, tiene la logica assieme, porta l'utente alla view più rapidamente, rende le animazini più facili su `ng-view` o `ui-view`e da la sensazione all'utente di istantaneità. @@ -1365,15 +1365,15 @@ Invece usa la più semplice sintassi setter. ### Promesse risolte nel route ###### [Stile [Y081](#stile-y081)] - - Quando un controller dipende dal fatto che una promessa sia risolta prima che il controller sia attivato, risolvi queste dipendenze nel `$routeProvider` prima che la logica del controller sia eseguita. Se hai bisogno di annullare condizionalmente una route prima che il controller sia attivato, usa un resolver della route. + - Quando un controller dipende dal fatto che una promessa sia risolta prima che il controller sia attivato, risolvi queste dipendenze nel `$routeProvider` prima che la logica del controller sia eseguita. Se hai bisogno di annullare condizionalmente una route prima che il controller sia attivato, usa una risoluzione della route. - Usa la risoluzione della route quando decidi di annullare la route prima ancora di iniziara la transizione alla view. - *Perché?*: Un controller può richiedere dei dati prima che si carichi. Quei dati potrebbero venire da una promessa di una factory su misura oppure [$http](https://docs.angularjs.org/api/ng/service/$http). Usando un [resolver della route](https://docs.angularjs.org/api/ngRoute/provider/$routeProvider) acconsenti che la promessa sia risolta prima che la logica del controller sia eseguita, così da poter prendere decisioni basandosi sui dati provenienti dalla promessa. + *Perché?*: Un controller può richiedere dei dati prima che si carichi. Quei dati potrebbero venire da una promessa di una factory su misura oppure [$http](https://docs.angularjs.org/api/ng/service/$http). Usando un [resolver della route](https://docs.angularjs.org/api/ngRoute/provider/$routeProvider) consenti che la promessa sia risolta prima che la logica del controller sia eseguita, così da poter prendere decisioni basandosi sui dati provenienti dalla promessa. - *Perché?*: Il codice è eseguito dopo la route e nella funzione di attivazione del controller. La view inizia il caricamento immediatamente. Il data binding è effettivo quando le promesse nella funzine di attivazione sono risolte. Una animazione di “attendere” può essere mostrata durante la transizione alla view (via ng-view o ui-view). + *Perché?*: Il codice è eseguito dopo la route e nella funzione di attivazione del controller. La view inizia il caricamento immediatamente. Il data binding è effettivo quando le promesse nella funzione di attivazione sono risolte. Una animazione di “attendere” può essere mostrata durante la transizione alla view (per mezzo di ng-view o ui-view). - Nota: Il codice è eseguito prima il route per mezo di una promessa. Il rifiuto della promessa annulla la route. "resolve" fa attendere la view mentre viene risolta. Una animazione “attendere” può essere mostrata prima della risoluzione e durante tutta la transizione alla vista. Se desideri di arrivare alla view più in fretta e non hai bisogno di un punto di controllo per decidere se vuoi navigare alla view, considera piuttosto [Promesse di attivazione di un Controller](#stile-y080). + Nota: Il codice è eseguito prima del route per mezzo di una promessa. Il rifiuto della promessa annulla la route. "Resolve" fa attendere la view mentre viene risolta. Una animazione “attendere” può essere mostrata prima della risoluzione e durante tutta la transizione alla vista. Se desideri arrivare alla view più in fretta e non hai bisogno di un punto di controllo per decidere se vuoi navigare alla view, considera piuttosto [Promesse di attivazione di un Controller](#stile-y080). ```javascript /* evitare */ @@ -1426,10 +1426,10 @@ Invece usa la più semplice sintassi setter. } ``` - Note: L'esempio sotto mostra il punto di risoluzione della route in una funzione con il nome per cui è più semplice da fare il debug e più semplice da gestire nella iniezione delle dependenze. + Nota: L'esempio sotto mostra il punto di risoluzione della route in una funzione con il nome per cui è più semplice da fare il debug e più semplice da gestire nella iniezione delle dependenze. ```javascript - /* meglio */ + /* ancora meglio */ // route-config.js angular @@ -1463,7 +1463,7 @@ Invece usa la più semplice sintassi setter. vm.movies = moviesPrepService.movies; } ``` - Nota: La dipendenza del codice di esempio da `movieService` non è a prova di minificazione in se stessa. Per i dettagli su come rendere questo codice a prova di minificazione, vedi la sezione sulla [dependency injection](#manual-annotating-for-dependency-injection) e sulla [minificazione e annotazione](#minification-and-annotation). + Nota: La dipendenza del codice di esempio da `movieService` non è a prova di minificazione in se stessa. Per i dettagli su come rendere questo codice a prova di minificazione, vedi la sezione sulla [dependency injection](#annotazioni-manuali-per-la-dependency-injection) e sulla [minificazione e annotazione](#minificazione-e-annotazioni). **[Torna all'inizio](#tavola-dei-contenuti)** @@ -1474,7 +1474,7 @@ Invece usa la più semplice sintassi setter. - Evita di usare abbreviazioni sintattiche per la dichiarazione di dipendenze senza usare un approccio a prova di minificazione. - *Perché?*: I parametri dei componenti (p.e. controller, factory, etc.) saranno convertiti in variabili dal nome ridotto. Per esempio, `common` e `dataservice` potrebbero diventare `a` o `b` e non essere piò ritrovate da AngularJS. + *Perché?*: I parametri dei componenti (p.e. controller, factory, etc.) saranno convertiti in variabili dal nome ridotto. Per esempio, `common` e `dataservice` potrebbero diventare `a` o `b` e non essere piò ritrovate da Angular. ```javascript /* evita - non a prova di minificazione*/ @@ -1496,13 +1496,13 @@ Invece usa la più semplice sintassi setter. ### Indentificazione manuale delle dipendenze ###### [Stile [Y091](#stile-y091)] - - Usa `$inject` per identificare manualmente le tue dipendenze per i componenti di AngularJS. + - Usa `$inject` per identificare manualmente le tue dipendenze per i componenti di Angular. - *Perché?*: Questa tecnica rispecchia la tecnica usata da [`ng-annotate`](https://github.com/olov/ng-annotate), che raccomando per l'automazione della creazione della minificazione che sia a sicura per le dipendenze. Se `ng-annotate` rileva che una iniezione è stata fatta, non la duplicherà. + *Perché?*: Questa tecnica rispecchia la tecnica usata da [`ng-annotate`](https://github.com/olov/ng-annotate), che raccomando per l'automazione della creazione della minificazione sicura delle dipendenze. Se `ng-annotate` rileva che una iniezione è stata fatta, non la duplicherà. - *Perché?*: Questo salvaguarda le tue dipendenze dal essere vulnerabili alla questione della minificazione quando i parametri possono essere passati con nomi ridotti. Per esempio, `common` e `dataservice` possono diventare `a` o `b` e non essere più trovati da AngularJS. + *Perché?*: Questo salvaguarda le tue dipendenze dall'essere vulnerabili alla questione della minificazione quando i parametri possono essere passati con nomi ridotti. Per esempio, `common` e `dataservice` possono diventare `a` o `b` e non essere più trovati da Angular. - *Perché?*: Evita la creazione di dipendenze sulla stessa linea dal momento che lunghe liste possono essere difficili da leggere nell'array. Inoltre può essere fuorviante che l'array è una serie di stringhe mentre l'ultimo elemento è una funzione. + *Perché?*: Evita la creazione di dipendenze sulla stessa linea dal momento che lunghe liste possono essere difficili da leggere nell'array. Inoltre può essere fuorviante che l'array è una serie di stringhe mentre l'ultimo elemento è la funzione del componente. ```javascript /* evitare */ @@ -1537,44 +1537,48 @@ Invece usa la più semplice sintassi setter. } ``` - Nota: Quando la tua funzione si trova sotto una dichiarazione di return, $inject potrebbe essere non raggiungibile (ciò può accadere in una directive). Puoi risolvere ciò sia spostando l'$inject sopra la dichiarazione di return oppure usando la sintassi di array di iniezione alternativa. - - Nota: [`ng-annotate 0.10.0`](https://github.com/olov/ng-annotate) introduce una caratteristica che sposta l'`$inject` dove è raggiungibile. + Nota: Quando la tua funzione si trova dopo una dichiarazione di return, `$inject` potrebbe essere non raggiungibile (ciò può accadere in una directive). Puoi risolvere ciò sia spostando il Controller fuori dalla directive. ```javascript + /* evitare */ // dentro la definizione di una directive function outer() { - return { - controller: DashboardPanel, + var ddo = { + controller: DashboardPanelController, + controllerAs: 'vm' }; + return ddo; - DashboardPanel.$inject = ['logger']; // Unreachable - function DashboardPanel(logger) { + DashboardPanelController.$inject = ['logger']; // Non raggiungibile + function DashboardPanelController(logger) { } } ``` ```javascript - // dentro la definizione di una directive + /* consigliato */ + // fuori la definizione di una directive function outer() { - DashboardPanel.$inject = ['logger']; // reachable - return { - controller: DashboardPanel, + var ddo = { + controller: DashboardPanelController, + controllerAs: 'vm' }; + return ddo; + } - function DashboardPanel(logger) { - } + DashboardPanelController.$inject = ['logger']; + function DashboardPanelController(logger) { } ``` ### Idetificazione manuale delle dipendenze di resolver della route ###### [Stile [Y092](#stile-y092)] - - Usa $inject per identificare manualmente le tue dipendenze di resolver della route per i componenti di AngularJS. + - Usa `$inject` per identificare manualmente le tue dipendenze di resolver della route per i componenti di Angular. - *Perché?*: Questa tecnica evade le funzioni anonime per il di resolver della route, rendendolo più semplice da leggere. + *Perché?*: Questa tecnica evade le funzioni anonime per il resolver della route, rendendolo più semplice da leggere. - *Perché?*: Una dichiarazione `$inject` può facilmente precedere il resolver della route per gestire la produzione di dipendenze che siano a prova di minificazione. + *Perché?*: Una dichiarazione `$inject` può facilmente precedere il resolver per gestire la produzione di dipendenze che siano a prova di minificazione. ```javascript /* consigliato */ @@ -1603,11 +1607,10 @@ Invece usa la più semplice sintassi setter. ### ng-annotate ###### [Stile [Y100](#stile-y100)] - - Usa [ng-annotate](//github.com/olov/ng-annotate) per [Gulp](http://gulpjs.com) o [Grunt](http://gruntjs.com) e commenta le funzioni che necessitano di automatizzare il dependency injection usando `/** @ngInject */` + - Usa [ng-annotate](//github.com/olov/ng-annotate) per [Gulp](http://gulpjs.com) o [Grunt](http://gruntjs.com) e commenta le funzioni che necessitano di automatizzare la dependency injection usando `/** @ngInject */` *Perché?*: Questo salvaguarda il tuo codice da ogni dipendenza che non segua le pratiche a prova di minificazione - *Perché?*: [`ng-min`](https://github.com/btford/ngmin) is deprecated *Perché?*: [`ng-min`](https://github.com/btford/ngmin) è deprecato. >Preferisco Gulp poiché lo ritengo più semplice da scrivere, leggere e fare il debug. @@ -1632,7 +1635,7 @@ Invece usa la più semplice sintassi setter. } ``` - Quando il codice soprastante è eseguito da ng-annotate produce il seguente output con l'annotazione `$inject` e diventa a prova di minificazione. + Quando il codice soprastante passa da ng-annotate viene prodotto il seguente output con l'annotazione `$inject` e diventa a prova di minificazione. ```javascript angular @@ -1675,13 +1678,13 @@ Invece usa la più semplice sintassi setter. } ``` - > Nota: A partire da AngularJS 1.3 usa il parametro `ngStrictDi` della directive [`ngApp`](https://docs.angularjs.org/api/ng/directive/ngApp). Quando presente, l'iniettore sarà creato in modalità "strict-di" causando il fallimento dell'invocazione di funzioni che non fanno uso esplicito di annotazione delle funzioni da parte dell'applicazione (queste potrebbero non essere a prova di minificazione). Informazioni di debug saranno mostrate nella console per aiutare nel tracciare il codice non confacente. + > Nota: A partire da Angular 1.3 puoi usare il parametro `ngStrictDi` della directive [`ngApp`](https://docs.angularjs.org/api/ng/directive/ngApp) per rilevare ogni potenziale dipendenza che non sia a prova di minificazione. Quando presente, l'iniettore sarà creato in modalità "strict-di" causando il fallimento dell'invocazione di funzioni che non fanno uso esplicito di annotazione delle funzioni da parte dell'applicazione (queste potrebbero non essere a prova di minificazione). Informazioni di debug saranno mostrate nella console per aiutare nel tracciare il codice non confacente. Preferisco usare soltanto `ng-strict-di` per i soli scopi di debug. `` ### Usa Gulp o Grunt per ng-annotate ###### [Stile [Y101](#stile-y101)] - - Usa [gulp-ng-annotate](https://www.npmjs.org/package/gulp-ng-annotate) o [grunt-ng-annotate](https://www.npmjs.org/package/grunt-ng-annotate) in un task di build automatizzato. Inietta `/* @ngInject */` prima di qualunque funzione che abbia delle dipendenze. + - Usa [gulp-ng-annotate](https://www.npmjs.org/package/gulp-ng-annotate) o [grunt-ng-annotate](https://www.npmjs.org/package/grunt-ng-annotate) in un task di automatizzazione delle build. Inietta `/* @ngInject */` prima di qualunque funzione che abbia delle dipendenze. *Perché?*: ng-annotate carpirà la maggior parte delle dipendenze ma talvolta necessita dell'uso del suggerimento sintattico `/* @ngInject */`. @@ -1690,6 +1693,7 @@ Invece usa la più semplice sintassi setter. ```javascript gulp.task('js', ['jshint'], function() { var source = pkg.paths.js; + return gulp.src(source) .pipe(sourcemaps.init()) .pipe(concat('all.min.js', {newLine: ';'})) @@ -1715,9 +1719,9 @@ Invece usa la più semplice sintassi setter. ### decoratori (decorator) ###### [Stile [Y110](#stile-y110)] - - Usa un [decorator](https://docs.angularjs.org/api/auto/service/$provide#decorator), al momento del config una un servizio [`$provide`](https://docs.angularjs.org/api/auto/service/$provide), sul servizio [`$exceptionHandler`](https://docs.angularjs.org/api/ng/service/$exceptionHandler) per eseguire azioni ad hoc quando l'eccezione occorre. + - Usa un [decorator](https://docs.angularjs.org/api/auto/service/$provide#decorator), al momento del config usando il servizio [`$provide`](https://docs.angularjs.org/api/auto/service/$provide), sul servizio [`$exceptionHandler`](https://docs.angularjs.org/api/ng/service/$exceptionHandler) per eseguire azioni ad hoc quando l'eccezione occorre. - *Perché?*: Fornisci un modo consistente per la gestione delle eccezioni che non trattate da AngularJS sia durante lo sviluppo che a runtime. + *Perché?*: Fornisce un modo consistente per la gestione delle eccezioni non trattate da Angular sia durante lo sviluppo che a runtime. Nota: Un'altra opzione è di fare l'override del servizio invece che usare un decorator. Questa è una buona opzione ma se vuoi tenere il comportamento di default ed estenderlo un decorator è consigliato. @@ -1760,7 +1764,7 @@ Invece usa la più semplice sintassi setter. *Perché?*: Fornisce un modo consistente di ricevere le eccezioni che possono essere lanciate nel tuo codice (p.e. durante una chiamata XHR o il fallimento di promesse). - Nota: Il ricevitore di eccezioni è buono per ricevere e reagire a specifiche eccezioni da chiamate che sai ne possono generare una. Per esempio, quando fai una chiamata XHR per il recupero di dati da un servizio di un server web remoto e vuoi ricevere qualsiasi eccezione da ciò e reagire univocamente. + Nota: Il ricevitore di eccezioni è buono per ricevere e reagire a specifiche eccezioni da parte di chiamate che sai ne possono generare una. Per esempio, quando fai una chiamata XHR per il recupero di dati da un servizio di un server web remoto e vuoi ricevere qualsiasi eccezione da ciò e reagire univocamente. ```javascript /* consigliato */ @@ -1899,7 +1903,7 @@ Invece usa la più semplice sintassi setter. avenger-profile.directive.spec.js ``` - Nota: Un'altra convenzione comune è dare il nome al file del controller senza la parola `controller` nel nome del file come `avengers.js` invece di `avengers.controller.js`. Tutte le altre convenzioni continuano ancora a mantenere il suffisso del tipo. I controller sono i tipi di componenti più comuni perciò questo risparmia digitazione continuando ad essere facilmente identificabili. Consiglio di scegliere 1 convenzione e rimanere consistente nel tuo team. + Nota: Un'altra convenzione comune è dare il nome al file del controller senza la parola `controller` nel nome del file come `avengers.js` invece di `avengers.controller.js`. Tutte le altre convenzioni continuano ancora a mantenere il suffisso del tipo. I controller sono i tipi di componenti più comuni perciò questo risparmia digitazione continuando ad essere facilmente identificabili. Consiglio di scegliere 1 convenzione e rimanere consistente nel tuo team. La mia preferenza va a `avengers.controller.js`. ```javascript /** @@ -1917,7 +1921,7 @@ Invece usa la più semplice sintassi setter. *Perché?*: Fornisce un modo consistente per identificare facilmente i componenti. - *Perché?*: Fornisce uno schema di corrispondenza per [karma](http://karma-runner.github.io/) o altri esecutori di test. + *Perché?*: Fornisce uno schema di corrispondenza per [karma](http://karma-runner.github.io/) o altri esecutori di test. ```javascript /** @@ -1954,28 +1958,13 @@ Invece usa la più semplice sintassi setter. ### Suffisso nel nome di un controller ###### [Stile [Y124](#stile-y124)] - - Aggiungi `Controller` alla fine del nome del controller o no. Segli 1 non entrambi. + - Aggiungi `Controller` alla fine del nome del controller. *Perché?*: Il suffisso `Controller` è quello più comunemente usato ed è più esplicitamente descrittivo. - *Perché?*: L'omissione del suffisso è più coinciso ed il controller è spesso facilmente identificabile anche senza suffisso. - ```javascript /** - * consigliato: Opzione 1 - */ - - // avengers.controller.js - angular - .module - .controller('Avengers', Avengers); - - function Avengers(){ } - ``` - - ```javascript - /** - * consigliato: Opzione 2 + * consigliato */ // avengers.controller.js @@ -1989,7 +1978,7 @@ Invece usa la più semplice sintassi setter. ### Nomi delle factory ###### [Stile [Y125](#stile-y125)] - - Usa una nomenclatura consistente per tutte le factory dando i nomi date le loro funzionalità. Usa il camel-case per service e factory. Evita di pre-nominare factory e service con `$` + - Usa una nomenclatura consistente per tutte le factory dando i nomi a seguito delle loro funzionalità. Usa il camel-case per service e factory. Evita di pre-nominare factory e service con `$` *Perché?*: Fornisce un modo consistente per identificare facilmente e referenziare le factory. @@ -2011,7 +2000,7 @@ Invece usa la più semplice sintassi setter. ### Nomi dei componenti directive ###### [Stile [Y126](#stile-y126)] - - Usa nomi consistenti per putte le directive usando il camel-case. Usa un breve prefisso che descriva l'area alla quale la directive appartiene (alcuni esempi sono prefissi relativi all'azienda o al progetto). + - Usa nomi consistenti per tutte le directive usando il camel-case. Usa un breve prefisso che descriva l'area alla quale la directive appartiene (alcuni esempi sono prefissi relativi all'azienda o al progetto). *Perché?*: Fornisce un modo consistente per identificare e referenziare facilmente i componenti. @@ -2025,7 +2014,7 @@ Invece usa la più semplice sintassi setter. .module .directive('xxAvengerProfile', xxAvengerProfile); - // usage is + // l'uso è function xxAvengerProfile(){ } ``` @@ -2033,11 +2022,11 @@ Invece usa la più semplice sintassi setter. ### Moduli ###### [Stile [Y127](#stile-y127)] - - Quando i sono moduli multipli, il modulo principale è nominato come `app.module.js` mentre altri moduli dipendenti prendono i nomi da ciò che rappresentano. Per esempio, un modulo admin è nominato `admin.module.js`. I rispettivi nomi con i quali sono registrati saranno `app` e `admin`. + - Quando ci sono moduli multipli, il modulo principale è nominato come `app.module.js` mentre altri moduli dipendenti prendono i nomi da ciò che rappresentano. Per esempio, un modulo admin è nominato `admin.module.js`. I rispettivi nomi con i quali sono registrati saranno `app` e `admin`. *Perché?*: Fornisce consistenza per app che hanno più di un modulo e per poter espandere verso applicazioni a larga scala. - *Perché?*: Fornisci un modo semplice al fine di usare processi automatici per caricare prima tutte le definizioni di moduli, successivamente tutti gli altri file di Angular (per il bundling). + *Perché?*: Fornisce un modo semplice al fine di usare processi automatici per caricare prima tutte le definizioni di moduli, successivamente tutti gli altri file di Angular (per il bundling). ### Configurazione ###### [Stile [Y128](#stile-y128)] @@ -2046,7 +2035,7 @@ Invece usa la più semplice sintassi setter. *Perché?*: Separa la configurazione dalla definizione, componenti e codice di attivazione del modulo. - *Perché?*: Fornisci una posizione identificabile per settare la configurazione di un modulo. + *Perché?*: Fornisce una posizione identificabile per settare la configurazione di un modulo. ### Route ###### [Stile [Y129](#stile-y129)] From 040a5a33255ee6bda0255bf23304651e00c6a0a4 Mon Sep 17 00:00:00 2001 From: angelochiello Date: Mon, 18 May 2015 18:29:09 +0200 Subject: [PATCH 295/567] [it-IT] Complete Review (Modularity) This is a complete review. Reviewed till "Modularity". --- i18n/it-IT.md | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/i18n/it-IT.md b/i18n/it-IT.md index 828b0122..7770caa1 100644 --- a/i18n/it-IT.md +++ b/i18n/it-IT.md @@ -2048,14 +2048,14 @@ Invece usa la più semplice sintassi setter. ### LIFT ###### [Stile [Y140](#stile-y140)] - - Struttura la tua app tale da poter `L`ocate (localizzare) il codice facilmente, `I`dentify (identificare) il codice con uno sguardo, tenere la struttura più `F`lattest (piatta) che puoi, e `T`ry (provare) a rimanere DRY (Don't Repeat Yourself - Non ripetersi). La struttura dovrebbe seguire queste 4 linee guida basilari. + - Struttura la tua app tale da poter `L`ocate (localizzare) il codice facilmente, `I`dentify (identificare) il codice a colpo d'occhio, tenere la struttura più `F`lattest (piatta) che puoi, e `T`ry (provare) a rimanere DRY (Don't Repeat Yourself - Non ripetersi). La struttura dovrebbe seguire queste 4 linee guida basilari. - *Perché LIFT?*: Fornisce una struttura consistente che scala bene, è modulare e rende più semplice aumentare l'efficienza nel trovare facilmente il codice. Un altro modo per verificare la struttura della tua app è chiediti: Quanto rapidamente puoi aprire e lavorare ad una funzionalità in tutti i file che sono collegati? + *Perché LIFT?*: Fornisce una struttura consistente che scala bene, è modulare e rende più semplice aumentare l'efficienza dello sviluppatore nel trovare facilmente il codice. Un altro modo per verificare la struttura della tua app è chiederti: Quanto rapidamente puoi aprire e lavorare ad una funzionalità in tutti i file che sono collegati? Quando ritengo che la mia struttura non sia confortevole, torno indietro a rivedere le linee guida LIFT 1. `L`ocalizzare il nostro codice con facilità - 2. `I`dentificare il codice a vista + 2. `I`dentificare il codice a colpo d'occhio 3. `F`lat (pitta) struttura quanto più possibile 4. `T`ry (prova) a restare DRY (Don’t Repeat Yourself) o T-DRY @@ -2064,7 +2064,7 @@ Invece usa la più semplice sintassi setter. - Rendi intuitivo, semplice e facile localizzare il codice. - *Perché?*: Ritengo ciò essere estremamente importante per il progetto. Se il team non è in grado di trovare i file di cui necessita rapidamente, non sarà in grado di lavorare il più efficacemente possibile, per cui la struttura necessita un cambiamento. Potresti non sapere il nome del file o dove sono i file a questo correlati quindi posizionarli in nel posto più intuitivo e prossimi gli uni agli altri fa risparmiare un mucchio di tempo. Una descrittiva struttura delle cartelle può essere d'aiuto. + *Perché?*: Ritengo ciò essere estremamente importante per un progetto. Se il team non è in grado di trovare i file di cui necessita rapidamente, non sarà in grado di lavorare il più efficacemente possibile, per cui la struttura necessita un cambiamento. Potresti non sapere il nome del file o dove sono i file a questo correlati quindi posizionarli in nel posto più intuitivo e prossimi gli uni agli altri fa risparmiare un mucchio di tempo. Una descrittiva struttura delle cartelle può essere d'aiuto. ``` /bower_components @@ -2097,7 +2097,7 @@ Invece usa la più semplice sintassi setter. - Tieni la struttura delle cartelle piatta il più a lungo possibile. Quando arrivi ad avere 7 o più file, inizia a considerarne una separazione. - *Perché?*: Nessuno vuole cercare 7 livelli di cartelle per trovare un file. Pensa ai menù di un sito web.. qualunque cosa oltre i 2 livelli dovrebbe esser presa in considerazione. Nella struttura di cartella non c'è una regola con un numero esattamente definito ma quando una cartella contiene 7-10 file, è il momento di creare una sottocartella. Basalo su un livello a te comodo. Usa una struttura più piatta fino a che c'è l'ovvia necessità (praticando il resto dei principi LIFT) di creare una nuova cartella. + *Perché?*: Nessuno vuole cercare 7 livelli di cartelle per trovare un file. Pensa ai menù di un sito web.. qualunque cosa oltre i 2 livelli dovrebbe esser presa in seria considerazione. Nella struttura di cartella non c'è una regola con un numero esattamente definito ma quando una cartella contiene 7-10 file, potrebbe essere il momento di creare una sottocartella. Basalo su un livello a te comodo. Usa una struttura più piatta fino a che c'è l'ovvia necessità (praticando il resto dei principi LIFT) di creare una nuova cartella. ### T-DRY (Try to Stick to DRY) - Prova a non ripeterti ###### [Stile [Y144](#stile-y144)] @@ -2113,7 +2113,7 @@ Invece usa la più semplice sintassi setter. ### Linee guida generali ###### [Stile [Y150](#stile-y150)] - - Abbi una visione a breve termine dell'implementazione e una a lunga scadenza. In altre parole, parti in piccolo ma tieni in mente su dove l'app è diretta lungo il percorso. Tutto il codice dell'app va nella cartella principale chiamata `app`. Tutti i contenuti rispettano 1 funzione per file. Ogni controller, service, module, view nel proprio file. Tutti gli script di terze party sono poste in una altra cartella principale e non nella cartella `app`. Non le ho scritte e non voglio facciano disordine nella mia app (`bower_components`, `scripts`, `lib`). + - Abbi una visione a breve termine dell'implementazione e una a lunga scadenza. In altre parole, parti in piccolo ma tieni in mente su dove l'app è diretta lungo il percorso. Tutto il codice dell'app va nella cartella principale chiamata `app`. Tutto il contenuto rispetta 1 funzione per file. Ogni controller, service, module, view nel proprio file. Tutti gli script di terze party sono poste in una altra cartella principale e non nella cartella `app`. Non le ho scritte e non voglio facciano disordine nella mia app (`bower_components`, `scripts`, `lib`). Nota: Trovi più dettagli e le motivazioni di questa struttura nel [post originale sulla struttura delle applicazioni](http://www.johnpapa.net/angular-app-structuring-guidelines/) (in inglese). @@ -2139,7 +2139,7 @@ Invece usa la più semplice sintassi setter. ```javascript /** - * raccomanadato + * consigliato */ app/ @@ -2175,7 +2175,7 @@ Invece usa la più semplice sintassi setter. session-detail.controller.js ``` - ![Struttura dell'App di Esempio](https://raw.githubusercontent.com/johnpapa/angularjs-styleguide/master/assets/modularity-2.png) + ![Struttura dell'App di Esempio](https://raw.githubusercontent.com/johnpapa/angularjs-styleguide/master/assets/modularity-2.png) Nota: Non utilizzare una strutturazione del tipo cartella-per-tipo. Questo richiede spostarsi tra molte cartelle quando si lavora su una funzionalità e diventa rapidamente scomodo quando l'app cresce di 5, 10 o più di 25 tra view e controller (ed altre funzionalità), per cui è più difficile rispetto alla localizzazione basata su cartella-per-funzionalità. From 53e12e3f7fd425e5353ec9e7c9127e077a74b715 Mon Sep 17 00:00:00 2001 From: angelochiello Date: Mon, 18 May 2015 19:13:52 +0200 Subject: [PATCH 296/567] [it-IT] Complete Review (Startup Logic) This is a complete review. Reviewed till "Startup Logic". --- i18n/it-IT.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/i18n/it-IT.md b/i18n/it-IT.md index 7770caa1..7bc3b97c 100644 --- a/i18n/it-IT.md +++ b/i18n/it-IT.md @@ -2235,12 +2235,12 @@ Invece usa la più semplice sintassi setter. - Crea un modulo principale per l'applicazione il cui ruolo sia di mettere insieme tutti gli altri moduli e funzionalità della tua applicazione. Chiamalo con il nome della tua applicazione. - *Perché?*: AngularJS incoraggia la modularità e schemi di separazione. La creazione di un modulo principale il cui ruolo sia quello di legante tra gli altri moduli consente un modo lineare di aggiungere o rimuovere moduli dall'applicazione. + *Perché?*: Angular incoraggia la modularità e schemi di separazione. La creazione di un modulo principale il cui ruolo sia quello di legante tra gli altri moduli consente un modo lineare di aggiungere o rimuovere moduli dall'applicazione. ### Tenere il modulo App snello ###### [Stile [Y162](#stile-y162)] - - Nel modulo principale metti solo la logica che serva da collante per l'app. Lascia le funzioni ognuno al proprio modulo. + - Nel modulo principale metti solo la logica che serva da collante per l'app. Lascia le funzionalità ognuna al proprio modulo. *Perché?*: L'aggiunta di ruoli addizionali al modulo principale per il recupero dei dati, il mostrare viste o altra logica non correlata al tenere insieme l'applicazione sporca il modulo principale e rende entrambi gli insiemi di funzionalità più complessi da riusare o rimuovere. @@ -2262,7 +2262,7 @@ Invece usa la più semplice sintassi setter. - Crea moduli che rappresentino blocchi di applicazione riutilizzabili per servizi comuni quali la gestione delle eccezioni, il log, la diagnostica, sicurezza e il data stashing locale. - *Perché?*: Questi tipi di funzionalità sono richieste in molte applicazioni, perciò tenerle separate in moduli possono essere generiche l'applicazione e riutilizzate in applicazioni diverse. + *Perché?*: Questi tipi di funzionalità sono richieste in molte applicazioni, perciò tenendole separate nel proprio modulo possono essere generiche e riutilizzate in applicazioni diverse. ### Dipendenze dei Moduli ###### [Stile [Y165](#stile-y165)] @@ -2275,13 +2275,13 @@ Invece usa la più semplice sintassi setter. *Perché?*: Ogni area di funzionalità contiene un manifesto di ciò da cui dipende, in modo tale da poter essere usato come dipendenza in altre applicazioni e continuare a funzionare. - *Perché?*: Funzionalità intra-app come servizio ai dati condiviso diventano facilmente localizzabili da dentro `app.core` (questi il nome che più di piaccia per questo modulo). + *Perché?*: Funzionalità intra-app come servizio ai dati condiviso diventano facilmente localizzabili da dentro `app.core` (scegli il nome che più di piaccia per questo modulo). - Nota: Questa è una strategia per la consistenza. Ci sono diverse buone opzioni in questo caso. Scegline una che sia consistente, segua le regole delle dipendenze di AngularJS e sia facile da manutenere e scalabile. + Nota: Questa è una strategia per la consistenza. Ci sono diverse buone opzioni in questo caso. Scegline una che sia consistente, segua le regole delle dipendenze di Angular e sia facile da manutenere e scalare. > La mia struttura varia leggermente tra progetti ma tutti seguono queste linee guida per la strutturazione e modularità. L'implementazione può variare in relazione alle funzionalità ed al team. In altre parole, non ti bloccare su una struttura che sia esattamente uguale ma giustifica la tua struttura tenendo a mente l'uso di consistenza, manutenibilità ed efficienza. - > In una applicazione piccola, si può considerare di mettere tutte le dipendenze condivise nel modulo dell'app dove i moduli delle funzionalità non hanno dipendenze dirette. Ciò rende più semplice mantenere l'applicazione più piccola ma rende più difficile riutilizzare i moduli fuori dell'applicazione stessa. + > In una applicazione piccola, si può considerare di mettere tutte le dipendenze condivise nel modulo dell'app dove i moduli delle funzionalità non hanno dipendenze dirette. Ciò rende semplice mantenere l'applicazione più piccola ma rende più difficile riutilizzare i moduli fuori dell'applicazione stessa. **[Torna all'inizio](#tavola-dei-contenuti)** From 8d6c5ee2c8f055ce79bf78907c1b10dc0ecd7677 Mon Sep 17 00:00:00 2001 From: angelochiello Date: Mon, 18 May 2015 20:46:06 +0200 Subject: [PATCH 297/567] [it-IT] Complete Review This is a complete review. It is reviewed till the end. --- i18n/it-IT.md | 187 +++++++++++++++++++++++++++++++++++++------------- 1 file changed, 138 insertions(+), 49 deletions(-) diff --git a/i18n/it-IT.md b/i18n/it-IT.md index 7bc3b97c..f5d80528 100644 --- a/i18n/it-IT.md +++ b/i18n/it-IT.md @@ -2353,16 +2353,16 @@ Invece usa la più semplice sintassi setter. ### $timeout e $interval ###### [Stile [Y181](#stile-y181)] - - Usa [`$timeout`](https://docs.angularjs.org/api/ng/service/$timeout) e [`$interval`](https://docs.angularjs.org/api/ng/service/$interval) al posto di `setTimeout` e `setInterval` . + - Usa [`$timeout`](https://docs.angularjs.org/api/ng/service/$timeout) e [`$interval`](https://docs.angularjs.org/api/ng/service/$interval) al posto di `setTimeout` e `setInterval`. - *Perché?*: Questi servizi sono gestiti da Angular e più facilmente testabili e trattano il ciclo di digest di AngularJS quindi tengono il data binding sincronizzato. + *Perché?*: Questi servizi sono gestiti da Angular e più facilmente testabili e gestiscono il ciclo di digest di Angular così da tenere sincronizzato il data binding. **[Torna all'inizio](#tavola-dei-contenuti)** ## Test -Gli unit test aiutano a mantenere il codice più chiaro, perciò ho incluso alcune mie raccomandazioni fondamentali per lo unit testing con link e ulteriori informazioni. +Gli unit test aiutano a mantenere il codice più chiaro, perciò ho incluso alcune mie raccomandazioni per le fondamenta dello unit testing con link per ulteriori dettagli. -### Scrivi i test con le Storie +### Scrivi test che abbiano storie ###### [Stile [Y190](#stile-y190)] - Scrivi un set di test per ogni storia. Inizia con un test vuoto e riempilo fino a scrivere il codice per la storia. @@ -2386,7 +2386,7 @@ Gli unit test aiutano a mantenere il codice più chiaro, perciò ho incluso alcu //TODO ($httpBackend?) }); - // continuare + // così via ``` ### Librerie per i test @@ -2394,9 +2394,9 @@ Gli unit test aiutano a mantenere il codice più chiaro, perciò ho incluso alcu - Usa [Jasmine](http://jasmine.github.io/) oppure [Mocha](http://mochajs.org) per lo unit testing. - *Perché?*: Sia Jasmine che Mocha sono largamente utilizzati nella comunità di AngularJS. Entrambi son stabili, ben manutenuti e forniscono funzionalità solide per i test. + *Perché?*: Sia Jasmine che Mocha sono largamente utilizzati nella comunità di Angular. Entrambi son stabili, ben manutenuti e forniscono funzionalità solide per i test. - Nota: Usando Mocha, tieni in considerazione di usare anche una libreria di asserzione come [Chai](http://chaijs.com). + Nota: Usando Mocha, tieni in considerazione di usare anche una libreria di asserzione come [Chai](http://chaijs.com). Io preferisco Mocha. ### Esecutori di Test ###### [Stile [Y192](#stile-y192)] @@ -2407,7 +2407,7 @@ Gli unit test aiutano a mantenere il codice più chiaro, perciò ho incluso alcu *Perché?*: Karma si aggancia facilmente al tuo processo di Integrazione Continua da solo o attraverso Grunt o Gulp. - *Perché?*: Alcuni IDE cominciamo ad integrare Karma, come [WebStorm](http://www.jetbrains.com/webstorm/) e [Visual Studio](http://visualstudiogallery.msdn.microsoft.com/02f47876-0e7a-4f6c-93f8-1af5d5189225). + *Perché?*: Alcuni IDE cominciano ad integrarsi con Karma, come [WebStorm](http://www.jetbrains.com/webstorm/) e [Visual Studio](http://visualstudiogallery.msdn.microsoft.com/02f47876-0e7a-4f6c-93f8-1af5d5189225). *Perché?*: Karma lavora bene con leader di automazione di processo quali [Grunt](http://www.gruntjs.com) (con [grunt-karma](https://github.com/karma-runner/grunt-karma)) e [Gulp](http://www.gulpjs.com) (con [gulp-karma](https://github.com/lazd/gulp-karma)). @@ -2425,9 +2425,9 @@ Gli unit test aiutano a mantenere il codice più chiaro, perciò ho incluso alcu - Usa [PhantomJS](http://phantomjs.org/) per eseguire i test su un server. - *Perché?*: PhantomJS è un headless browser che aiuta l'esecuzione di test senza la necessità di un browser "visuale". Quindi non devi installare Chrome, Safari, IE o altri browser sul server. + *Perché?*: PhantomJS è un headless browser (browser senza interfaccia grafica) che aiuta l'esecuzione di test senza la necessità di un browser "visuale". Quindi non devi installare Chrome, Safari, IE o altri browser sul server. - Nota: Dovresti in ogni caso testare tutti i browser del tuo ambiente, come appropriato per il pubblico che è il target. + Nota: Dovresti in ogni caso testare tutti i browser nel tuo ambiente, come appropriato per il pubblico che ne è il target. ### Analisi del codice ###### [Stile [Y195](#stile-y195)] @@ -2436,10 +2436,10 @@ Gli unit test aiutano a mantenere il codice più chiaro, perciò ho incluso alcu *Perché?*: I test sono codice. JSHint può aiutare ad identificare problemi di qualità del codice che causano l’improprio funzionamento del test. -### Alleviare le regole sulle variabili globali di JSHint per i Test +### Alleviare le regole sulle variabili globali di JSHint per i test ###### [Stile [Y196](#stile-y196)] - - Rilassa le regole sul codice dei test per consentendoli per variabili globali comuni quali `describe` ed `expect`. + - Rilassa le regole sul codice dei test per consentire variabili globali comuni quali `describe` ed `expect`. *Perché?*: I tuoi test sono codice e richiedono al medesima attenzione e regole per la qualità del codice come tutto il resto del codice di produzione. Comunque, variabili globali usate dai framework di test, per esempio, possono essere rilassate includendole nelle specifiche dei test. @@ -2458,9 +2458,9 @@ Gli unit test aiutano a mantenere il codice più chiaro, perciò ho incluso alcu ### Organizzazione dei test ###### [Stile [Y197](#stile-y197)] - - Posiziona i file degli unit test vicino al codice del client. Posiziona le specifiche che coprono l'integrazione con il server o che testano più componenti in una cartella separata `tests`. + - Posiziona i file degli unit test (spec) vicino al codice del client. Posiziona le specifiche che coprono l'integrazione con il server o che testano più componenti in una cartella separata `tests`. - *Perché?*: Gli unit test hanno una correlazione diretta con un componente specifico e un file nei sogenti. + *Perché?*: Gli unit test hanno una correlazione diretta con un componente specifico e file nei sogenti. *Perché?*: È più semplice da tenere aggiornati dal momento che sono sempre a vista. Quando scrivi codice, sia che tu faccia TDD o fai i test durante o dopo lo sviluppo, le scpecifiche sono sempre di fianco e mai fuori dalla vista o dai pensieri, quindi è più probabile che siano aggiornati e ciò consente inoltre a mantenere una migliore copertura del codice. @@ -2489,9 +2489,9 @@ Gli unit test aiutano a mantenere il codice più chiaro, perciò ho incluso alcu ### Utilizzo ###### [Stile [Y210](#stile-y210)] - - Usa sfumate [animazioni con AngularJS](https://docs.angularjs.org/guide/animations) per fare transizioni tra stati per viste ed elementi visuali primari. Includi il [modulo ngAnimate](https://docs.angularjs.org/api/ngAnimate). Le 3 chiavi sono sfumate, dolci e continue. + - Usa sfumate [animazioni con Angular](https://docs.angularjs.org/guide/animations) per fare transizioni tra stati per viste ed elementi visuali primari. Includi il [modulo ngAnimate](https://docs.angularjs.org/api/ngAnimate). Le 3 chiavi sono sfumate, dolci e continue. - *Perché?*: Animazioni sfumate possono migliorare l'esperienza dell'utente (UX) quando usate in modo appropriato. + *Perché?*: Animazioni sfumate possono migliorare l'esperienza dell'utente quando usate in modo appropriato. *Perché?*: Animazioni sfumate possono migliorare la percezione di prestazioni nella transizione tra le viste. @@ -2500,7 +2500,7 @@ Gli unit test aiutano a mantenere il codice più chiaro, perciò ho incluso alcu - Usa animazioni che abbiano una durata breve. Generalmente parto con 300 ms e aggiusto finché non è appropriato. - *Perché?*: Long animations can have the reverse affect on User Experience and perceived performance by giving the appearance of a slow application. + *Perché?*: Animazioni lunghe possono avere l'effetto contrario sull'esperienza dell'utente e di percezzione delle prestazioni che danno il senso di una applicazione lenta. ### animate.css ###### [Stile [Y212](#stile-y212)] @@ -2513,7 +2513,7 @@ Gli unit test aiutano a mantenere il codice più chiaro, perciò ho incluso alcu *Perché?*: animate.css è ampiamente usato e testato. - Nota: Leggi questo [ottimo posto di Matias Niemelä sulle animazioni di AngularJS](http://www.yearofmoo.com/2013/08/remastered-animation-in-angularjs-1-2.html) + Nota: Leggi questo [ottimo post di Matias Niemelä sulle animazioni di Angular](http://www.yearofmoo.com/2013/08/remastered-animation-in-angularjs-1-2.html) **[Torna all'inizio](#tavola-dei-contenuti)** @@ -2524,13 +2524,13 @@ Gli unit test aiutano a mantenere il codice più chiaro, perciò ho incluso alcu - Se hai intenzione di produrre documentazione, usa la sintassi di [`jsDoc`](http://usejsdoc.org/) per documentare nomi di funzione, descrizione, parametri e ciò che ritorna. Usa `@namespace` e `@memberOf` per adattarlo alla stuttura della tua app. - *Perché?*: Puoi generare (e rigenerare) documentazione dal tuo codice, piuttosto che scriverlo partendo da zero. + *Perché?*: Puoi generare (e rigenerare) documentazione dal tuo codice, invece di scriverlo partendo da zero. - *Perché?*: Fornisce consistenza usando un tool industriale comune. + *Perché?*: Fornisce consistenza usando un tool comune nell'industria. ```javascript /** - * Factory di Logger + * Factory di Log * @namespace Factories */ (function() { @@ -2574,7 +2574,7 @@ Gli unit test aiutano a mantenere il codice più chiaro, perciò ho incluso alcu ### Usa un file di opzioni ###### [Stile [Y230](#stile-y230)] - - Usa JS Hint per spazzolare il tuo JavaScript ed assicurati di ritagliare il file di opzioni di JS Hint e di includerlo nel source control . Vedi la [documentazione di JS Hint](http://www.jshint.com/docs/) per i dettagli sulle opzioni. + - Usa JS Hint per spazzolare il tuo JavaScript ed assicurati di ritagliare il file di opzioni di JS Hint e di includerlo nel source control. Vedi la [documentazione di JS Hint](http://www.jshint.com/docs/) per i dettagli sulle opzioni. *Perché?*: Da un allerta iniziale prima di fare il commit di qualunque codice al source control. @@ -2739,9 +2739,9 @@ Gli unit test aiutano a mantenere il codice più chiaro, perciò ho incluso alcu ### Variabili globali delle terze parti ###### [Stile [Y240](#stile-y240)] - - Crea una costante di AngularJS per le variabili globali delle librerie di terze parti. + - Crea una costante di Angular per le variabili globali delle librerie di terze parti. - *Perché?*: Fornisce in modo per iniettare librerie di terze parte che altrimenti sarebbero globali. Questo migliore la testabilità permettendoti più facilmente di sapere quali sono le dipendenze dei tuoi componenti. Ti consente inoltre di fare un mock di queste dipendenze, dove ciò ha senso. + *Perché?*: Fornisce in modo per iniettare librerie di terze parte che altrimenti sarebbero globali. Questo migliore la testabilità del codice permettendoti più facilmente di sapere quali sono le dipendenze dei tuoi componenti. Ti consente inoltre di fare un mock di queste dipendenze, dove ciò ha senso. ```javascript // constants.js @@ -2761,11 +2761,11 @@ Gli unit test aiutano a mantenere il codice più chiaro, perciò ho incluso alcu - Usa constanti per i valori che non cambiano e che non provengono da un altro servizio. Quando le costanti sono utilizzate solo per un modulo che potrebbe essere riutilizzato in più applicazioni, metti le costanti in un file per modulo e nominalo come il modulo. Fintanto che tale necesstià non si presenti, tieni le constanti nel modulo principale in un file `constants.js`. - *Perché*: Un valore che potrebbe variare, anche non di frequente, dovrebbe essere recuperato da un servizio così che non sia necessario cambiare il sorgente. Per esempio, una URL per un servizio di accesso ai dati può essere messo in una costante ma un miglior posizionamento sarebbe quello di caricarlo da un web service. + *Perché*: Un valore che potrebbe variare, anche non di frequente, dovrebbe essere recuperato da un servizio così che non sia necessario cambiare il codice sorgente. Per esempio, una URL per un servizio di accesso ai dati può essere messo in una costante ma un miglior posizionamento sarebbe quello di caricarlo da un web service. *Perché?*: Le costanti possono essere iniettate in un componente di angular, provider inclusi. - *Perché?*: Quando una applicazione è separata in modulo che potrebbero essere usati in altre applicazioni, ogni modulo a se stante dovrebbe essere in grado di funzionare da solo ivi incluse ogni costante da cui dipende. + *Perché?*: Quando una applicazione è separata in moduli che potrebbero essere usati in altre applicazioni, ogni modulo dovrebbe essere in grado di funzionare a se stante ivi incluse ogni costante da cui dipende. ```javascript // Costanti usate dall'intera applicazione @@ -2785,12 +2785,12 @@ Gli unit test aiutano a mantenere il codice più chiaro, perciò ho incluso alcu **[Torna all'inizio](#tavola-dei-contenuti)** ## File Template e Snippet -Usa file template o snippet che ti aiutino a seguire stili e schemi consistentemente. Qui trovi alcuni template e/o snippet per alcuni degli editor per lo sviluppo wbe e IDE. +Usa file template o snippet che ti aiutino a seguire stili e schemi consistentemente. Qui trovi alcuni template e/o snippet per alcuni degli editor per lo sviluppo web e IDE. ### Sublime Text ###### [Stile [Y250](#stile-y250)] - - Snippet di AngularJS che seguono questi stili e linee guida. + - Snippet di Angular che seguono questi stili e linee guida. - Scarica gli [snippet di Angular per Sublime](assets/sublime-angular-snippets.zip?raw=true) - Mettili nella tua cartella Packages @@ -2799,9 +2799,11 @@ Usa file template o snippet che ti aiutino a seguire stili e schemi consistentem ```javascript ngcontroller // crea un controller Angular - ngdirective // crea una directive Angular - ngfactory // crea una factory Angular - ngmodule // crea un modulo Angular + ngdirective // crea una directive Angular + ngfactory // crea una factory Angular + ngmodule // crea un modulo Angular + ngservice // crea un servizio Angular + ngfilter // crea un filtro Angular ``` ### Visual Studio @@ -2816,9 +2818,9 @@ Usa file template o snippet che ti aiutino a seguire stili e schemi consistentem ### WebStorm ###### [Stile [Y252](#stile-y252)] - - Snippet di Angular JS e file di template che seguono queste linee guida. Le puoi importare dentro i tuoi settaggi di WebStorm: + - Snippet di Angular e file di template che seguono queste linee guida. Le puoi importare dentro i tuoi settaggi di WebStorm: - - Scarica i [file dei template e gli snippet diAngularJS per WebStorm](assets/webstorm-angular-file-template.settings.jar?raw=true) + - Scarica i [file dei template e gli snippet di Angular per WebStorm](assets/webstorm-angular-file-template.settings.jar?raw=true) - Apri WebStorm e vai al menù `File` - Scegli la voce di menù `Import Settings` - Seleziona il file e clicca `OK` @@ -2833,7 +2835,7 @@ Usa file template o snippet che ti aiutino a seguire stili e schemi consistentem ### Atom ###### [Stile [Y253](#stile-y253)] - - Snippet di Angular JS e file di template che seguono queste linee guida. + - Snippet di Angular e file di template che seguono queste linee guida. ``` apm install angularjs-styleguide-snippets ``` @@ -2856,8 +2858,8 @@ Usa file template o snippet che ti aiutino a seguire stili e schemi consistentem ### Brackets ###### [Stile [Y254](#stile-y254)] - - Snippet di Angular che seguono questi stili e linee guida. - + - Snippet per Angular che seguono questi stili e linee guida. + - Scarica gli [snippet di Angulare per Brackets](assets/brackets-angular-snippets.yaml?raw=true) - Brackets Extension manager ( File > Extension manager ) - Installa ['Brackets Snippets (by edc)'](https://github.com/chuyik/brackets-snippets) - Clicca sulla lampadina nel gutter destro in bracket @@ -2875,16 +2877,33 @@ Usa file template o snippet che ti aiutino a seguire stili e schemi consistentem ngapp // crea una impostazione di modulo Angular ngservice // crea un service Angular ngfilter // crea un filtro Angular - ngroute // crea un routeProvider Angular // Questi sono snippet parziali intesi per essere concatenati ngmodule // crea un getter di modulo Angular ngstate // crea una definizione di stato di UI Router Angular ngconfig // definisce un funzione per la fase di cofigurazione ngrun // definisce una funzione per la fase di esecuzione - ngwhen // definisce una route per il routeProvider + ngroute // definisce una ngRoute Angular con la definizione 'when' + ngtranslate // usa il service $translate con le proprie promesse ``` +### vim +###### [Style [Y255](#style-y255)] + + - Snippet di vim che seguono questi stili e linee guida. + + - Scarica gli [snippet vim per Angular](assets/vim-angular-snippets?raw=true) + - setta [neosnippet.vim](https://github.com/Shougo/neosnippet.vim) + - copia gli snippets nella directory snippet + + ```javascript + ngcontroller // crea un controller Angular + ngdirective // crea una directive Angular + ngfactory // crea una factory Angular + ngmodule // crea un modulo Angular + ngservice // crea un service Angular + ngfilter // crea un filter Angular + ``` **[Torna all'inizio](#tavola-dei-contenuti)** ## Generatore Yeoman @@ -2920,13 +2939,83 @@ Il routing del lato client è importante al fine di creare in flusso di navigazi - Usa il [Router AngularUI](http://angular-ui.github.io/ui-router/) per il routing del lato client. - *Perché?*: UI Router offre tutte le funzionalità del router di Angular più alcune funzionalità aggiuntive che includono orute nidificate e stati. + *Perché?*: UI Router offre tutte le funzionalità del router di Angular più alcune funzionalità aggiuntive che includono route nidificate e stati. *Perché?*: la sintassi è piuttosto simile a quella del router di Angular ed è facile migrare a UI Router. + + - Nota: Puoi usare un provider quale `routerHelperProvider` mostrato sotto per aiutarti a configurare gli stati tra i file durante la fase di esecuzione. + + ```javascript + // customers.routes.js + angular + .module('app.customers') + .run(appRun); + + /* @ngInject */ + function appRun(routerHelper) { + routerHelper.configureStates(getStates()); + } + + function getStates() { + return [ + { + state: 'customer', + config: { + abstract: true, + template: '', + url: '/customer' + } + } + ]; + } + ``` + + ```javascript + // routerHelperProvider.js + angular + .module('blocks.router') + .provider('routerHelper', routerHelperProvider); + + routerHelperProvider.$inject = ['$locationProvider', '$stateProvider', '$urlRouterProvider']; + /* @ngInject */ + function routerHelperProvider($locationProvider, $stateProvider, $urlRouterProvider) { + /* jshint validthis:true */ + this.$get = RouterHelper; + + $locationProvider.html5Mode(true); + + RouterHelper.$inject = ['$state']; + /* @ngInject */ + function RouterHelper($state) { + var hasOtherwise = false; + + var service = { + configureStates: configureStates, + getStates: getStates + }; + + return service; + + /////////////// + + function configureStates(states, otherwisePath) { + states.forEach(function(state) { + $stateProvider.state(state.state, state.config); + }); + if (otherwisePath && !hasOtherwise) { + hasOtherwise = true; + $urlRouterProvider.otherwise(otherwisePath); + } + } + + function getStates() { return $state.get(); } + } + } + ``` ###### [Stile [Y271](#stile-y271)] - - Definisci le route per le view nel modulo dove queste esisteono. Ogni modulo dovrebbe contenere le route per le view del modulo. + - Definisci le route per le view nel modulo dove queste esistono. Ogni modulo dovrebbe contenere le route per le view del modulo. *Perché?*: Ogni modulo dovrebbe essere a se stante. @@ -2937,13 +3026,13 @@ Il routing del lato client è importante al fine di creare in flusso di navigazi **[Torna all'inizio](#tavola-dei-contenuti)** ## Automazione dei processi -Usa [Gulp](http://gulpjs.com) o [Grunt](http://gruntjs.com) per la creazione di processi automatizzati. Gulp si basa su codive sopra configurazione mentre Grunt si basa su configurazione sopre codice. Personalmente preferisco Gulp poiché lo percepisco come più facile da leggere e scrivere ma entrambi sono eccellenti. +Usa [Gulp](http://gulpjs.com) o [Grunt](http://gruntjs.com) per la creazione di processi automatizzati. Gulp si basa su "codice sopra configurazione" mentre Grunt si basa su "configurazione sopra codice". Personalmente preferisco Gulp poiché lo percepisco come più facile da leggere e scrivere ma entrambi sono eccellenti. > Impara di più su Gulp per l'automazione dei processi e pattern in mio [corso Pluralsight su Gulp](http://jpapa.me/gulpps) (in inglese) ###### [Stile [Y400](#stile-y400)] - - Usa l'automazione dei processi per elencare i file delle definizioni dei modili `*.module.js` prima di qualunque altro file JavaScript dell'applicazione. + - Usa l'automazione dei processi per elencare i file delle definizioni dei moduli `*.module.js` prima di qualunque altro file JavaScript dell'applicazione. *Perché?*: Angular necessita delle definizione del modulo da essere registrate prima di essere usati. @@ -2965,25 +3054,25 @@ Usa [Gulp](http://gulpjs.com) o [Grunt](http://gruntjs.com) per la creazione di ###### [Stile [Y420](#stile-y420)] - - Evita l'utilizzo di filtri per la scansione di tutte le proprietà di un grafico di un oggetto complesso. Usa i filtri per selezionare le proprietà. + - Evita l'utilizzo di filtri per la scansione di tutte le proprietà del grafo di un oggetto complesso. Usa i filtri per selezionare le proprietà. - *Perché?*:I filtri possono facilmente essere abusati ed avere un impatto negativo sulle prestazioni se non usati con saggezza, per esempio quando i filtri hanno come soggetto un grafico di un ogetto largo e profondo. + *Perché?*: I filtri possono facilmente essere abusati ed avere un impatto negativo sulle prestazioni se non usati con saggezza, per esempio quando i filtri hanno come soggetto il grafo di un oggetto largo e profondo. **[Torna all'inizio](#tavola-dei-contenuti)** -## Documentazione di AngularJS -For anything else, API reference, check the [Angular documentation](//docs.angularjs.org/api). +## Documentazione di Angular +Per qualunque altra cosa, riferimenti alle API, controlla la [documentazione di Angular](//docs.angularjs.org/api). ## Contribuire -Apri prima una "issue" per discutere potenziali cambiamenti/aggiunte. Se hai delle domande relative alla guida, sentiti libero di porle come "issue" nel repository. Se trovi un errore di scrittura, crea una pull request. L'idea è quella di tenere aggiornato il contenuto e usare le funzioni native di Github per aiutare nel racconto della storia con issue e pull request che sono tutte ricercabili via Google. Perché? Il caso vuole che se hai una domanda, qualcun altro l'abbia pure. Puoi trovare di più qui su come contribuire. +Apri prima una "issue" per discutere potenziali cambiamenti/aggiunte. Se hai domande relative alla guida, sentiti libero di porle come "issue" nel repository. Se trovi un errore di scrittura, crea una pull request. L'idea è quella di tenere aggiornato il contenuto e usare le funzioni native di Github per aiutare nel racconto della storia con issue e pull request che sono tutte ricercabili via Google. Perché? Il caso vuole che se hai una domanda, qualcun altro l'abbia pure. Puoi trovare di più su come contribuire qui. *Contribuendo a questo repository sei d'accordo a rendere il tuo contenuto soggetto alla licenza di questo repository* ### Processo - 1. Discuti i cambiamenti in un Issue. - 2. Apri una Pull Request, fai riferimento all issue e spiega i cambiamenti e perché questi aggiungono valore. + 1. Discuti i cambiamenti in un issue di GitHub. + 2. Apri una Pull Request, fai riferimento all issue e specifica i cambiamenti e perché questi aggiungono valore. 3. La Pull Request sarà vagliata e quindi fatto un merge o declinata. ## Licenza From 7e61440028dd66a3febe47d9ea41ca60921e8886 Mon Sep 17 00:00:00 2001 From: angelochiello Date: Mon, 18 May 2015 20:50:36 +0200 Subject: [PATCH 298/567] [it-IT] Updated as PR #403 --- i18n/it-IT.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/i18n/it-IT.md b/i18n/it-IT.md index f5d80528..2f87a364 100644 --- a/i18n/it-IT.md +++ b/i18n/it-IT.md @@ -2475,8 +2475,8 @@ Gli unit test aiutano a mantenere il codice più chiaro, perciò ho incluso alcu ``` /src/client/app/customers/customer-detail.controller.js /customer-detail.controller.spec.js + /customers.controller.js /customers.controller.spec.js - /customers.controller-detail.spec.js /customers.module.js /customers.route.js /customers.route.spec.js From 65d82afbbef7c757c5bc258b141e4be81f930aa2 Mon Sep 17 00:00:00 2001 From: angelochiello Date: Mon, 18 May 2015 20:53:29 +0200 Subject: [PATCH 299/567] [it-IT] Updated as PR #401 --- i18n/it-IT.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/i18n/it-IT.md b/i18n/it-IT.md index 2f87a364..6d9ee988 100644 --- a/i18n/it-IT.md +++ b/i18n/it-IT.md @@ -628,7 +628,7 @@ Invece usa la più semplice sintassi setter. - Quando un controller deve essere accoppiato ad una view ed un componente può essere riutilizzato da altri controller o view, definisci i controller insieme alle loro route. - Nota: Se una View è caricata attraverso altri mezzi che una route, allora usa la sintassi `ng-controller="Avengers as vm"`. + Nota: Se una View è caricata attraverso altri mezzi che una route, allora usa la sintassi `ng-controller="AvengersController as avengers"`. *Perché?*: Accoppiare il controller in una route consente a route diverse di invocare diversi accoppiamenti di controller e view. Quando i controller sono assegnati in una view usando [`ng-controller`](https://docs.angularjs.org/api/ng/directive/ngController) quella view sarà sempre associata al medesimo controller. @@ -650,7 +650,7 @@ Invece usa la più semplice sintassi setter. ```html -
+
``` From d9850315f99fced54406df80f58d59eb0eb4e299 Mon Sep 17 00:00:00 2001 From: angelochiello Date: Mon, 18 May 2015 20:55:31 +0200 Subject: [PATCH 300/567] [it-IT] Updated as PR #399 --- i18n/it-IT.md | 1 - 1 file changed, 1 deletion(-) diff --git a/i18n/it-IT.md b/i18n/it-IT.md index 6d9ee988..4a6d4a79 100644 --- a/i18n/it-IT.md +++ b/i18n/it-IT.md @@ -2723,7 +2723,6 @@ Gli unit test aiutano a mantenere il codice più chiaro, perciò ho incluso alcu "disallowCommaBeforeLineBreak": null, "disallowDanglingUnderscores": null, "disallowEmptyBlocks": null, - "disallowMultipleLineStrings": null, "disallowTrailingComma": null, "requireCommaBeforeLineBreak": null, "requireDotNotation": null, From 7b4a3f495a553da08072996a0b64fd8395d20c89 Mon Sep 17 00:00:00 2001 From: angelochiello Date: Mon, 18 May 2015 20:56:53 +0200 Subject: [PATCH 301/567] [it-IT] Updated as PR #394 --- i18n/it-IT.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/i18n/it-IT.md b/i18n/it-IT.md index 4a6d4a79..75153391 100644 --- a/i18n/it-IT.md +++ b/i18n/it-IT.md @@ -621,7 +621,7 @@ Invece usa la più semplice sintassi setter. - Definisci un controller per vista e prova a non riutilizzare il controller per altre view. Piuttosto, sposta la logica riutilizzabile alle factory e mantieni il controller semplice ed a fuoco sulla propria view. - *Perché?*: Riutilizzare i controller con diverse view è precario e sono necessari dei buoni test end to end (e2e) per assicurarne la stabilità in applicazioni su larga scala. + *Perché?*: Riutilizzare i controller con diverse view è precario e sono necessari dei buoni test end-to-end (e2e) per assicurarne la stabilità in applicazioni su larga scala. ### Assegnazione dei Controller ###### [Stile [Y038](#stile-y038)] From 5cf13c80420c660b003d8095e3275dbdc9b8f661 Mon Sep 17 00:00:00 2001 From: angelochiello Date: Mon, 18 May 2015 21:00:16 +0200 Subject: [PATCH 302/567] [it-IT] Updated as PR #393 --- i18n/it-IT.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/i18n/it-IT.md b/i18n/it-IT.md index 75153391..1914084a 100644 --- a/i18n/it-IT.md +++ b/i18n/it-IT.md @@ -2177,7 +2177,7 @@ Invece usa la più semplice sintassi setter. ![Struttura dell'App di Esempio](https://raw.githubusercontent.com/johnpapa/angularjs-styleguide/master/assets/modularity-2.png) - Nota: Non utilizzare una strutturazione del tipo cartella-per-tipo. Questo richiede spostarsi tra molte cartelle quando si lavora su una funzionalità e diventa rapidamente scomodo quando l'app cresce di 5, 10 o più di 25 tra view e controller (ed altre funzionalità), per cui è più difficile rispetto alla localizzazione basata su cartella-per-funzionalità. + Nota: Non usare una strutturazione del tipo cartella-per-tipo per la tua app. Questo richiede spostarsi tra molte cartelle quando si lavora su una funzionalità e diventa rapidamente scomodo quando l'app cresce di 5, 10 o più di 25 tra view e controller (ed altre funzionalità), per cui è più difficile rispetto alla localizzazione basata su cartella-per-funzionalità. ```javascript /* From 678dbd53b0ae7e5176f78332e239f825d6454c69 Mon Sep 17 00:00:00 2001 From: angelochiello Date: Mon, 18 May 2015 21:05:05 +0200 Subject: [PATCH 303/567] [it-IT] Uniform translation for snippets Uniform translation for snippet's initial sentences. --- i18n/it-IT.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/i18n/it-IT.md b/i18n/it-IT.md index 1914084a..ec6576f0 100644 --- a/i18n/it-IT.md +++ b/i18n/it-IT.md @@ -2789,7 +2789,7 @@ Usa file template o snippet che ti aiutino a seguire stili e schemi consistentem ### Sublime Text ###### [Stile [Y250](#stile-y250)] - - Snippet di Angular che seguono questi stili e linee guida. + - Snippet Angular che seguono questi stili e linee guida. - Scarica gli [snippet di Angular per Sublime](assets/sublime-angular-snippets.zip?raw=true) - Mettili nella tua cartella Packages @@ -2817,7 +2817,7 @@ Usa file template o snippet che ti aiutino a seguire stili e schemi consistentem ### WebStorm ###### [Stile [Y252](#stile-y252)] - - Snippet di Angular e file di template che seguono queste linee guida. Le puoi importare dentro i tuoi settaggi di WebStorm: + - Snippet Angular e file di template che seguono queste linee guida. Le puoi importare dentro i tuoi settaggi di WebStorm: - Scarica i [file dei template e gli snippet di Angular per WebStorm](assets/webstorm-angular-file-template.settings.jar?raw=true) - Apri WebStorm e vai al menù `File` @@ -2834,7 +2834,7 @@ Usa file template o snippet che ti aiutino a seguire stili e schemi consistentem ### Atom ###### [Stile [Y253](#stile-y253)] - - Snippet di Angular e file di template che seguono queste linee guida. + - Snippet Angular e file di template che seguono queste linee guida. ``` apm install angularjs-styleguide-snippets ``` @@ -2857,7 +2857,7 @@ Usa file template o snippet che ti aiutino a seguire stili e schemi consistentem ### Brackets ###### [Stile [Y254](#stile-y254)] - - Snippet per Angular che seguono questi stili e linee guida. + - Snippet Angular che seguono questi stili e linee guida. - Scarica gli [snippet di Angulare per Brackets](assets/brackets-angular-snippets.yaml?raw=true) - Brackets Extension manager ( File > Extension manager ) - Installa ['Brackets Snippets (by edc)'](https://github.com/chuyik/brackets-snippets) From 5d7ef814f25e8fc3f0b879afc4cf86fda5ae48ad Mon Sep 17 00:00:00 2001 From: angelochiello Date: Mon, 18 May 2015 21:10:34 +0200 Subject: [PATCH 304/567] [it-IT] Updated as PR #370 --- i18n/it-IT.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/i18n/it-IT.md b/i18n/it-IT.md index ec6576f0..27ea319c 100644 --- a/i18n/it-IT.md +++ b/i18n/it-IT.md @@ -1448,7 +1448,7 @@ Invece usa la più semplice sintassi setter. }); } - function moviePrepService(movieService) { + function moviesPrepService(movieService) { return movieService.getMovies(); } @@ -1589,13 +1589,13 @@ Invece usa la più semplice sintassi setter. controller: 'Avengers', controllerAs: 'vm', resolve: { - moviesPrepService: moviePrepService + moviesPrepService: moviesPrepService } }); } - moviePrepService.$inject = ['movieService']; - function moviePrepService(movieService) { + moviesPrepService.$inject = ['movieService']; + function moviesPrepService(movieService) { return movieService.getMovies(); } ``` From f22a63878532d3c86eb460381d6c51f6762408f0 Mon Sep 17 00:00:00 2001 From: Felipe de Lorenzzi Date: Fri, 22 May 2015 14:06:46 -0300 Subject: [PATCH 305/567] Fix 'De volta ao topo' missing character --- i18n/PT-BR.md | 48 ++++++++++++++++++++++++------------------------ 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/i18n/PT-BR.md b/i18n/PT-BR.md index 5cd3e353..4b159ed4 100644 --- a/i18n/PT-BR.md +++ b/i18n/PT-BR.md @@ -110,7 +110,7 @@ ou *Responsabilidade Única* function someFactory() { } ``` -**[⬆ De volta ao topo ⬆](#tabela-de-conte%C3%BAdo)** +**[De volta ao topo](#tabela-de-conte%C3%BAdo)** ## IIFE ### JavaScript Closures @@ -175,7 +175,7 @@ ou *Responsabilidade Única* - **Nota**: IIFE impede que códigos de teste alcancem membros privados como expressões regulares ou funções auxiliares que são frequentemente boas para testes unitários. Entretanto, você pode testá-las através de membros acessíveis ou expondo-os pelo próprio componente. Por exemplo, colocando funções auxiliares, expressões regulares ou constantes em sua própria *factory* ou constante. -**[⬆ De volta ao topo ⬆](#tabela-de-conte%C3%BAdo)** +**[De volta ao topo](#tabela-de-conte%C3%BAdo)** ## Modules ou *Módulos* @@ -286,7 +286,7 @@ ou *Funções Nomeadas vs Funções Anônimas* function logger() { } ``` -**[⬆ De volta ao topo ⬆](#tabela-de-conte%C3%BAdo)** +**[De volta ao topo](#tabela-de-conte%C3%BAdo)** ## Controllers ou *Controladores* @@ -643,7 +643,7 @@ ou *Controladores*
``` -**[⬆ De volta ao topo ⬆](#tabela-de-conte%C3%BAdo)** +**[De volta ao topo](#tabela-de-conte%C3%BAdo)** ## Services ou *Serviços* @@ -682,7 +682,7 @@ ou *Serviços* } ``` -**[⬆ De volta ao topo ⬆](#tabela-de-conte%C3%BAdo)** +**[De volta ao topo](#tabela-de-conte%C3%BAdo)** ## Factories ou *Fábricas* @@ -853,7 +853,7 @@ ou *Declarações de função para esconder detalhes de implementação* } ``` -**[⬆ De volta ao topo ⬆](#tabela-de-conte%C3%BAdo)** +**[De volta ao topo](#tabela-de-conte%C3%BAdo)** ## Data Services ou *Serviços de dados* @@ -979,7 +979,7 @@ ou *Retorne uma promessa de chamadas de dados* } ``` - **[⬆ De volta ao topo ⬆](#tabela-de-conte%C3%BAdo)** + **[De volta ao topo](#tabela-de-conte%C3%BAdo)** ## Directives ou *Diretivas* @@ -1213,7 +1213,7 @@ ou *Diretivas e "ControladorComo"*
min={{vm.min}}
``` -**[⬆ De volta ao topo ⬆](#tabela-de-conte%C3%BAdo)** +**[De volta ao topo](#tabela-de-conte%C3%BAdo)** ## Resolving Promises for a Controller ou *Resolvendo promessas para um controlador* @@ -1322,7 +1322,7 @@ ou *Resolução de promessas na rota* Nota: As dependências no código de exemplos do `movieService` não estão seguras para minificação. Para mais detalhes de como fazer o código seguro para minificação, veja as seções [injeção de dependência (dependency injection)](#manual-annotating-for-dependency-injection) e [minificação e anotação (minification and annotation)](#minification-and-annotation). -**[⬆ De volta ao topo ⬆](#tabela-de-conte%C3%BAdo)** +**[De volta ao topo](#tabela-de-conte%C3%BAdo)** ## Manual Annotating for Dependency Injection ou *Anotação Manual para Injeção de Dependência* @@ -1454,7 +1454,7 @@ ou *Identifique Dependências do Resolvedor de Rotas Manualmente* } ``` -**[⬆ De volta ao topo ⬆](#tabela-de-conte%C3%BAdo)** +**[De volta ao topo](#tabela-de-conte%C3%BAdo)** ## Minification and Annotation ou *Minificação e Anotação* @@ -1564,7 +1564,7 @@ ou *Minificação e Anotação* ``` -**[⬆ De volta ao topo ⬆](#tabela-de-conte%C3%BAdo)** +**[De volta ao topo](#tabela-de-conte%C3%BAdo)** ## Exception Handling ou *Tratamento de exceção* @@ -1671,7 +1671,7 @@ ou *Coletores de exceção* } ``` -**[⬆ De volta ao topo ⬆](#tabela-de-conte%C3%BAdo)** +**[De volta ao topo](#tabela-de-conte%C3%BAdo)** ## Nomenclatura @@ -1886,7 +1886,7 @@ ou *Coletores de exceção* - Separate route configuration into its own file. Examples might be `app.route.js` for the main module and `admin.route.js` for the `admin` module. Even in smaller apps I prefer this separation from the rest of the configuration. An alternative is a longer name such as `admin.config.route.js`. -**[⬆ De volta ao topo ⬆](#tabela-de-conte%C3%BAdo)** +**[De volta ao topo](#tabela-de-conte%C3%BAdo)** ## Application Structure LIFT Principle ### LIFT @@ -1944,7 +1944,7 @@ ou *Coletores de exceção* *Why?*: Being DRY is important, but not crucial if it sacrifices the others in LIFT, which is why I call it T-DRY. I don’t want to type session-view.html for a view because, well, it’s obviously a view. If it is not obvious or by convention, then I name it. -**[⬆ De volta ao topo ⬆](#tabela-de-conte%C3%BAdo)** +**[De volta ao topo](#tabela-de-conte%C3%BAdo)** ## Application Structure @@ -2053,7 +2053,7 @@ ou *Coletores de exceção* topnav.html ``` -**[⬆ De volta ao topo ⬆](#tabela-de-conte%C3%BAdo)** +**[De volta ao topo](#tabela-de-conte%C3%BAdo)** ## Modularity @@ -2107,7 +2107,7 @@ ou *Coletores de exceção* > My structures vary slightly between projects but they all follow these guidelines for structure and modularity. The implementation may vary depending on the features and the team. In other words, don't get hung up on an exact like-for-like structure but do justify your structure using consistency, maintainability, and efficiency in mind. -**[⬆ De volta ao topo ⬆](#tabela-de-conte%C3%BAdo)** +**[De volta ao topo](#tabela-de-conte%C3%BAdo)** ## Angular $ Wrapper Services @@ -2123,7 +2123,7 @@ ou *Coletores de exceção* *Why?*: These services are wrapped by Angular and more easily testable and handle AngularJS's digest cycle thus keeping data binding in sync. -**[⬆ De volta ao topo ⬆](#tabela-de-conte%C3%BAdo)** +**[De volta ao topo](#tabela-de-conte%C3%BAdo)** ## Testing Testes unitários ajudam a manter o código limpo, tal como, eu inclui algumas recomendações de fundamentos para testes unitários com links para mais informações. @@ -2208,7 +2208,7 @@ Testes unitários ajudam a manter o código limpo, tal como, eu inclui algumas r ![Testing Tools](https://raw.githubusercontent.com/johnpapa/angularjs-styleguide/master/assets/testing-tools.png) -**[⬆ De volta ao topo ⬆](#tabela-de-conte%C3%BAdo)** +**[De volta ao topo](#tabela-de-conte%C3%BAdo)** ## Animations @@ -2238,7 +2238,7 @@ Testes unitários ajudam a manter o código limpo, tal como, eu inclui algumas r Note: See this [great post by Matias Niemelä on AngularJS animations](http://www.yearofmoo.com/2013/08/remastered-animation-in-angularjs-1-2.html) -**[⬆ De volta ao topo ⬆](#tabela-de-conte%C3%BAdo)** +**[De volta ao topo](#tabela-de-conte%C3%BAdo)** ## Comments @@ -2289,7 +2289,7 @@ Testes unitários ajudam a manter o código limpo, tal como, eu inclui algumas r })(); ``` -**[⬆ De volta ao topo ⬆](#tabela-de-conte%C3%BAdo)** +**[De volta ao topo](#tabela-de-conte%C3%BAdo)** ## JS Hint @@ -2365,7 +2365,7 @@ Testes unitários ajudam a manter o código limpo, tal como, eu inclui algumas r } ``` -**[⬆ De volta ao topo ⬆](#tabela-de-conte%C3%BAdo)** +**[De volta ao topo](#tabela-de-conte%C3%BAdo)** ## Constants @@ -2391,7 +2391,7 @@ Testes unitários ajudam a manter o código limpo, tal como, eu inclui algumas r })(); ``` -**[⬆ De volta ao topo ⬆](#tabela-de-conte%C3%BAdo)** +**[De volta ao topo](#tabela-de-conte%C3%BAdo)** ## File Templates and Snippets Use file templates or snippets to help follow consistent styles and patterns. Here are templates and/or snippets for some of the web development editors and IDEs. @@ -2436,7 +2436,7 @@ Use file templates or snippets to help follow consistent styles and patterns. He ng-m // creates an Angular module ``` -**[⬆ De volta ao topo ⬆](#tabela-de-conte%C3%BAdo)** +**[De volta ao topo](#tabela-de-conte%C3%BAdo)** ## AngularJS docs For anything else, API reference, check the [Angular documentation](//docs.angularjs.org/api). @@ -2479,4 +2479,4 @@ 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. -**[⬆ De volta ao topo ⬆](#tabela-de-conte%C3%BAdo)** +**[De volta ao topo](#tabela-de-conte%C3%BAdo)** From 0d3f363a0a70bb7eba11b5e01524a6c3b62806d8 Mon Sep 17 00:00:00 2001 From: Felipe de Lorenzzi Date: Fri, 22 May 2015 14:18:49 -0300 Subject: [PATCH 306/567] Fix 'Naming' session hyperlink --- i18n/PT-BR.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/i18n/PT-BR.md b/i18n/PT-BR.md index 4b159ed4..36ecd0b2 100644 --- a/i18n/PT-BR.md +++ b/i18n/PT-BR.md @@ -1673,7 +1673,8 @@ ou *Coletores de exceção* **[De volta ao topo](#tabela-de-conte%C3%BAdo)** -## Nomenclatura +## Naming +ou *Nomenclatura* ### Diretrizes de Nomenclatura From e64fecd5784884998684a5efc9136f71cb9251b0 Mon Sep 17 00:00:00 2001 From: Felipe de Lorenzzi Date: Fri, 22 May 2015 14:49:31 -0300 Subject: [PATCH 307/567] Fix 'Router errors' session --- i18n/PT-BR.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/i18n/PT-BR.md b/i18n/PT-BR.md index 36ecd0b2..79cdf680 100644 --- a/i18n/PT-BR.md +++ b/i18n/PT-BR.md @@ -1642,7 +1642,8 @@ ou *Coletores de exceção* ``` ### Route Errors - - Gerencie e log todos os erros de routing utilizando o [`$routeChangeError`](https://docs.angularjs.org/api/ngRoute/service/$route#$routeChangeError). + + - Gerencie e log todos os erros de routing utilizando o [`$routeChangeError`](https://docs.angularjs.org/api/ngRoute/service/$route#$routeChangeError). *Por que?*: Fornece uma maneira consistente de gerenciar erros relacionados a routing. From c05e9faf981c0ee67af5dd27cd9bd0e08968add7 Mon Sep 17 00:00:00 2001 From: Felipe de Lorenzzi Date: Fri, 22 May 2015 15:02:21 -0300 Subject: [PATCH 308/567] Translate 'Naming' session --- i18n/PT-BR.md | 81 ++++++++++++++++++++++++++++----------------------- 1 file changed, 44 insertions(+), 37 deletions(-) diff --git a/i18n/PT-BR.md b/i18n/PT-BR.md index 79cdf680..f6cfc6ac 100644 --- a/i18n/PT-BR.md +++ b/i18n/PT-BR.md @@ -1688,6 +1688,7 @@ ou *Nomenclatura* *Por que?*: As convenções de nomenclatura deveriam simplesmente te ajudar a encontrar trechos do seu código mais rápido e torná-lo mais fácil de se entender. ### Feature File Names +ou *Nome para funcionalidades* - Use nomes consistentes para todos os componentes seguindo um padrão que descreve a funcionalidade do componente e, em seguida, (opcionalmente) o seu tipo. Meu padrão recomendado é `feature.type.js`. @@ -1697,7 +1698,7 @@ ou *Nomenclatura* ```javascript /** - * common options + * opções comuns */ // Controllers @@ -1713,7 +1714,7 @@ ou *Nomenclatura* ```javascript /** - * recommended + * recomendado */ // controllers @@ -1746,7 +1747,7 @@ ou *Nomenclatura* ```javascript /** - * recommended + * recomendado */ // Controllers avengers.js @@ -1754,16 +1755,17 @@ ou *Nomenclatura* ``` ### Test File Names +ou *Nome para aquivos de testes* - - Name test specifications similar to the component they test with a suffix of `spec`. - - *Why?*: Provides a consistent way to quickly identify components. + - Nomeie as especificações de testes de forma similar aos componentes que elas testam, com o sufixo `spec`. + + *Por que?*: Fornece um modo consistente para identificar rapidamente os componentes. - *Why?*: Provides pattern matching for [karma](http://karma-runner.github.io/) or other test runners. + *Por que?*: Fornece padrões de correspondência para o [karma](http://karma-runner.github.io/) ou outros test runners. ```javascript /** - * recommended + * recomendado */ avengers.controller.spec.js logger.service.spec.js @@ -1772,16 +1774,17 @@ ou *Nomenclatura* ``` ### Controller Names +ou *Nome para controllers* - - Use consistent names for all controllers named after their feature. Use UpperCamelCase for controllers, as they are constructors. - - *Why?*: Provides a consistent way to quickly identify and reference controllers. + - Use nomes consistentes para todos os controlers nomeados após as sua funcionalidade. Use UpperCamelCase para os controllers, assim como para seus construtores. + + *Por que?*: Fornece um modo consistente para identificar e referenciar os controllers. - *Why?*: UpperCamelCase is conventional for identifying object that can be instantiated using a constructor. + *Por que?*: O UpperCamelCase é o modo mais comum para identificar objetos que serão instanciados através de construtores. ```javascript /** - * recommended + * recomendado */ // avengers.controller.js @@ -1793,16 +1796,15 @@ ou *Nomenclatura* ``` ### Controller Name Suffix +ou *sufixo "Controllers"* - - Append the controller name with the suffix `Controller` or with no suffix. Choose 1, not both. - - *Why?*: The `Controller` suffix is more commonly used and is more explicitly descriptive. - - *Why?*: Omitting the suffix is more succinct and the controller is often easily identifiable even without the suffix. + - Complemente o nome do controller com ou sem o sufixo `Controller`. Escolha uma opção, não ambas. + *Por que?*: O sufixo `Controller` é mais usado e mais descritivo. + ```javascript /** - * recommended: Option 1 + * recomendado: Opção 1 */ // avengers.controller.js @@ -1815,7 +1817,7 @@ ou *Nomenclatura* ```javascript /** - * recommended: Option 2 + * recomendado: Opção 2 */ // avengers.controller.js @@ -1827,14 +1829,17 @@ ou *Nomenclatura* ``` ### Factory Names +ou *Nome para factory* - - Use consistent names for all factories named after their feature. Use camel-casing for services and factories. + - Use nomes consistentes para todas as factories nomeadas após sua funcionalidade. Use a conveção camelCase para services e factories, e evite prefixos com `$`. + + *Por que?*: Fornece um modo consistende de identificar e referenciar rapidamente as factories. - *Why?*: Provides a consistent way to quickly identify and reference factories. + *Por que?*: Evite colisão de nomes com factories e services pré-programadas que usam o prefixo `$`. ```javascript /** - * recommended + * recomendado */ // logger.service.js @@ -1846,14 +1851,15 @@ ou *Nomenclatura* ``` ### Directive Component Names +ou *Nome para directive* - - Use consistent names for all directives using camel-case. Use a short prefix to describe the area that the directives belong (some example are company prefix or project prefix). - - *Why?*: Provides a consistent way to quickly identify and reference components. - + - Use nomes consistentes para todas as directives usando a convenção camelCase. Use um prefixo curto para descrever a área a qual a directive pertence (como prefixo da compania ou do projeto). + + *Por que?*: Fornece um modo consistente de identificar e referenciar rapidamente os componentes. + ```javascript /** - * recommended + * recomendado */ // avenger.profile.directive.js @@ -1867,26 +1873,27 @@ ou *Nomenclatura* ``` ### Modules +ou *Módulos* - - When there are multiple modules, the main module file is named `app.module.js` while other dependent modules are named after what they represent. For example, an admin module is named `admin.module.js`. The respective registered module names would be `app` and `admin`. A single module app might be named `app.js`, omitting the module moniker. + - Quando há vários módulos, o arquivo principal deste módulo é nomeado `app.module.js`, enquanto os módulos dependentes são nomeados de acordo com o que eles representam. Por exemplo, um módulo admin é nomeado `admin.module.js`. Os nomes dos respectivos módulos registrados seriam `app` e `admin`. - *Why?*: An app with 1 module is named `app.js`. It is the app, so why not be super simple. - - *Why?*: Provides consistency for multiple module apps, and for expanding to large applications. + *Por que?*: Fornece consistência para múltiplos módulos, e para expansão para grandes aplicações. - *Why?*: Provides easy way to use task automation to load all module definitions first, then all other angular files (for bundling). + *Por que?*: Fornece um modo fácil para automação de tarefas, a fim de carregar todos as definições dos módulos em primeiro lugar, então os demais arquivos (empacotamento). ### Configuration +ou *Configuração* - - Separate configuration for a module into its own file named after the module. A configuration file for the main `app` module is named `app.config.js` (or simply `config.js`). A configuration for a module named `admin.module.js` is named `admin.config.js`. + - Separe a configuração do módulo em seu próprio arquivo, nomeado após o módulo. Um arquivo de configuração para o módulo principal `app` é nomeado `app.config.js` (ou simplesmente `config.js`). Uma configuração para o módulo `admin.module.js` é nomeada `admin.config.js`. - *Why?*: Separates configuration from module definition, components, and active code. + *Por que?*: Separe a configuração do módulo da definição, dos componentes e do código ativo. - *Why?*: Provides a identifiable place to set configuration for a module. + *Por que?*: Fornece um local identificável para definir as configurações de um módulo. ### Routes +ou *Rotas* - - Separate route configuration into its own file. Examples might be `app.route.js` for the main module and `admin.route.js` for the `admin` module. Even in smaller apps I prefer this separation from the rest of the configuration. An alternative is a longer name such as `admin.config.route.js`. + - Separe as configurações das rotas em seus próprios arquivos. Os exemplos podem ser `app.route.js` para o módulo princial, e `admin.route.js` para o módulo `admin`. Mesmo nas menores aplicações, prefiro esta separação das demais configurações. Uma alternativa é um nome mais longo, como `admin.config.route.js`. **[De volta ao topo](#tabela-de-conte%C3%BAdo)** From c5cf75022100efaed16dabd5ecf53bd7f4783b48 Mon Sep 17 00:00:00 2001 From: John Papa Date: Mon, 25 May 2015 20:00:38 -0400 Subject: [PATCH 309/567] updated German translation --- i18n/README.md | 15 ++++++++------- i18n/de-DE.md | 6 +++++- 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/i18n/README.md b/i18n/README.md index d20b97a6..ca99715e 100644 --- a/i18n/README.md +++ b/i18n/README.md @@ -5,13 +5,14 @@ The [original English version](http://jpapa.me/ngstyles) is the source of truth, *All translations are created by and maintained by the community.* 1. [French](fr-FR.md) -2. [Italian](it-IT.md) -3. [Japanese](ja-JP.md) -4. [Macedonian](mk-MK.md) -5. [Portuguese-Brazil](PT-BR.md) -6. [Russian](ru-RU.md) -7. [Simplified Chinese](zh-CN.md) -8. [Spanish](es-ES.md) +2. [German](de-DE.md) +3. [Italian](it-IT.md) +4. [Japanese](ja-JP.md) +5. [Macedonian](mk-MK.md) +6. [Portuguese-Brazil](PT-BR.md) +7. [Russian](ru-RU.md) +8. [Simplified Chinese](zh-CN.md) +9. [Spanish](es-ES.md) ## Contributing Language translations are welcomed and encouraged. The succcess of these translations depends on the community. I highly encourage new translation contributions and help to keep them up to date. diff --git a/i18n/de-DE.md b/i18n/de-DE.md index a1acd79b..4b836b2d 100644 --- a/i18n/de-DE.md +++ b/i18n/de-DE.md @@ -1,7 +1,11 @@ -# Angular Styleguide +# Angular Style Guide *Dogmatischer Angular Styleguide für Teams von John Papa [@john_papa](//twitter.com/john_papa)* +*Translated by [miseeger](https://github.com/miseeger)* + +>The [original English version](http://jpapa.me/ngstyles) is the source of truth, as it is maintained and updated first. + Sind Sie auf der Suche nach einem dogmatischen Styleguide zur Syntax, zu Konventionen und zur Struktur von Angular-Anwendungen, dann treten sie näher. Diese Vorlagen basieren auf meinen Erfahrungen mit [Angular](//angularjs.org), Präsentationen, [Pluralsight Trainingskursen](http://pluralsight.com/training/Authors/Details/john-papa) und der Arbeit in Teams. Der Zweck dieses Styleguides ist es, eine Anleitung für die Erstellung von Angular-Anwendungen bereitzustellen, indem ich die Konventionen, die ich nutze, zeige und - wichtiger als das - beschreibe, warum ich sie wähle. From b7848a1adfe31a84976e0fab6e3518c4becfa08f Mon Sep 17 00:00:00 2001 From: John Papa Date: Mon, 25 May 2015 20:03:22 -0400 Subject: [PATCH 310/567] fixed angularjs to angular --- i18n/de-DE.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/i18n/de-DE.md b/i18n/de-DE.md index 4b836b2d..e43b8717 100644 --- a/i18n/de-DE.md +++ b/i18n/de-DE.md @@ -12,7 +12,7 @@ Der Zweck dieses Styleguides ist es, eine Anleitung für die Erstellung von Angu >Wenn Sie diese Anleitung mögen, dann besuchen Sie meinen Kurs [Angular Patterns: Clean Code] (http://jpapa.me/ngclean) auf Pluralsight, der eine Begleitung zu dieser Anleitung dartellt. - [![AngularJs Patterns: Clean Code](https://raw.githubusercontent.com/johnpapa/angular-styleguide/master/assets/ng-clean-code-banner.png)](http://jpapa.me/ngclean) + [![Angular Patterns: Clean Code](https://raw.githubusercontent.com/johnpapa/angular-styleguide/master/assets/ng-clean-code-banner.png)](http://jpapa.me/ngclean) ## Außergewöhnliche Community and Anerkennung Arbeite niemals im leeren Raum. Ich finde, dass die Angular-Community eine unglaubliche Gruppe ist, die ihre Erfahrung mit Leidenschaft teilt. Also haben ein Freund und Angular-Experte, Todd Motto, und ich viele Vorlagen und Konventionen zusammengetragen. Bei den meisten sind wir uns einig, und bei ein paar sind wir verschiedener Meinung. Ich möchte Sie ermutigen, sich [Todd's Guidelines](https://github.com/toddmotto/angularjs-styleguide) anzusehen, um ein Gespühr für seinen Ansatz zu entwickeln und ihn vergleichen zu können. From b63830f82c5d21abde06cad0b2ebb89258869b31 Mon Sep 17 00:00:00 2001 From: John Papa Date: Mon, 25 May 2015 20:04:07 -0400 Subject: [PATCH 311/567] removed js --- i18n/es-ES.md | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/i18n/es-ES.md b/i18n/es-ES.md index af249df0..2edc626b 100644 --- a/i18n/es-ES.md +++ b/i18n/es-ES.md @@ -1,6 +1,6 @@ # Guía de estilo AngularJS -*Guía de estilos colaborativa de AngularJS para equipos por [@john_papa](//twitter.com/john_papa)* +*Guía de estilos colaborativa de Angular para equipos por [@john_papa](//twitter.com/john_papa)* *Translation by [Alberto Calleja](https://github.com/AlbertoImpl) and [Gilberto](https://github.com/ingilniero)* @@ -8,14 +8,14 @@ Si estás buscando una guía colaborativa sobre sintaxis, convenciones y estructura de aplicaciones con AngulRJS, este es el sitio. Estos estilos están basados en mi experiencia desarrollando con [AngularJS](//angularjs.org), persentaciones, [Cursos en Pluralsight](http://pluralsight.com/training/Authors/Details/john-papa) y trabajando en equipos. -El propósito de esta guía de estilos es proporcionar una guía de cómo construir aplicaciones con AngularJS enseñando convenciones que uso y, lo más importante, el porqué. +El propósito de esta guía de estilos es proporcionar una guía de cómo construir aplicaciones con Angular enseñando convenciones que uso y, lo más importante, el porqué. ->Si te gusta esta guía, echa un vistazo al curso de Pluralsight [AngularJS Patterns: Clean Code](http://jpapa.me/ngclean). +>Si te gusta esta guía, echa un vistazo al curso de Pluralsight [Angular Patterns: Clean Code](http://jpapa.me/ngclean). - [![AngularJs Patterns: Clean Code](https://raw.githubusercontent.com/johnpapa/angularjs-styleguide/master/assets/ng-clean-code-banner.png)](http://jpapa.me/ngclean) + [![Angular Patterns: Clean Code](https://raw.githubusercontent.com/johnpapa/angularjs-styleguide/master/assets/ng-clean-code-banner.png)](http://jpapa.me/ngclean) ## Asombrosa comunidad y créditos -Nunca trabajes solo. Personalmente, la comunidad de AngularJS es un increíble grupo apasionado por compartir experiencias. Como por ejemplo, mi amigo y experto en AngularJS Todd Motto, con el que he colaborado en muchos de los estilos y convenciones. Estamos de acuerdo en la mayoría, y en otras no. Te recomiendo que le eches un vistazo a [Todd's guidelines](https://github.com/toddmotto/angularjs-styleguide) para que le des sentido a esta guía y la compares. +Nunca trabajes solo. Personalmente, la comunidad de Angular es un increíble grupo apasionado por compartir experiencias. Como por ejemplo, mi amigo y experto en Angular Todd Motto, con el que he colaborado en muchos de los estilos y convenciones. Estamos de acuerdo en la mayoría, y en otras no. Te recomiendo que le eches un vistazo a [Todd's guidelines](https://github.com/toddmotto/angularjs-styleguide) para que le des sentido a esta guía y la compares. Muchos de los estilos han salido de las muchas sesiones de pair programming que [Ward Bell](http://twitter.com/wardbell) y yo hemos tenido. Aunque no siempre coincidimos, mi amigo Ward me ha ayudado con la última evolución de esta guía. @@ -55,7 +55,7 @@ Mientras que esta guía explica el *qué*, *por qué* y *cómo*, me resulta úti 1. [Generador de Yeoman](#generador-de-yeoman) 1. [Ruteo](#ruteo) 1. [Automatización de Tareas](#automatización-de-tareas) - 1. [AngularJS Docs](#angularjs-docs) + 1. [Angular Docs](#angularjs-docs) 1. [Contribuyendo](#contribuyendo) 1. [Licencia](#licencia) @@ -118,7 +118,7 @@ Mientras que esta guía explica el *qué*, *por qué* y *cómo*, me resulta úti ### Closures de JavaScript ###### [Style [Y010](#style-y010)] - - Envuelve los componentes AngularJS en una expresión de función que se invoca inmediatamente Immediately Invoked Function Expression (IIFE). + - Envuelve los componentes Angular en una expresión de función que se invoca inmediatamente Immediately Invoked Function Expression (IIFE). *¿Por qué?*: Una IIFE elimina las variables del scope global. Esto ayuda a prevenir que las variables y las declaraciones de funciones vivan más de lo esperado en el scope global, evitando así colisión de variables. @@ -687,7 +687,7 @@ Mientras que esta guía explica el *qué*, *por qué* y *cómo*, me resulta úti - Los Servicios son instanciados con un `new`, usan `this` para los métodos públicos y las variables. Ya que son muy similares a las factories, usa una factory en su lugar por consistencia. - Nota: [Todos los servicios AngularJS son singletons](https://docs.angularjs.org/guide/services). Esto significa que sólo hay una instancia de un servicio por inyector. + Nota: [Todos los servicios Angular son singletons](https://docs.angularjs.org/guide/services). Esto significa que sólo hay una instancia de un servicio por inyector. ```javascript // service @@ -731,7 +731,7 @@ Mientras que esta guía explica el *qué*, *por qué* y *cómo*, me resulta úti - Las Fábricas son singleton y devuelven un objeto que contiene las variables del servicio. - Nota: [Todos los servicios AngularJS son singletons](https://docs.angularjs.org/guide/services). + Nota: [Todos los servicios Angular son singletons](https://docs.angularjs.org/guide/services). ### Miembros accesibles Arriba ###### [Style [Y052](#style-y052)] @@ -1134,7 +1134,7 @@ Mientras que esta guía explica el *qué*, *por qué* y *cómo*, me resulta úti *¿Por qué?*: Mientras permitamos que una directiva sea usada como una clase, si esa directiva realmente está actuando como un elemento, tiene sentido que sea un elemento, o al menos un atributo. - Nota: En AngularJS 1.3+ EA es el valor por defecto + Nota: En Angular 1.3+ EA es el valor por defecto ```html @@ -1662,7 +1662,7 @@ Mientras que esta guía explica el *qué*, *por qué* y *cómo*, me resulta úti } ``` - > Nota: A partir de AngularJS 1.3 usa el párametro `ngStrictDi` de la directiva [`ngApp`](https://docs.angularjs.org/api/ng/directive/ngApp). Al presentarse el injector será creado en modo "strict-di" causando que la aplicación falle al invocar funciones que no usan explícitamente anotación de funciones (éstas podrían no estar minificadas en forma segura). Información para debugear será mostrada en la consola para ayudar a rastrear el código infractor. + > Nota: A partir de Angular 1.3 usa el párametro `ngStrictDi` de la directiva [`ngApp`](https://docs.angularjs.org/api/ng/directive/ngApp). Al presentarse el injector será creado en modo "strict-di" causando que la aplicación falle al invocar funciones que no usan explícitamente anotación de funciones (éstas podrían no estar minificadas en forma segura). Información para debugear será mostrada en la consola para ayudar a rastrear el código infractor. `` ### Usa Gulp o Grunt para ng-annotate @@ -1705,7 +1705,7 @@ Mientras que esta guía explica el *qué*, *por qué* y *cómo*, me resulta úti - Usa un decorador o [decorator](https://docs.angularjs.org/api/auto/service/$provide#decorator), en tiempo de configuración usando el servicio [`$provide`](https://docs.angularjs.org/api/auto/service/$provide), en el servicio [`$exceptionHandler`](https://docs.angularjs.org/api/ng/service/$exceptionHandler) para realizar acciones personalizadas cuando una excepción ocurra. - *¿Por qué?*: Provee una manera consistente de manejar excepciones de AngularJS que no están siendo capturadas en tiempo de desarrollo o en tiempo de ejecución. + *¿Por qué?*: Provee una manera consistente de manejar excepciones de Angular que no están siendo capturadas en tiempo de desarrollo o en tiempo de ejecución. Nota: Otra opción es sobreescribir el servicio en lugar de usar un decorador. Esto está bien, pero si quiere mantener el comportamiento por default y extenderlo se recomienda usar un decorador. @@ -2223,7 +2223,7 @@ Mientras que esta guía explica el *qué*, *por qué* y *cómo*, me resulta úti - Crea una módulo raíz de aplicación cuyo rol sea unir todos los módulos y características de tu aplicación. Nombra éste de acuerdo a tu aplicación. - *¿Por qué?*: AngularJS incentiva la modularidad y patrones de separación. Crear un módulo raíz de aplicación cuyo rol es atar otros módulos juntos provee una manera muy directa de agregar o remover módulos de tu aplicación. + *¿Por qué?*: Angular incentiva la modularidad y patrones de separación. Crear un módulo raíz de aplicación cuyo rol es atar otros módulos juntos provee una manera muy directa de agregar o remover módulos de tu aplicación. ### Mantén el Módulo App Delgado ###### [Style [Y162](#style-y162)] @@ -2343,7 +2343,7 @@ Mientras que esta guía explica el *qué*, *por qué* y *cómo*, me resulta úti - Usa [`$timeout`](https://docs.angularjs.org/api/ng/service/$timeout) y [`$interval`](https://docs.angularjs.org/api/ng/service/$interval) en lugar de `setTimeout` y `setInterval` . - *¿Por qué?*: Estos servicios están envueltos por Angular y son más fáciles de testear y manejar el ciclo digest de AngularJS así que mantienen el bindeo de los datos en sincronización. + *¿Por qué?*: Estos servicios están envueltos por Angular y son más fáciles de testear y manejar el ciclo digest de Angular así que mantienen el bindeo de los datos en sincronización. **[Volver arriba](#tabla-de-contenidos)** @@ -2684,7 +2684,7 @@ Usa Plantillas o snippets para ayudarte a seguir estilos consistentes o patrones ### Sublime Text ###### [Style [Y250](#style-y250)] - - Snippets de AngularJS que siguen estos estilos y directrices. + - Snippets de Angular que siguen estos estilos y directrices. - Descarga los [snippets de Angular para Sublime](assets/sublime-angular-snippets.zip?raw=true) - Colócalos en tu directorio de Packages @@ -2701,7 +2701,7 @@ Usa Plantillas o snippets para ayudarte a seguir estilos consistentes o patrones ### Visual Studio ###### [Style [Y251](#style-y251)] - - Plantillas de AngularJS que siguen estos estilos y directrices pueden ser encontrados en [SideWaffle](http://www.sidewaffle.com) + - Plantillas de Angular que siguen estos estilos y directrices pueden ser encontrados en [SideWaffle](http://www.sidewaffle.com) - Descarga la extensión [SideWaffle](http://www.sidewaffle.com) de Visual Studio (archivo vsix) - Corre el archivo vsix @@ -2710,9 +2710,9 @@ Usa Plantillas o snippets para ayudarte a seguir estilos consistentes o patrones ### WebStorm ###### [Style [Y252](#style-y252)] - - Snippets y arhicos de AngularJS que siguen estos estilos y directrices. Puedes importarlos en tus configuraciones de WebStorm: + - Snippets y arhicos de Angular que siguen estos estilos y directrices. Puedes importarlos en tus configuraciones de WebStorm: - - Descarga los [snippets y plantillas de AngularJS para WebStorm](assets/webstorm-angular-file-template.settings.jar?raw=true) + - Descarga los [snippets y plantillas de Angular para WebStorm](assets/webstorm-angular-file-template.settings.jar?raw=true) - Abre WebStorm y ve al menú `File` - Elije la opción `Import Settings` - Selecciona el archivo y da click en `OK` @@ -2798,7 +2798,7 @@ Usa [Gulp](http://gulpjs.com) o [Grunt](http://gruntjs.com) para crear tareas au **[Volver arriba](#tabla-de-contenidos)** -## AngularJS docs +## Angular docs Para cualquier otra cosa, refiérete a la API, mira la [documentación de Angular](//docs.angularjs.org/api). ## Contribuyendo From 2b945e537e649f4ef3de7e43ad59167478208d18 Mon Sep 17 00:00:00 2001 From: John Papa Date: Mon, 25 May 2015 20:04:28 -0400 Subject: [PATCH 312/567] removed js --- i18n/fr-FR.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/i18n/fr-FR.md b/i18n/fr-FR.md index e0b7407a..ece93b52 100644 --- a/i18n/fr-FR.md +++ b/i18n/fr-FR.md @@ -10,9 +10,9 @@ Si vous cherchez un guide de style pour la syntaxe, les conventions, et la struc Le but de ce guide de style est de proposer des conseils sur le développement d'applications Angular en montrant les conventions que j'utilise et, plus important encore, les raisons des choix que j'ai pris. ->Si vous appréciez ce guide, visitez mon cours [AngularJS Patterns: Clean Code](http://jpapa.me/ngclean) sur Pluralsight. +>Si vous appréciez ce guide, visitez mon cours [Angular Patterns: Clean Code](http://jpapa.me/ngclean) sur Pluralsight. - [![AngularJs Patterns: Clean Code](https://raw.githubusercontent.com/johnpapa/angular-styleguide/master/assets/ng-clean-code-banner.png)](http://jpapa.me/ngclean) + [![Angular Patterns: Clean Code](https://raw.githubusercontent.com/johnpapa/angular-styleguide/master/assets/ng-clean-code-banner.png)](http://jpapa.me/ngclean) ## Suprématie de la Communauté et Remerciements Ne jamais travailler dans le vide. J'ai trouvé que la communauté Angular est un incroyable groupe dont les membres ont à coeur de partager leurs expériences. Ainsi, un ami et expert Angular Todd Motto et moi avons collaboré sur de nombreux styles et conventions. Nous sommes d'accord sur la plupart, et nous divergeons sur d'autres. Je vous encourage à visiter [les guideslines de Todd](https://github.com/toddmotto/angularjs-styleguide) pour vous faire un sentiment sur son approche et en quoi elle est comparable. From 7296cb3afedf5c779f100838db594276b76b0fbe Mon Sep 17 00:00:00 2001 From: John Papa Date: Mon, 25 May 2015 20:04:45 -0400 Subject: [PATCH 313/567] removed js --- i18n/it-IT.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/i18n/it-IT.md b/i18n/it-IT.md index 27ea319c..bc23f650 100644 --- a/i18n/it-IT.md +++ b/i18n/it-IT.md @@ -1,6 +1,6 @@ # Guida stilistica ad AngularJS -*Guida stilistica dogmatica ad AngularJS per i team di [@john_papa](//twitter.com/john_papa)* +*Guida stilistica dogmatica ad Angular per i team di [@john_papa](//twitter.com/john_papa)* *Traduzione di [Angelo Chiello](https://github.com/angelochiello)* @@ -10,9 +10,9 @@ Se stai cercando una guida stilistica dogmatica per le sintassi, convenzioni e s L'obbiettivo di questa guida stilistica è di fare da vademecum alla costruzione di applicazioni con Angular mostrando le convenzioni che uso e, più importante, perché le uso. ->Se ti piace questa guida, dai un'occhiata al mio corso [AngularJS Patterns: Clean Code](http://jpapa.me/ngclean) (in inglese) su Pluralsight come complemento a questa guida. +>Se ti piace questa guida, dai un'occhiata al mio corso [Angular Patterns: Clean Code](http://jpapa.me/ngclean) (in inglese) su Pluralsight come complemento a questa guida. - [![AngularJs Patterns: Clean Code](https://raw.githubusercontent.com/johnpapa/angularjs-styleguide/master/assets/ng-clean-code-banner.png)](http://jpapa.me/ngclean) + [![Angular Patterns: Clean Code](https://raw.githubusercontent.com/johnpapa/angularjs-styleguide/master/assets/ng-clean-code-banner.png)](http://jpapa.me/ngclean) ## Eccezionalità della comunità e riconoscimenti Mai lavorare nel vuoto. Ritengo che la comunità intorno ad Angular sia un gruppo incredibile con la passione di condividere le esperienze. Perciò, Todd Motto, un amico ed un esperto di Angular, ed io abbiamo collaborato su molti stili e convenzioni. Su molto siamo d'accordo, su altro meno. Ti invito a controllare le [linee guida di Todd](https://github.com/toddmotto/angularjs-styleguide) per avere cognizione del suo approccio e di come paragonarle. From 488834d5211d3fec08a473abdb0df67157bb575b Mon Sep 17 00:00:00 2001 From: John Papa Date: Mon, 25 May 2015 20:05:12 -0400 Subject: [PATCH 314/567] removed js --- i18n/mk-MK.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/i18n/mk-MK.md b/i18n/mk-MK.md index 6a06ba07..872cf239 100644 --- a/i18n/mk-MK.md +++ b/i18n/mk-MK.md @@ -13,7 +13,7 @@ >Ако ви се допаѓа овој водич, тогаш проверете ми го курсот [Angular Patterns: Clean Code](http://jpapa.me/ngclean) на Pluralsight кој е придружник на овој водич. -[![AngularJs Шаблон: Чист Код](https://raw.githubusercontent.com/johnpapa/angular-styleguide/master/assets/ng-clean-code-banner.png)](http://jpapa.me/ngclean) +[![Angular Шаблон: Чист Код](https://raw.githubusercontent.com/johnpapa/angular-styleguide/master/assets/ng-clean-code-banner.png)](http://jpapa.me/ngclean) ## Величествена заедница и заслуга Никогаш не работи во вакуум. Јас сметам дека Angular заедницата е неверојатна група кои се страсни за споделување искуство. Како резултат, јас и мојот пријател кој е Angular експерт, Todd Motto соработувавме со многу стилови и конвенции. Се согласуваме на повеќето, додека на останатите се разликуваме. Ве охрабрувам да ги погледнете на [Todd's guidelines](https://github.com/toddmotto/angular-styleguide) со цел да добиете осет за неговиот пристап и како се споредува. From be650be04278e95623ab36014edbf2cc3f366ca9 Mon Sep 17 00:00:00 2001 From: John Papa Date: Mon, 25 May 2015 20:05:34 -0400 Subject: [PATCH 315/567] removed js --- i18n/PT-BR.md | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/i18n/PT-BR.md b/i18n/PT-BR.md index f6cfc6ac..0289257e 100644 --- a/i18n/PT-BR.md +++ b/i18n/PT-BR.md @@ -1,6 +1,6 @@ # Guia de Estilo AngularJS -*Guia de Estilo opinativo de AngularJS para times. Por [@john_papa](//twitter.com/john_papa)* +*Guia de Estilo opinativo de Angular para times. Por [@john_papa](//twitter.com/john_papa)* *Traduzido por [Eric Douglas](https://github.com/ericdouglas), [Ciro Nunes](https://github.com/cironunes), [Jean Lucas de Carvalho](https://github.com/jlcarvalho) e [Vinicius Sabadim Fernandes](https://github.com/vinicius-sabadim)* @@ -8,13 +8,13 @@ Se você procura por um guia de estilo opinativo para sintaxe, convenções e estruturação de aplicações AngularJS, então siga em frente! Estes estilos são baseados em minha experiência com desenvolvimento com [AngularJS](//angularjs.org), apresentações, [cursos de treinamento na Pluralsight](http://pluralsight.com/training/Authors/Details/john-papa) e trabalhando em equipe. -> Se você gostar deste guia, confira meu curso [AngularJS Patterns: Clean Code](http://jpapa.me/ngclean) na Pluralsight. +> Se você gostar deste guia, confira meu curso [Angular Patterns: Clean Code](http://jpapa.me/ngclean) na Pluralsight. -A proposta deste guia de estilo é fornecer uma direção na construção de aplicações AngularJS mostrando convenções que eu uso, e o mais importante, porque eu as escolhi. +A proposta deste guia de estilo é fornecer uma direção na construção de aplicações Angular mostrando convenções que eu uso, e o mais importante, porque eu as escolhi. ## A Importância da Comunidade e Créditos -Nunca trabalhe sozinho. Acho que a comunidade AngularJS é um grupo incrível, apaixonado em compartilhar experiências. Dessa forma, Todd Motto, um amigo e expert em AngularJS e eu temos colaborado com vários estilos e convenções. Nós concordamos na maioria deles, e discordamos em alguns. Eu encorajo você a conferir o [guia do Todd](https://github.com/toddmotto/angularjs-styleguide) para ter uma noção sobre sua abordagem e como ela se compara a esta. +Nunca trabalhe sozinho. Acho que a comunidade Angular é um grupo incrível, apaixonado em compartilhar experiências. Dessa forma, Todd Motto, um amigo e expert em Angular e eu temos colaborado com vários estilos e convenções. Nós concordamos na maioria deles, e discordamos em alguns. Eu encorajo você a conferir o [guia do Todd](https://github.com/toddmotto/angularjs-styleguide) para ter uma noção sobre sua abordagem e como ela se compara a esta. Vários de meus estilos vieram de várias sessões de pair-programming (programação pareada) que [Ward Bell](http://twitter.com/wardbell) e eu tivemos. Embora não concordemos sempre, meu amigo Ward certamente me ajudou influenciando na última evolução deste guia. @@ -53,7 +53,7 @@ Embora este guia explique o **o quê**, **porque** e **como**, acho útil ver tu 1. [JSHint](#js-hint) 1. [Constants](#constants) 1. [File Templates and Snippets](#file-templates-and-snippets) - 1. [AngularJS Docs](#angularjs-docs) + 1. [Angular Docs](#angularjs-docs) 1. [Contributing](#contributing) 1. [License](#license) @@ -115,7 +115,7 @@ ou *Responsabilidade Única* ## IIFE ### JavaScript Closures - - Envolva os componentes AngularJS em uma *Immediately Invoked Function Expression (IIFE - Expressão de função imediatamente invocada)*. + - Envolva os componentes Angular em uma *Immediately Invoked Function Expression (IIFE - Expressão de função imediatamente invocada)*. **Por que?** Uma IIFE remove as variáveis do escopo global. Isso ajuda a prevenir declarações de variáveis e funções de viverem por mais tempo que o esperado no escopo global, que também auxilia evitar colisões de variáveis. @@ -652,7 +652,7 @@ ou *Serviços* - Services são instanciados com a palavra-chave `new`, use `this` para métodos públicos e variáveis. Services são bastante similares a factories, use um factory para consistência. - Nota: [Todos services em AngularJS são singletons](https://docs.angularjs.org/guide/services). Isso significa que há apenas uma instância do serviço para cada injetor. + Nota: [Todos services em Angular são singletons](https://docs.angularjs.org/guide/services). Isso significa que há apenas uma instância do serviço para cada injetor. ```javascript // service @@ -696,7 +696,7 @@ ou *Responsabilidade Única* - Factories são singletons e retornam um objeto que contém os membros do serviço. - Nota: [Todos services em AngularJS são singletons](https://docs.angularjs.org/guide/services). + Nota: [Todos services em Angular são singletons](https://docs.angularjs.org/guide/services). ### Accessible Members Up Top ou *Membros acessíveis no topo* @@ -1101,7 +1101,7 @@ ou *Restringir para elementos e atributos* **Por que?**: Nós podemos utilizar uma diretiva como uma classe (class), mas se a diretiva está realmente agindo como um elemento, faz mais sentido utilizar como um elemento, ou pelo menos como um atributo. - Nota: EA é o padrão para o AngularJS 1.3 + + Nota: EA é o padrão para o Angular 1.3 + ```html @@ -1532,7 +1532,7 @@ ou *Minificação e Anotação* } ``` - > Nota: Apartir do AngularJS 1.3 use o parâmetro `ngStrictDi` da diretiva [`ngApp`](https://docs.angularjs.org/api/ng/directive/ngApp). Quando presente, o injetor será criado no modo "strict-di" fazendo com que a aplicação falhe ao tentar invocar funções que não usem anotação explícita de função (elas podem não ser seguras para minificação). Informação de debug será logada no console para ajudar a rastrear o código ofensivo. + > Nota: Apartir do Angular 1.3 use o parâmetro `ngStrictDi` da diretiva [`ngApp`](https://docs.angularjs.org/api/ng/directive/ngApp). Quando presente, o injetor será criado no modo "strict-di" fazendo com que a aplicação falhe ao tentar invocar funções que não usem anotação explícita de função (elas podem não ser seguras para minificação). Informação de debug será logada no console para ajudar a rastrear o código ofensivo. `` ### Utilize Gulp ou Grunt para o ng-annotate @@ -1574,7 +1574,7 @@ ou *decoradores* - Utilize um [decorator](https://docs.angularjs.org/api/auto/service/$provide#decorator), no seu config utilizando o serviço [`$provide`](https://docs.angularjs.org/api/auto/service/$provide), no serviço [`$exceptionHandler`](https://docs.angularjs.org/api/ng/service/$exceptionHandler) para realizar ações customizadas quando um erro ocorrer. - **Por que?**: Fornece um caminho consistente para manipular erros não tratados pelo AngularJS em tempo de desenvolvimento ou execução (run-time). + **Por que?**: Fornece um caminho consistente para manipular erros não tratados pelo Angular em tempo de desenvolvimento ou execução (run-time). Nota: Outra opção é sobrescrever o serviço ao invés de utilizar um decorator. Esta é uma boa opção, mas se você quer manter o comportamento padrão e estender, o decorator é recomendado. @@ -2076,7 +2076,7 @@ ou *Rotas* - Create an application root module whose role is pull together all of the modules and features of your application. Name this for your application. - *Why?*: AngularJS encourages modularity and separation patterns. Creating an application root module whose role is to tie your other modules together provides a very straightforward way to add or remove modules from your application. + *Why?*: Angular encourages modularity and separation patterns. Creating an application root module whose role is to tie your other modules together provides a very straightforward way to add or remove modules from your application. ### Keep the App Module Thin @@ -2245,7 +2245,7 @@ Testes unitários ajudam a manter o código limpo, tal como, eu inclui algumas r *Why?*: animate.css is widely used and tested. - Note: See this [great post by Matias Niemelä on AngularJS animations](http://www.yearofmoo.com/2013/08/remastered-animation-in-angularjs-1-2.html) + Note: See this [great post by Matias Niemelä on Angular animations](http://www.yearofmoo.com/2013/08/remastered-animation-in-angularjs-1-2.html) **[De volta ao topo](#tabela-de-conte%C3%BAdo)** @@ -2382,7 +2382,7 @@ Testes unitários ajudam a manter o código limpo, tal como, eu inclui algumas r ### Globais de terceiros (*vendors*) - - Cria uma *Constant* no AngularJS para variáveis globais de bibliotecas de terceiros. + - Cria uma *Constant* no Angular para variáveis globais de bibliotecas de terceiros. *Por que?*: Fornece uma forma de injetar bibliotecas de terceiros que de outra forma seriam globais. Isso melhora a testabilidade do código permitindo a você conhecer mais facilmente quais dependências os seus componentes têm (evita vazamento de abstrações). Também permite que você simule estas dependências, o que faz sentido. @@ -2407,7 +2407,7 @@ Use file templates or snippets to help follow consistent styles and patterns. He ### Sublime Text - - AngularJS snippets that follow these styles and guidelines. + - Angular snippets that follow these styles and guidelines. - Download the [Sublime Angular snippets](assets/sublime-angular-snippets.zip) - Place it in your Packages folder @@ -2423,7 +2423,7 @@ Use file templates or snippets to help follow consistent styles and patterns. He ### Visual Studio - - AngularJS file templates that follow these styles and guidelines can be found at [SideWaffle](http://www.sidewaffle.com) + - Angular file templates that follow these styles and guidelines can be found at [SideWaffle](http://www.sidewaffle.com) - Download the [SideWaffle](http://www.sidewaffle.com) Visual Studio extension (vsix file) - Run the vsix file @@ -2431,9 +2431,9 @@ Use file templates or snippets to help follow consistent styles and patterns. He ### WebStorm - - AngularJS snippets and file templates that follow these styles and guidelines. You can import them into your WebStorm settings: + - Angular snippets and file templates that follow these styles and guidelines. You can import them into your WebStorm settings: - - Download the [WebStorm AngularJS file templates and snippets](assets/webstorm-angular-file-template.settings.jar) + - Download the [WebStorm Angular file templates and snippets](assets/webstorm-angular-file-template.settings.jar) - Open WebStorm and go to the `File` menu - Choose the `Import Settings` menu option - Select the file and click `OK` @@ -2447,7 +2447,7 @@ Use file templates or snippets to help follow consistent styles and patterns. He **[De volta ao topo](#tabela-de-conte%C3%BAdo)** -## AngularJS docs +## Angular docs For anything else, API reference, check the [Angular documentation](//docs.angularjs.org/api). ## Contributing From 0c095a9b6be980e9defd8543b90c27854fcb8bf8 Mon Sep 17 00:00:00 2001 From: John Papa Date: Mon, 25 May 2015 20:05:54 -0400 Subject: [PATCH 316/567] removed js --- i18n/ru-RU.md | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/i18n/ru-RU.md b/i18n/ru-RU.md index e2d068b8..d35effcb 100644 --- a/i18n/ru-RU.md +++ b/i18n/ru-RU.md @@ -1,6 +1,6 @@ # Руководство по стилям для AngularJS -*AngularJS соглашения по стилям для команд разработчиков, предложенные [@john_papa](//twitter.com/john_papa)* +*Angular соглашения по стилям для команд разработчиков, предложенные [@john_papa](//twitter.com/john_papa)* *Перевел на русский язык [Василий Мажекин](https://github.com/mazhekin)* @@ -9,12 +9,12 @@ Если вам нужны стандарты написания кода, соглашения, и руководства структурирования приложений AngularJS, то вы находитесь в правильном месте. Эти соглашения основаны на моем опыте программирования на [AngularJS](//angularjs.org), на моих презентациях [Pluralsight training courses](http://pluralsight.com/training/Authors/Details/john-papa), а также на совместной работе в командах разработчиков. Главной целью этого документа является желание предоставить вам наиболее полные инструкции для построения приложений AngularJS. Рекомендуя данные соглашения, я стараюсь акцентировать ваше внимание на цели и причины, зачем их нужно придерживаться. ->Если это руководство вам понравится, то вы можете также оценить мой курс [AngularJS Patterns: Clean Code](http://jpapa.me/ngclean), который размещен на сайте Pluralsight. +>Если это руководство вам понравится, то вы можете также оценить мой курс [Angular Patterns: Clean Code](http://jpapa.me/ngclean), который размещен на сайте Pluralsight. - [![AngularJs Patterns: Clean Code](https://raw.githubusercontent.com/johnpapa/angularjs-styleguide/master/assets/ng-clean-code-banner.png)](http://jpapa.me/ngclean) + [![Angular Patterns: Clean Code](https://raw.githubusercontent.com/johnpapa/angularjs-styleguide/master/assets/ng-clean-code-banner.png)](http://jpapa.me/ngclean) ## Признательность сообществу и коллегам -Никогда не работайте в вакууме. Я считаю AngularJS-сообщество невероятно открытым, которое активно обменивается опытом и заботится об этом. Также как и мой друг Todd Motto (отличный AngularJS эксперт), я работал со многими стилями и соглашениями. Мы с ним сходимся во многом, но иногда и противоречим друг другу. Я предлагаю вам ознакомиться с курсом [Todd's guidelines](https://github.com/toddmotto/angularjs-styleguide) дабы почувствовать разницу подходов. +Никогда не работайте в вакууме. Я считаю AngularJS-сообщество невероятно открытым, которое активно обменивается опытом и заботится об этом. Также как и мой друг Todd Motto (отличный Angular эксперт), я работал со многими стилями и соглашениями. Мы с ним сходимся во многом, но иногда и противоречим друг другу. Я предлагаю вам ознакомиться с курсом [Todd's guidelines](https://github.com/toddmotto/angularjs-styleguide) дабы почувствовать разницу подходов. Многие из моих стилей взяты в ходе моих программистских сессий с [Ward Bell](http://twitter.com/wardbell). А так как мы не всегда были согласны друг с другом, то мой друг Ward оказал очень сильное влияние на эволюцию и окончательную редакцию этого документа. @@ -53,7 +53,7 @@ 1. [Yeoman Generator](#yeoman-generator) 1. [Routing (Маршрутизация)](#routing) 1. [Task Automation (Автоматизация)](#task-automation) - 1. [AngularJS Docs (AngularJS документация)](#angularjs-docs) + 1. [Angular Docs (Angular документация)](#angularjs-docs) 1. [Contributing (Сотрудничество)](#contributing) 1. [License](#license) @@ -116,7 +116,7 @@ ### Замыкания JavaScript ###### [Style [Y010](#style-y010)] - - Оборачивайте компоненты AngularJS в Немедленно Исполняемые Функции(IIFE - Immediately Invoked Function Expression). + - Оборачивайте компоненты Angular в Немедленно Исполняемые Функции(IIFE - Immediately Invoked Function Expression). *Зачем?*: IIFE удаляют переменные из глобальной области видимости. Этот прием не дает существовать переменным и функциям дольше, чем это необходимо в глобальной области видимости. Иначе это может вызвать непредсказуемые коллизии во время исполнения всего приложения. @@ -683,7 +683,7 @@ - Сервисы создаются с помощью ключевого слова `new`. Используйте `this` для публичных методов и переменных. Так как они очень похожи на фабрики, то используйте фабрики для согласованности. - Замечание: [Все AngularJS сервисы являются синглтонами](https://docs.angularjs.org/guide/services). Это значит, что создается только один экземпляр сервиса на один инжектор. + Замечание: [Все Angular сервисы являются синглтонами](https://docs.angularjs.org/guide/services). Это значит, что создается только один экземпляр сервиса на один инжектор. ```javascript // service @@ -727,7 +727,7 @@ - Фабрики это синглтоны, которые возвращают объект, содержащий свойства и методы сервиса. - Замечание: [Все AngularJS сервисы являются синглтонами](https://docs.angularjs.org/guide/services). + Замечание: [Все Angular сервисы являются синглтонами](https://docs.angularjs.org/guide/services). ### Доступные Члены Наверх ###### [Style [Y052](#style-y052)] @@ -1122,13 +1122,13 @@ ### Ограничивайте Элементы и Атрибуты ###### [Style [Y074](#style-y074)] - - При создании директивы, которая планируется как самостоятельный элемент, применяйте ограничение `E` (разработано, как элемент) или по необходимости ограничение `A` (разработано, как атрибут). В основном, если директива разрабатывается как элемент, ограничения `E` вполне достаточно. Хотя AngularJS позволяет использовать `EA`, но все же лучше определится как реализовывать директиву, либо как самостоятельный отдельный элемент, либо как атрибут для улучшения функциональности существующего DOM-элемента. + - При создании директивы, которая планируется как самостоятельный элемент, применяйте ограничение `E` (разработано, как элемент) или по необходимости ограничение `A` (разработано, как атрибут). В основном, если директива разрабатывается как элемент, ограничения `E` вполне достаточно. Хотя Angular позволяет использовать `EA`, но все же лучше определится как реализовывать директиву, либо как самостоятельный отдельный элемент, либо как атрибут для улучшения функциональности существующего DOM-элемента. *Почему?*: Это имееет смысл. *Почему?*: Конечно мы можем использовать директиву в атрибуте class, но если директива действует как элемент, то лучше объявлять ее как элемент, ну или по крайней мере как атрибут. - Замечание: EA используется по умолчанию для AngularJS 1.3 + + Замечание: EA используется по умолчанию для Angular 1.3 + ```html @@ -1606,7 +1606,7 @@ } ``` - > Замечание: Начиная с AngularJS 1.3 используйте [`ngApp`](https://docs.angularjs.org/api/ng/directive/ngApp) директивный параметр `ngStrictDi`. При наличии инжектора будет создан режим "strict-di", который не даст приложению работать, если обнаружит функции, которые не используют явные аннотации (например, для защиты от минификации). Отладочная информация будет отображаться в консоли, чтобы помочь разработчику выявить код, ломающий приложение. + > Замечание: Начиная с Angular 1.3 используйте [`ngApp`](https://docs.angularjs.org/api/ng/directive/ngApp) директивный параметр `ngStrictDi`. При наличии инжектора будет создан режим "strict-di", который не даст приложению работать, если обнаружит функции, которые не используют явные аннотации (например, для защиты от минификации). Отладочная информация будет отображаться в консоли, чтобы помочь разработчику выявить код, ломающий приложение. `` ### Используйте Gulp или Grunt для ng-annotate @@ -1648,7 +1648,7 @@ - Используйте [decorator](https://docs.angularjs.org/api/auto/service/$provide#decorator), во время конфигурации, применяя сервис [`$provide`](https://docs.angularjs.org/api/auto/service/$provide), пользовательские действия будут происходить в сервисе [`$exceptionHandler`](https://docs.angularjs.org/api/ng/service/$exceptionHandler), если произойдут исключения. - *Почему?*: Это дает постоянный надежный способ обработки необработанных исключений AngularJS во время разработки и во время выполнения. + *Почему?*: Это дает постоянный надежный способ обработки необработанных исключений Angular во время разработки и во время выполнения. Замечание: Другим способом является переопределение сервиса, вместо использования декоратора. Это прекрасный способ, но если вы хотите сохранить поведение по умолчанию, и просто дополнить это поведение, то декоратоор крайне рекомендуем. @@ -2161,7 +2161,7 @@ - Создайте корневой модуль приложения, который будет собирать вместе все модули и функциональности вашего приложения. Назовите этот модуль именем вашего приложения. - *Почему?*: AngularJS специально разработан для поддержки модульности и принципов разделения сущностей. А создание корневого модуля приложения, который связывает все ваши остальные модули вместе, предоставляет очень простой способ добавления и удаления модулей из приложения. + *Почему?*: Angular специально разработан для поддержки модульности и принципов разделения сущностей. А создание корневого модуля приложения, который связывает все ваши остальные модули вместе, предоставляет очень простой способ добавления и удаления модулей из приложения. ### Держите Модуль Приложения Тонким ###### [Style [Y162](#style-y162)] @@ -2568,7 +2568,7 @@ ### Глобальные Переменные Сторонних Производителей (Vendors) ###### [Style [Y240](#style-y240)] - - Создайте константы AngularJS для глобальных переменных из библиотек сторонних производителей. + - Создайте константы Angular для глобальных переменных из библиотек сторонних производителей. *Почему?*: Предоставляет способ подключить сторонние библиотеки, которые являются глобальными переменными. Это улучшает тестируемость кода, позволяя вам проще узнать, какие зависимости есть у ваших компонентов. Это также позволит вам, создать фиктивные объекты этих зависимостей, если это нужно. @@ -2619,7 +2619,7 @@ ### Sublime Text ###### [Style [Y250](#style-y250)] - - AngularJS сниппеты, которые соблюдают приведенные здесь стили и руководства. + - Angular сниппеты, которые соблюдают приведенные здесь стили и руководства. - Скачайте [Sublime Angular сниппеты](assets/sublime-angular-snippets.zip?raw=true) - Поместите все в вашу папку Packages @@ -2645,9 +2645,9 @@ ### WebStorm ###### [Style [Y252](#style-y252)] - - AngularJS сниппеты и шаблоны файлов, которые соблюдают приведенные здесь стили и руководства. Вы можете импортировать их в свои настройки WebStorm: + - Angular сниппеты и шаблоны файлов, которые соблюдают приведенные здесь стили и руководства. Вы можете импортировать их в свои настройки WebStorm: - - Скачайте [WebStorm AngularJS шаблоны файлов и сниппетов](../assets/webstorm-angular-file-template.settings.jar?raw=true) + - Скачайте [WebStorm Angular шаблоны файлов и сниппетов](../assets/webstorm-angular-file-template.settings.jar?raw=true) - Откройте WebStorm и перейдите в меню `File` - Выберите пункт меню `Import Settings` - Выберите файл и нажмите `OK` @@ -2733,7 +2733,7 @@ **[К Содержанию](#table-of-contents)** -## AngularJS Docs +## Angular Docs Для дополнительной информации, описания API, смотрите [документацию Angular](//docs.angularjs.org/api). ## Contributing From f1ff6067e772b278d2ff7c4813038d8c1b628061 Mon Sep 17 00:00:00 2001 From: Nikita Shulipa Date: Mon, 1 Jun 2015 22:17:49 +0300 Subject: [PATCH 317/567] More consistency Translate questions, fixed meaning of some sentences. --- i18n/ru-RU.md | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/i18n/ru-RU.md b/i18n/ru-RU.md index d35effcb..5a0b09d4 100644 --- a/i18n/ru-RU.md +++ b/i18n/ru-RU.md @@ -799,7 +799,7 @@ *Почему?*: Вам не надо беспокоиться о порядке определений функций. Перестановка зависимых друг от друга функций не ломает код. - *Why?*: А для выражений функций порядок критичен. + *Почему?*: А для выражений функций порядок критичен. ```javascript /** @@ -1537,9 +1537,9 @@ - Используйте [ng-annotate](//github.com/olov/ng-annotate) для [Gulp](http://gulpjs.com) или [Grunt](http://gruntjs.com) и комментируйте функции, которые нуждаются в автоматической вставке зависимостей, используйте `/** @ngInject */`. - *Why?*: Это гарантирует, что в вашем коде нет зависимостей, которые не используют защиту для повреждений от минификации. + *Почему?*: Это гарантирует, что в вашем коде нет зависимостей, которые не используют защиту для повреждений от минификации. - *Why?*: [`ng-min`](https://github.com/btford/ngmin) не рекомендуется для применения, выводится из употребления + *Почему?*: [`ng-min`](https://github.com/btford/ngmin) не рекомендуется для применения, выводится из употребления >Я предпочитаю Gulp, так как для меня он проще для чтения, написания кода и отладки. @@ -1961,7 +1961,7 @@ *Почему?*: Конфигурация отделяется от определения модуля, компонентов и активного кода. - *Why?*: Мы получаем идентифицируемое место для установки конфигурации модуля. + *Почему?*: Мы получаем идентифицируемое место для установки конфигурации модуля. ### Маршруты ###### [Style [Y129](#style-y129)] @@ -2331,7 +2331,7 @@ *Почему?*: Karma просто конфигурируется, она просто запускается вручную или автоматически (как только вы измените код). - *Why?*: Karma просто внедряется в ваш процесс Continuous Integration, как самостоятельно, так и через Grunt или Gulp. + *Почему?*: Karma просто внедряется в ваш процесс Continuous Integration, как самостоятельно, так и через Grunt или Gulp. *Почему?*: Некоторые средства разработки (IDE) начали интегрировать в себя библиотеку Karma, это - [WebStorm](http://www.jetbrains.com/webstorm/) и [Visual Studio](http://visualstudiogallery.msdn.microsoft.com/02f47876-0e7a-4f6c-93f8-1af5d5189225). @@ -2411,7 +2411,7 @@ *Почему?*: При правильном использовании тонкая анимация может улучшить удобство работы. - *Почему?*: Тонкие анимации могут воспринимаемую эффективность при изменениии представлений. + *Почему?*: Тонкие анимации могут улучшить воспринимаемую эффективность при изменениии представлений. ### Длительность Анимаций ###### [Style [Y211](#style-y211)] @@ -2702,11 +2702,11 @@ - Определяйте маршруты для всех представлений в модуле, где они есть. Каждый модуль должен содержать маршруты для всех своих представлений. - *Why?*: Каждый модуль должен быть независим. + *Почему?*: Каждый модуль должен быть независим. - *Why?*: Когда мы удаляем или добавляем модуль, то приложение должно содержать только те маршруты, которые указывают на существующие представления. + *Почему?*: Когда мы удаляем или добавляем модуль, то приложение должно содержать только те маршруты, которые указывают на существующие представления. - *Why?*: Так мы можем включать или исключать части приложения, не заботясь о том, что у нас останутся маршруты на несуществующие представления. + *Почему?*: Так мы можем включать или исключать части приложения, не заботясь о том, что у нас останутся маршруты на несуществующие представления. **[К Содержанию](#table-of-contents)** @@ -2717,9 +2717,9 @@ - Используйте автоматизацию для сборки всех файлов с определениями модуля `*.module.js` перед всеми остальными JavaScript-файлами приложения. - *Why?*: Angular должен зарегистрировать все определения модулей, перед тем как их использовать. + *Почему?*: Angular должен зарегистрировать все определения модулей, перед тем как их использовать. - *Why?*: Именование модулей по специальному шаблону `*.module.js` упрощает их поиск и сборку в единую группу, для того чтобы подключить их первыми. + *Почему?*: Именование модулей по специальному шаблону `*.module.js` упрощает их поиск и сборку в единую группу, для того чтобы подключить их первыми. ```javascript var clientApp = './src/client/app/'; From a871f42f9745a7ecfb9dc90a1f6a365bdd53748e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=A8=8B=E7=A7=91?= Date: Mon, 8 Jun 2015 14:24:59 +0800 Subject: [PATCH 318/567] Update zh-CN.md fix typo --- i18n/zh-CN.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/i18n/zh-CN.md b/i18n/zh-CN.md index 8e72ffe1..5ed3cf0f 100644 --- a/i18n/zh-CN.md +++ b/i18n/zh-CN.md @@ -2362,7 +2362,7 @@ Angular社区是一个热衷于分享经验的令人难以置信的社区,尽 ###用故事来编写测试 ###### [Style [Y190](#style-y190)] - - 给每一个故事都写一组测试,县创建一个空的测试,然后用你给这个故事写的代码来填充它。 + - 给每一个故事都写一组测试,先创建一个空的测试,然后用你给这个故事写的代码来填充它。 *为什么?*:编写测试有助于明确规定你的故事要做什么、不做什么以及你如何判断是否成功。 From 6c9b8052b430a0dcd147a154feb723708ccbed98 Mon Sep 17 00:00:00 2001 From: Alex Katopodis Date: Wed, 10 Jun 2015 16:13:13 +0300 Subject: [PATCH 319/567] Sublime filter snippet: removed unnecessary semicolon --- assets/sublime-angular-snippets/angular.filter.sublime-snippet | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/assets/sublime-angular-snippets/angular.filter.sublime-snippet b/assets/sublime-angular-snippets/angular.filter.sublime-snippet index dba88bb1..7e1bc54e 100644 --- a/assets/sublime-angular-snippets/angular.filter.sublime-snippet +++ b/assets/sublime-angular-snippets/angular.filter.sublime-snippet @@ -10,9 +10,10 @@ return ${2:filter}Filter; //////////////// + function ${2:filter}Filter(${3:params}) { return ${3:params}; - }; + } } })(); From fc47ef5820fb223617422672ffaec4044fb5ec81 Mon Sep 17 00:00:00 2001 From: Victor Johnson Date: Wed, 10 Jun 2015 08:06:12 -0600 Subject: [PATCH 320/567] Fixed incorrect usage of effect to affect. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 351d6a23..4b788714 100644 --- a/README.md +++ b/README.md @@ -3054,7 +3054,7 @@ Use [Gulp](http://gulpjs.com) or [Grunt](http://gruntjs.com) for creating automa - Avoid using filters for scanning all properties of a complex object graph. Use filters for select properties. - *Why?*: Filters can easily be abused and negatively effect performance if not used wisely, for example when a filter hits a large and deep object graph. + *Why?*: Filters can easily be abused and negatively affect performance if not used wisely, for example when a filter hits a large and deep object graph. **[Back to top](#table-of-contents)** From b44c0f4242042a2823012038f53cc1bdda157ecb Mon Sep 17 00:00:00 2001 From: angelochiello Date: Sun, 14 Jun 2015 08:59:07 +0200 Subject: [PATCH 321/567] [it-IT] Removed "JS" from title Removed "JS" from title to comply with original document. --- i18n/it-IT.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/i18n/it-IT.md b/i18n/it-IT.md index bc23f650..aea42a6b 100644 --- a/i18n/it-IT.md +++ b/i18n/it-IT.md @@ -1,4 +1,4 @@ -# Guida stilistica ad AngularJS +# Guida stilistica ad Angular *Guida stilistica dogmatica ad Angular per i team di [@john_papa](//twitter.com/john_papa)* From 9263f04b524ed5b983f8caca722507abb1389fa0 Mon Sep 17 00:00:00 2001 From: noritamago Date: Sun, 21 Jun 2015 02:02:25 +0900 Subject: [PATCH 322/567] follow latest master branch change in ja-JP --- i18n/ja-JP.md | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/i18n/ja-JP.md b/i18n/ja-JP.md index 46c9e982..29218653 100644 --- a/i18n/ja-JP.md +++ b/i18n/ja-JP.md @@ -366,7 +366,7 @@ } ``` - Note: 下記のコメントをコードの上部に入れることで [jshint](http://www.jshint.com/) のwarningsを避けることができます。 しかし関数がアッパーケースの場合には不要です。規約的にはそれはコンストラクタであり、Angularではコントローラに当たります。 + Note: コメントをコードの上部に入れることで [jshint](http://www.jshint.com/) のwarningsを避けることができます。 しかし関数がアッパーケースの場合には不要です。規約的にはそれはコンストラクタであり、Angularではコントローラに当たります。 ```javascript /* jshint validthis: true */ @@ -1263,7 +1263,7 @@ console.log('LINK: vm.max = %s', vm.max); } ``` -z + ###### [Style [Y076](#style-y076)] - `controller as`シンタックスをディレクティブで用い、外側のscopeをディレクティブのコントローラのscopeにバインドしたいときは `bindToController = true` を使って下さい。 @@ -2476,8 +2476,8 @@ z ``` /src/client/app/customers/customer-detail.controller.js /customer-detail.controller.spec.js + /customers.controller.js /customers.controller.spec.js - /customers.controller-detail.spec.js /customers.module.js /customers.route.js /customers.route.spec.js @@ -2724,7 +2724,6 @@ z "disallowCommaBeforeLineBreak": null, "disallowDanglingUnderscores": null, "disallowEmptyBlocks": null, - "disallowMultipleLineStrings": null, "disallowTrailingComma": null, "requireCommaBeforeLineBreak": null, "requireDotNotation": null, From 8d1441a190b2d2681835d79922034c2cd260c11c Mon Sep 17 00:00:00 2001 From: natee Date: Sat, 27 Jun 2015 20:31:18 +0800 Subject: [PATCH 323/567] update transition --- README.md | 2 +- i18n/zh-CN.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 4b788714..d887a430 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ The purpose of this style guide is to provide guidance on building Angular appli >If you like this guide, check out my [Angular Patterns: Clean Code](http://jpapa.me/ngclean) course at Pluralsight which is a companion to this guide. - [![AngularJs Patterns: Clean Code](https://raw.githubusercontent.com/johnpapa/angular-styleguide/master/assets/ng-clean-code-banner.png)](http://jpapa.me/ngclean) + [![Angular Patterns: Clean Code](https://raw.githubusercontent.com/johnpapa/angular-styleguide/master/assets/ng-clean-code-banner.png)](http://jpapa.me/ngclean) ## Community Awesomeness and Credit Never work in a vacuum. I find that the Angular community is an incredible group who are passionate about sharing experiences. As such, a friend and Angular expert Todd Motto and I have collaborated on many styles and conventions. We agree on most, and some we diverge. I encourage you to check out [Todd's guidelines](https://github.com/toddmotto/angularjs-styleguide) to get a sense for his approach and how it compares. diff --git a/i18n/zh-CN.md b/i18n/zh-CN.md index 81b337ee..65216c32 100644 --- a/i18n/zh-CN.md +++ b/i18n/zh-CN.md @@ -2474,8 +2474,8 @@ Angular社区是一个热衷于分享经验的令人难以置信的社区,尽 ``` /src/client/app/customers/customer-detail.controller.js /customer-detail.controller.spec.js + /customers.controller.js /customers.controller.spec.js - /customers.controller-detail.spec.js /customers.module.js /customers.route.js /customers.route.spec.js From 706b6693345d5a38b520b222af42cbc0be341c84 Mon Sep 17 00:00:00 2001 From: Nikolay Date: Tue, 30 Jun 2015 16:29:33 +0300 Subject: [PATCH 324/567] Update ru-RU.md --- i18n/ru-RU.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/i18n/ru-RU.md b/i18n/ru-RU.md index 5a0b09d4..66b9ae77 100644 --- a/i18n/ru-RU.md +++ b/i18n/ru-RU.md @@ -789,7 +789,7 @@ ### Определения Функций для Скрытия Деталей Реализации ###### [Style [Y053](#style-y053)] - - Используйте определения функций, чтобы скрыть детали реализации. Держите вызываемые члены фабрики в верхней части. Свяжите их с определениями функций, которые распололжены ниже в файле. Подробную информацию смотрите [здесь](http://www.johnpapa.net/angular-function-declarations-function-expressions-and-readable-code). + - Используйте определения функций, чтобы скрыть детали реализации. Держите вызываемые члены фабрики в верхней части. Свяжите их с определениями функций, которые расположены ниже в файле. Подробную информацию смотрите [здесь](http://www.johnpapa.net/angular-function-declarations-function-expressions-and-readable-code). *Почему?*: Размещение вызываемых членов в верхней части улучшает читабельность и помогает быстро определить, какие функции фабрики могут быть вызваны извне. From 11a5232c82a6277fee9a221b62f97537391da7cf Mon Sep 17 00:00:00 2001 From: Nikolay Date: Tue, 30 Jun 2015 16:37:05 +0300 Subject: [PATCH 325/567] Update ru-RU.md --- i18n/ru-RU.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/i18n/ru-RU.md b/i18n/ru-RU.md index 5a0b09d4..b6287cbe 100644 --- a/i18n/ru-RU.md +++ b/i18n/ru-RU.md @@ -1192,7 +1192,7 @@ Замечание: Что касается внедренной зависимости, смотрите [Определение зависимостей вручную](#manual-annotating-for-dependency-injection). - Замечание: Заметьте, что контроллер директивы находится снаружи самой директивы. Такой подход исключает проблемы, когда инжектор создается в недосягаемом код после, например, 'return'. + Замечание: Заметьте, что контроллер директивы находится снаружи самой директивы. Такой подход исключает проблемы, когда инжектор создается в недосягаемом кодe после, например, 'return'. ```html
From 70edfb25d216492382cb47bf1be181e9d2f3ef03 Mon Sep 17 00:00:00 2001 From: Greg Deane Date: Mon, 6 Jul 2015 10:28:09 +0200 Subject: [PATCH 326/567] Adjusted position of "Back to top" link in "File Templates and Snippets" section --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 4b788714..72602a74 100644 --- a/README.md +++ b/README.md @@ -2902,6 +2902,8 @@ Use file templates or snippets to help follow consistent styles and patterns. He ngservice // creates an Angular service ngfilter // creates an Angular filter ``` + + **[Back to top](#table-of-contents)** ## Yeoman Generator From 78e243865ef7bd103677c7eaf09292f523f48919 Mon Sep 17 00:00:00 2001 From: gordonmzhu Date: Tue, 7 Jul 2015 08:08:23 -0700 Subject: [PATCH 327/567] Fix spelling of 'success' --- i18n/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/i18n/README.md b/i18n/README.md index ca99715e..6a161c92 100644 --- a/i18n/README.md +++ b/i18n/README.md @@ -15,7 +15,7 @@ The [original English version](http://jpapa.me/ngstyles) is the source of truth, 9. [Spanish](es-ES.md) ## Contributing -Language translations are welcomed and encouraged. The succcess of these translations depends on the community. I highly encourage new translation contributions and help to keep them up to date. +Language translations are welcomed and encouraged. The success of these translations depends on the community. I highly encourage new translation contributions and help to keep them up to date. All translations must preserve the intention of the original document. From 23fbda3fe3f585f91b8adf3f7fc75116b7d2843c Mon Sep 17 00:00:00 2001 From: Sascha Hagedorn Date: Sat, 11 Jul 2015 14:33:59 +0200 Subject: [PATCH 328/567] Fixed typos. --- i18n/de-DE.md | 230 +++++++++++++++++++++++++------------------------- 1 file changed, 115 insertions(+), 115 deletions(-) diff --git a/i18n/de-DE.md b/i18n/de-DE.md index e43b8717..7eba3555 100644 --- a/i18n/de-DE.md +++ b/i18n/de-DE.md @@ -6,21 +6,21 @@ >The [original English version](http://jpapa.me/ngstyles) is the source of truth, as it is maintained and updated first. -Sind Sie auf der Suche nach einem dogmatischen Styleguide zur Syntax, zu Konventionen und zur Struktur von Angular-Anwendungen, dann treten sie näher. Diese Vorlagen basieren auf meinen Erfahrungen mit [Angular](//angularjs.org), Präsentationen, [Pluralsight Trainingskursen](http://pluralsight.com/training/Authors/Details/john-papa) und der Arbeit in Teams. +Sind Sie auf der Suche nach einem dogmatischen Styleguide zur Syntax, zu Konventionen und zur Struktur von Angular-Anwendungen, dann treten Sie näher. Diese Vorlagen basieren auf meinen Erfahrungen mit [Angular](//angularjs.org), Präsentationen, [Pluralsight Trainingskursen](http://pluralsight.com/training/Authors/Details/john-papa) und der Arbeit in Teams. Der Zweck dieses Styleguides ist es, eine Anleitung für die Erstellung von Angular-Anwendungen bereitzustellen, indem ich die Konventionen, die ich nutze, zeige und - wichtiger als das - beschreibe, warum ich sie wähle. ->Wenn Sie diese Anleitung mögen, dann besuchen Sie meinen Kurs [Angular Patterns: Clean Code] (http://jpapa.me/ngclean) auf Pluralsight, der eine Begleitung zu dieser Anleitung dartellt. +>Wenn Sie diese Anleitung mögen, dann besuchen Sie meinen Kurs [Angular Patterns: Clean Code] (http://jpapa.me/ngclean) auf Pluralsight, der eine Begleitung zu dieser Anleitung darstellt. [![Angular Patterns: Clean Code](https://raw.githubusercontent.com/johnpapa/angular-styleguide/master/assets/ng-clean-code-banner.png)](http://jpapa.me/ngclean) -## Außergewöhnliche Community and Anerkennung -Arbeite niemals im leeren Raum. Ich finde, dass die Angular-Community eine unglaubliche Gruppe ist, die ihre Erfahrung mit Leidenschaft teilt. Also haben ein Freund und Angular-Experte, Todd Motto, und ich viele Vorlagen und Konventionen zusammengetragen. Bei den meisten sind wir uns einig, und bei ein paar sind wir verschiedener Meinung. Ich möchte Sie ermutigen, sich [Todd's Guidelines](https://github.com/toddmotto/angularjs-styleguide) anzusehen, um ein Gespühr für seinen Ansatz zu entwickeln und ihn vergleichen zu können. +## Außergewöhnliche Community und Anerkennung +Arbeite niemals im leeren Raum. Ich finde, dass die Angular-Community eine unglaubliche Gruppe ist, die ihre Erfahrung mit Leidenschaft teilt. Also haben ein Freund und Angular-Experte, Todd Motto, und ich viele Vorlagen und Konventionen zusammengetragen. Bei den meisten sind wir uns einig, und bei ein paar sind wir verschiedener Meinung. Ich möchte Sie ermutigen, sich [Todd's Guidelines](https://github.com/toddmotto/angularjs-styleguide) anzusehen, um ein Gespür für seinen Ansatz zu entwickeln und ihn vergleichen zu können. Viele meiner Vorlagen entstanden aus Pair-Programming-Sessions, die [Ward Bell](http://twitter.com/wardbell) und ich hatten. Mein Freund Ward hat sicherlich die endgültige Entwicklung dieser Anleitung beeinflusst. ## Schauen Sie sich die Vorlagen in einer Beispielanwendung an -Während diese Anleitung das *Was*, *Warum* und *Wie* erklärt, finde ich es ebenso hilfreich, sie auch in der Praxis zu sehen. Diese Anleitung wird von einer Beispielanwendung begleitet, die diesen Vorlagen und Mustern folgt. Sie finden die [Beispielanwendung (namens "modular") hier] (https://github.com/johnpapa/ng-demos) im `modular`-Ordner. Fühlen Sie sich frei, sich diese zu holen, indem Sie sie clonen oder einen Fork erstellen.[Anweisungen, sie zum Laufen zu bringen, finden Sie im Readme](https://github.com/johnpapa/ng-demos/tree/master/modular). +Während diese Anleitung das *Was*, *Warum* und *Wie* erklärt, finde ich es ebenso hilfreich, sie auch in der Praxis zu sehen. Diese Anleitung wird von einer Beispielanwendung begleitet, die diesen Vorlagen und Mustern folgt. Sie finden die [Beispielanwendung (namens "modular") hier] (https://github.com/johnpapa/ng-demos) im `modular`-Ordner. Fühlen Sie sich frei, diese zu holen, indem Sie sie clonen oder einen Fork erstellen.[Anweisungen, sie zum Laufen zu bringen, finden Sie im Readme](https://github.com/johnpapa/ng-demos/tree/master/modular). ##Übersetzungen [Übersetzungen dieses Styleguides](https://github.com/johnpapa/angular-styleguide/tree/master/i18n) werden von der Community hier verwaltet. @@ -67,7 +67,7 @@ Während diese Anleitung das *Was*, *Warum* und *Wie* erklärt, finde ich es ebe - Definiere eine Komponente pro Datei. - Das folgende Beispoiel definiert das `app`-Modul und seine Abhängigkeiten, einen Controller und eine Factory in ein und derselben Datei. + Das folgende Beispiel definiert das `app`-Modul und seine Abhängigkeiten, einen Controller und eine Factory in ein und derselben Datei. ```javascript /* zu vermeiden */ @@ -119,11 +119,11 @@ Während diese Anleitung das *Was*, *Warum* und *Wie* erklärt, finde ich es ebe ### JavaScript Closures ###### [Style [Y010](#style-y010)] - - Packen sie Angular-Komponenten in eine Funktion, die sich sofort selbst ausführt (Immediately Invoked Function Expression, kurz: IIFE). + - Packen Sie Angular-Komponenten in eine Funktion, die sich sofort selbst ausführt (Immediately Invoked Function Expression, kurz: IIFE). - *Warum?*: Eine IIFE entfernt Variablen aus dem Global Scope. Dies verhindert, dass Variablen- und Funktionsdeklarationen länger als erwartet im global scope bleiben. Und es verhindert zusätzlich, Kollisionen bei Variablen zu verhindern. + *Warum?*: Eine IIFE entfernt Variablen aus dem global scope. Dies verhindert, dass Variablen- und Funktionsdeklarationen länger als erwartet im global scope bleiben. Und es verhindert zusätzlich, Kollisionen bei Variablen zu verhindern. - *Warum?*: Wird Ihr Code für das Deployment auf einem Produktionsserver minifiziert und in einer einzigen Datei zusammengepackt, kann es zur Kollision von Variablen (auch Globalen) kommen. Eine IIFE schützt Sie hiervor, indem sie den Gültigkeitsbereich der Variablen auf die jeweilige Datei beschränkt. + *Warum?*: Wird Ihr Code für das Deployment auf einem Produktionsserver minifiziert und in einer einzigen Datei zusammengepackt, kann es zur Kollision von Variablen (auch globalen) kommen. Eine IIFE schützt Sie hiervor, indem sie den Gültigkeitsbereich der Variablen auf die jeweilige Datei beschränkt. ```javascript /* zu vermeiden */ @@ -185,16 +185,16 @@ Während diese Anleitung das *Was*, *Warum* und *Wie* erklärt, finde ich es ebe ### Namenskollisionen vermeiden ###### [Style [Y020](#style-y020)] - - Benutzen sie eindeutige Namenskonventionen mit Trennzeichen für Untermodule. + - Benutzen Sie eindeutige Namenskonventionen mit Trennzeichen für Untermodule. - *Warum?*: Eindeutige Namen helfen, Kollisionen bei Modulnamen zu verhindern. Trennzeichen helfen, bei der Definition von Modulen und deren Untermodul-Hierarchie. Zum Beispiel kann `app` Ihr Root-Modul sein, während `app.dashboard` und `app.users` Module sein können, die von `app` als Abhängigkeiten genutzt werden. + *Warum?*: Eindeutige Namen helfen Kollisionen bei Modulnamen zu verhindern. Trennzeichen helfen bei der Definition von Modulen und deren Untermodul-Hierarchie. Zum Beispiel kann `app` Ihr Root-Modul sein, während `app.dashboard` und `app.users` Module sein können, die von `app` als Abhängigkeiten genutzt werden. ### Definitionen (auch: Setter) ###### [Style [Y021](#style-y021)] - Deklarieren Sie Module ohne eine Variable, indem Sie die Setter-Syntax verwenden. - *Warum?*: Bei einer Komponente pro Datei besteht kaum die Notwendigkeit, eine Variable für das Modul einzuführen. + *Warum?*: Bei einer Komponente pro Datei besteht kaum die Notwendigkeit eine Variable für das Modul einzuführen. ```javascript /* zu vermeiden */ @@ -224,7 +224,7 @@ Während diese Anleitung das *Was*, *Warum* und *Wie* erklärt, finde ich es ebe - Wenn Sie ein Modul nutzen, vermeiden Sie die Nutzung einer Variablen. Nutzen Sie stattdessen eine Verkettung mit der Getter-Syntax. - *Warum?*: Dies führt zu mehr lesbarem Code und verhindert Variablenkollistionen oder Leaks. + *Warum?*: Dies führt zu mehr lesbarem Code und verhindert Variablenkollisionen oder Leaks. ```javascript /* zu vermeiden */ @@ -248,7 +248,7 @@ Während diese Anleitung das *Was*, *Warum* und *Wie* erklärt, finde ich es ebe - Nur einmal setzen und für alle anderen Instanzen lesen (get). - *Warum?*: Ein Modul sollte nur einmal erstellt werden, ab diesem Punkt an nur noch gelesen werden. + *Warum?*: Ein Modul sollte nur einmal erstellt werden und ab diesem Punkt an nur noch gelesen werden. - Benutzen Sie `angular.module('app', []);` um das Modul zu erzeugen (set). - Benutzen Sie `angular.module('app');` um das Modul zu erhalten (get). @@ -258,7 +258,7 @@ Während diese Anleitung das *Was*, *Warum* und *Wie* erklärt, finde ich es ebe - Benutzen Sie für Callbacks benannte Funktionen, anstatt eine anonyme Funktion zu übergeben. - *Warum?*: Dies führt zu lesbarerem Code, ist einfach zu debuggen und veringert die Schachtelung des Callback-Codes. + *Warum?*: Dies führt zu lesbarerem Code, ist einfach zu debuggen und verringert die Schachtelung des Callback-Codes. ```javascript /* zu vermeiden */ @@ -297,11 +297,11 @@ Während diese Anleitung das *Was*, *Warum* und *Wie* erklärt, finde ich es ebe - Ziehen Sie die [`controllerAs`](http://www.johnpapa.net/do-you-like-your-angular-controllers-with-or-without-sugar/)-Syntax der `klassischen Controller-Mit-$scope`-Syntax vor. - *Warum?*: Controller werden immer wieder neu erstellt. Man erhält jedes Mal eine neue Instanz und die `controllerAs`-Syntax ist näher an der eines JavaScript-Konstruktors, als die`klassische Controller-Mit-$scope-Syntax`. + *Warum?*: Controller werden immer wieder neu erstellt. Man erhält jedes Mal eine neue Instanz und die `controllerAs`-Syntax ist näher an der eines JavaScript-Konstruktors, als die `klassische Controller-Mit-$scope-Syntax`. - *Warum?*: Es begünstigt die Bindung von "Punkt-Notierten" Objekten in der View (z. B. `customer.name` statt `name`), was kontextbezogener und einfacher zu lesen ist und Referenzproblemen, die ohne diese "Punkt-Notation" auftreten können, vorbeugt. + *Warum?*: Es begünstigt die Bindung von "Punkt-Notierten" Objekten im View (z. B. `customer.name` statt `name`), was kontextbezogener und einfacher zu lesen ist und Referenzproblemen, die ohne diese "Punkt-Notation" auftreten können, vorbeugt. - *Warum?*: Hilft, die Nutzung von `$parent`-Aufrufen in Views und geschachtelten Controllern zu vermeiden. + *Warum?*: Hilft die Nutzung von `$parent`-Aufrufen in Views und geschachtelten Controllern zu vermeiden. ```html @@ -324,7 +324,7 @@ Während diese Anleitung das *Was*, *Warum* und *Wie* erklärt, finde ich es ebe - Die `controllerAs`-Syntax nutzt `this` innerhalb des Controllers, welches an `$scope` gebunden wird. - *Warum?*: `controllerAs` stellt eine syntaktische "Versüßung" `$scope` dar. Sie können immer noch Bindungen an die View vornehmen und auf die `$scope`-Methoden zugreifen. + *Warum?*: `controllerAs` stellt eine syntaktische "Versüßung" `$scope` dar. Sie können immer noch Bindungen an dem View vornehmen und auf die `$scope`-Methoden zugreifen. *Warum?*: Hilft, die verführerische Nutzung von `$scope`-Methoden innerhalb eines Controllers zu unterbinden, wenn es besser wäre, sie zu vermeiden oder in eine Factory auszulagern. Man sollte die Nutzung von `$scope` in einer Factory oder einem Controller nur dann in Erwägung ziehen, wenn es notwendig ist. Wenn zum Beispiel Events mit [`$emit`](https://docs.angularjs.org/api/ng/type/$rootScope.Scope#$emit), [`$broadcast`](https://docs.angularjs.org/api/ng/type/$rootScope.Scope#$broadcast) oder [`$on`](https://docs.angularjs.org/api/ng/type/$rootScope.Scope#$on) abonniert oder publiziert werden, sollte man überlegen, diese nicht in eine Factory auszulagern und vom Controller aus auszulösen. @@ -347,7 +347,7 @@ Während diese Anleitung das *Was*, *Warum* und *Wie* erklärt, finde ich es ebe ### controllerAs mit vm ###### [Style [Y032](#style-y032)] - - Benutzen Sie eine Variable, um `this` zu übernehmen, wenn sie die `controllerAs`-Syntax verwenden. Wählen Sie einen konsistenten Variablennanen, wie `vm`, welcher für ViewModel steht. + - Benutzen Sie eine Variable, um `this` zu übernehmen, wenn Sie die `controllerAs`-Syntax verwenden. Wählen Sie einen konsistenten Variablennamen, wie `vm`, welcher für ViewModel steht. *Warum?*: Das `this`-Schlüsselwort ist kontextbezogen und kann diesen Kontext ändern, wenn es innerhalb einer Funktion eines Controllers verwendet wird. Wird der Kontext von `this` übernommen, wird dieses Problem verhindert. @@ -368,14 +368,14 @@ Während diese Anleitung das *Was*, *Warum* und *Wie* erklärt, finde ich es ebe } ``` - Anmerkung: Sie können jegliche [jshint](http://www.jshint.com/)-Warnungen unterbinden, indem sie den Kommentar vor der Codezeile einfügen. Allerdingst ist dies nicht notwendig, wenn die Funktion großgeschrieben ist (UpperCasing). Diese Konvention besagt, dass es sich um eine Kontruktor-Funktion handelt, was einem Controller in Angular entspricht. + Anmerkung: Sie können jegliche [jshint](http://www.jshint.com/)-Warnungen unterbinden, indem Sie den Kommentar vor der Codezeile einfügen. Allerdingst ist dies nicht notwendig, wenn die Funktion großgeschrieben ist (UpperCasing). Diese Konvention besagt, dass es sich um eine Konstruktor-Funktion handelt, was einem Controller in Angular entspricht. ```javascript /* jshint validthis: true */ var vm = this; ``` - Anmerkung: Wenn Sie Watches in einem Controller einsetzen, der über `controller as` genutzt wrid, können Sie die `vm.*`-Member über die folgende Syntax überwachen. (Erstellen Sie Watches mit Vorsicht, denn sie belasten den "digest cycle".) + Anmerkung: Wenn Sie Watches in einem Controller einsetzen, der über `controller as` genutzt wird, können Sie die `vm.*`-Member über die folgende Syntax überwachen. (Erstellen Sie Watches mit Vorsicht, denn sie belasten den "digest cycle".) ```html @@ -396,11 +396,11 @@ Während diese Anleitung das *Was*, *Warum* und *Wie* erklärt, finde ich es ebe ### Zu bindende Bestandteile nach oben ###### [Style [Y033](#style-y033)] - - Platzieren sie zu bindende Elemente alphabeisch sortiert am Anfang des Controllers und nicht verteilt im Code des Controllers. + - Platzieren Sie zu bindende Elemente alphabetisch sortiert am Anfang des Controllers und nicht verteilt im Code des Controllers. - *Warum?*: Die Platzierung von zu bindenden Elementen am Anfang verbessert die Lesbarkeit und hilft Ihnen, die zur Bindung und Nutzung in einer View vorgesehenen Elemente des Controllers schnell zu identifizieren. + *Warum?*: Die Platzierung von zu bindenden Elementen am Anfang verbessert die Lesbarkeit und hilft Ihnen, die zur Bindung und Nutzung in einem View vorgesehenen Elemente des Controllers schnell zu identifizieren. - *Warum?*: Anonyme Funktionen einzusetzen kann einfach sein, aber wenn diese Funktionen die Länge von einer Zeile überschreiten, wird die Lesbarkeit des Codes verschlechtert. Die Definition der Funktionen unterhalb der Deklaration der zur Bindung vorgesehenen Elemente verschiebt die Details der Implementierung nach unten, hält die zu Bindenden Elemente ganz oben und macht es lesbarer (die Funktionen werden quasi "hochgezogen"). + *Warum?*: Anonyme Funktionen einzusetzen kann einfach sein, aber wenn diese Funktionen die Länge von einer Zeile überschreiten, wird die Lesbarkeit des Codes verschlechtert. Die Definition der Funktionen unterhalb der Deklaration der zur Bindung vorgesehenen Elemente verschiebt die Details der Implementierung nach unten, hält die zu bindenden Elemente ganz oben und macht es lesbarer (die Funktionen werden quasi "hochgezogen"). ```javascript /* zu vermeiden */ @@ -448,7 +448,7 @@ Während diese Anleitung das *Was*, *Warum* und *Wie* erklärt, finde ich es ebe ![Controller Using "Above the Fold"](https://raw.githubusercontent.com/johnpapa/angular-styleguide/master/assets/above-the-fold-1.png) - Anmerkung: Falls eine Funktion aus nur einer Zeile bestehen sollte, können Sie sich überlegen, diese nach oben zu verlagen, so lange die Lesbarkeit nicht betroffen ist. + Anmerkung: Falls eine Funktion aus nur einer Zeile bestehen sollte, können Sie sich überlegen, diese nach oben zu verlagern, so lange die Lesbarkeit nicht betroffen ist. ```javascript /* zu vermeiden */ @@ -485,13 +485,13 @@ Während diese Anleitung das *Was*, *Warum* und *Wie* erklärt, finde ich es ebe ### Funktionsdeklarationen, um Details der Implementierung zu verbergen ###### [Style [Y034](#style-y034)] - - Nutzen Sie Funktionsdeklarationen, um Implementierungsdetails zu verbergen. Halten Sie Ihre zur Bindung vorgesehenen Elemente oben. Wenn sie eine Controller-Funktion zur Bindung vorsehen müssen, dann lassen Sie diese auf die Funktionsdeklaration zeigen, die weiter unten erscheint. Diese wird direkt an den Abschnitt mit den zur Bindung vorgesehenen Element geknüpft. Mehr erfahren sie hier in [diesem Beitrag](http://www.johnpapa.net/angular-function-declarations-function-expressions-and-readable-code). + - Nutzen Sie Funktionsdeklarationen, um Implementierungsdetails zu verbergen. Halten Sie Ihre zur Bindung vorgesehenen Elemente oben. Wenn Sie eine Controller-Funktion zur Bindung vorsehen müssen, dann lassen Sie diese auf die Funktionsdeklaration zeigen, die weiter unten erscheint. Diese wird direkt an den Abschnitt mit den zur Bindung vorgesehenen Element geknüpft. Mehr erfahren Sie hier in [diesem Beitrag](http://www.johnpapa.net/angular-function-declarations-function-expressions-and-readable-code). - *Warum?*: Die zur Bindung vorgesehenen Elemente am Anfang zu platzieren, erhöht die Lesbarkeit und hilft Ihnen die Elemente zu identifizieren, die gebunden und in einer View genutzt werden können. (Das Gleiche, wie zuvor.) + *Warum?*: Die zur Bindung vorgesehenen Elemente am Anfang zu platzieren, erhöht die Lesbarkeit und hilft Ihnen die Elemente zu identifizieren, die gebunden und in einem View genutzt werden können. (Das Gleiche, wie zuvor.) - *Warum?*: Das Platzieren der Implementierungsdetails einer Funktion weiter unten in der Datei, hält diese Codemenge außer Sicht und Sie sehen die wichtigen Dinge am Anfang. + *Warum?*: Das Platzieren der Implementierungsdetails einer Funktion weiter unten in der Datei hält diese Codemenge außer Sicht und Sie sehen die wichtigen Dinge am Anfang. - *Warum?*: Funktionsdeklarationen werden "nach oben gezogen" (sog. Hoisting), so dass es keine Probleme damit gibt, ob eine Funktion vor ihrer Benutzung deklariert werden sollte (wie es bei Funktiosausdrücken der Fall wäre). + *Warum?*: Funktionsdeklarationen werden "nach oben gezogen" (sog. Hoisting), so dass es keine Probleme damit gibt, ob eine Funktion vor ihrer Benutzung deklariert werden sollte (wie es bei Funktionsausdrücken der Fall wäre). *Warum?*: Sie müssen sich niemals Sorgen darum machen, wenn Sie in Funktionsdeklarationen `var a` vor `var b` platzieren, weil `a` von `b` abhängig ist. @@ -499,7 +499,7 @@ Während diese Anleitung das *Was*, *Warum* und *Wie* erklärt, finde ich es ebe ```javascript /** - * avoid + * zu vermeiden * Nutzung von Funktionsausdrücken. */ function Avengers(dataservice, logger) { @@ -557,7 +557,7 @@ Während diese Anleitung das *Was*, *Warum* und *Wie* erklärt, finde ich es ebe } ``` -### Verlagern Sie Controller-Logik in Services +### Verlagern Sie Controller-Logik in Services ###### [Style [Y035](#style-y035)] - Verlagern Sie die Logik eines Controllers, indem Sie diese in Services oder Factories übertragen. @@ -620,7 +620,7 @@ Während diese Anleitung das *Was*, *Warum* und *Wie* erklärt, finde ich es ebe ### Halten Sie die Controller auf ihre Aufgabe ausgerichtet ###### [Style [Y037](#style-y037)] - - Definieren Sie einen Controller für eine View und versuchen Sie nicht, diesen Controller für weitere Views zu verwenden. Verlagern Sie stattdessen wiederzuverwendende Logik in Factories und halten Sie den Controller einfach und ausgerichtet auf seine View. + - Definieren Sie einen Controller für einen View und versuchen Sie nicht, diesen Controller für weitere Views zu verwenden. Verlagern Sie stattdessen wiederzuverwendende Logik in Factories und halten Sie den Controller einfach und ausgerichtet auf seinen View. *Warum?*: Controller in mehreren Views wiederzuverwenden ist kritisch und bedingt eine gute End-Zu-End (e2e) Testabdeckung, um die Stabilität in großen Anwendungen zu garantieren. @@ -628,14 +628,14 @@ Während diese Anleitung das *Was*, *Warum* und *Wie* erklärt, finde ich es ebe ### Controller zuweisen ###### [Style [Y038](#style-y038)] - - Wenn ein Controller mit einer View verbunden werden muss und eine der beiden Komponenten aber von anderen Controllern oder Views wiederverwendet werden muss, dann sollten die Controller bei ihren Routen definiert werden. + - Wenn ein Controller mit einem View verbunden werden muss und eine der beiden Komponenten aber von anderen Controllern oder Views wiederverwendet werden muss, dann sollten die Controller bei ihren Routen definiert werden. Anmerkung: Sollte eine View in einem anderen Kontext als einer Route geladen werden, dann benutzen Sie die `ng-controller="Avengers as vm"`-Syntax. - *Warum?*: Wird der Controller inerhalb einer Route verbunden, dann ist es möglich, dass unterschiedliche Routen auch unterschiedliche Controller-View-Bindungen verwenden können. Sind Controller in einer View mit [`ng-controller`](https://docs.angularjs.org/api/ng/directive/ngController) angebunden, dann ist diese View immer mit dem gleichen Controller verbunden. + *Warum?*: Wird der Controller innerhalb einer Route verbunden, dann ist es möglich, dass unterschiedliche Routen auch unterschiedliche Controller-View-Bindungen verwenden können. Sind Controller in einer View mit [`ng-controller`](https://docs.angularjs.org/api/ng/directive/ngController) angebunden, dann ist diese View immer mit dem gleichen Controller verbunden. ```javascript - /* zu vermeiden - bei Nutzung mit eiuner Route, wenn eine dynamische Verbindung gewünscht ist */ + /* zu vermeiden - bei Nutzung mit einer Route, wenn eine dynamische Verbindung gewünscht ist */ // route-config.js angular @@ -687,7 +687,7 @@ Während diese Anleitung das *Was*, *Warum* und *Wie* erklärt, finde ich es ebe ### Singletons ###### [Style [Y040](#style-y040)] - - Services werden mit dem `new`-Schlüsselwort Instantiiert, und benutzen `this` für öffentliche Methoden und Variablen. Auch wenn sie den Factories so ähnlich sind, setzen Sie stattdessen aus Konsistenzgründen eine Factory ein. + - Services werden mit dem `new`-Schlüsselwort instanziiert, und benutzen `this` für öffentliche Methoden und Variablen. Auch wenn sie den Factories so ähnlich sind, setzen Sie stattdessen aus Konsistenzgründen eine Factory ein. Anmerkung: [Alle Angular-Services sind Singletons](https://docs.angularjs.org/guide/services). Das bedeutet, dass es nur eine Instanz eines Services pro Injector gibt. @@ -738,11 +738,11 @@ Während diese Anleitung das *Was*, *Warum* und *Wie* erklärt, finde ich es ebe ### Zugreifbare Bestandteile an den Anfang ###### [Style [Y052](#style-y052)] - - Halten sie die zugreifbaren Bestandteile eines Service (sein Interface) oben, indem Sie eine Technik anwenden, die aus [Revealing Module Pattern](http://addyosmani.com/resources/essentialjsdesignpatterns/book/#revealingmodulepatternjavascript) entlehnt ist. + - Halten Sie die zugreifbaren Bestandteile eines Service (sein Interface) oben, indem Sie eine Technik anwenden, die aus [Revealing Module Pattern](http://addyosmani.com/resources/essentialjsdesignpatterns/book/#revealingmodulepatternjavascript) entlehnt ist. *Warum?*: Die zugreifbaren Bestandteile oben zu platzieren, erhöht die Lesbarkeit und hilft Ihnen, schnell zu identifizieren, welche Elemente des Service aufgerufen werden können und getestet (oder simuliert) werden müssen. - *Warum?*: Dies ist besondert hilfreich, wenn die Datei länger wird, weil ein Scrollen unnötig wird, um zu sehen, was verfügbar ist. + *Warum?*: Dies ist besonders hilfreich, wenn die Datei länger wird, weil ein Scrollen unnötig wird, um zu sehen, was verfügbar ist. *Warum?*: Einfach nur Funktionen einzusetzen kann leicht sein. Wenn diese aber den Umfang einer Zeile überschreiben, kann dies die Lesbarkeit verringern und es muss mehr gescrollt werden. Ein aufrufbares Interface im zurückgelieferten Service zu definieren, verlagert die Implementierungsdetails nach unten, hält das aufrufbare Interface ganz oben und macht es lesbarer. @@ -795,13 +795,13 @@ Während diese Anleitung das *Was*, *Warum* und *Wie* erklärt, finde ich es ebe ### Funktionsdeklarationen, um die Details der Implementierung zu verbergen ###### [Style [Y053](#style-y053)] - - Benutzen Sie Funktionsdeklarationen, um die Details der Implementierung zu verbergen. Halten Sie Ihre zugreifbaren Bestandteile der Factory ganz oben. Lassen Sie diese auf Funktionsdeklarationen verweisen, die weiter unten in der Datei aufeführt werden. Mehr erfahren sie hier in [diesem Beitrag](http://www.johnpapa.net/angular-function-declarations-function-expressions-and-readable-code). + - Benutzen Sie Funktionsdeklarationen, um die Details der Implementierung zu verbergen. Halten Sie Ihre zugreifbaren Bestandteile der Factory ganz oben. Lassen Sie diese auf Funktionsdeklarationen verweisen, die weiter unten in der Datei aufgeführt werden. Mehr erfahren Sie hier in [diesem Beitrag](http://www.johnpapa.net/angular-function-declarations-function-expressions-and-readable-code). *Warum?*: Zugreifbare Elemente am Anfang zu platzieren, erhöht die Lesbarkeit und hilft Ihnen, zu identifizieren, auf welche Funktionen der Factory von außen zugegriffen werden kann. *Warum?*: Das Platzieren der Implementierungsdetails einer Funktion weiter unten in der Datei, hält diese Codemenge außer Sicht und Sie sehen die wichtigen Dinge am Anfang. - *Warum?*: Funktionsdeklarationen werden "nach oben gezogen" (sog. Hoisting), so dass es keine Probleme damit gibt, ob eine Funktion vor ihrer Benutzung deklariert werden sollte (wie es bei Funktiosausdrücken der Fall wäre). + *Warum?*: Funktionsdeklarationen werden "nach oben gezogen" (sog. Hoisting), so dass es keine Probleme damit gibt, ob eine Funktion vor ihrer Benutzung deklariert werden sollte (wie es bei Funktionsausdrücken der Fall wäre). *Warum?*: Sie müssen sich niemals Sorgen darum machen, wenn Sie in Funktionsdeklarationen `var a` vor `var b` platzieren, weil `a` von `b` abhängig ist. @@ -896,13 +896,13 @@ Während diese Anleitung das *Was*, *Warum* und *Wie* erklärt, finde ich es ebe ### Separate Datenzugriffe ###### [Style [Y060](#style-y060)] - - Verlagern sie die Datenzugriffslogik und die Operationen mit Daten in eine Factory Machen Sie die Datenservices verantwortlich für die XHR-Aufrufe, die lokale Speicherung, die Ablage im Speicher oder jede andere Datenoperation. + - Verlagern Sie die Datenzugriffslogik und die Operationen mit Daten in eine Factory Machen Sie die Datenservices verantwortlich für die XHR-Aufrufe, die lokale Speicherung, die Ablage im Speicher oder jede andere Datenoperation. - *Warum?*: Die Verantwortung des Controllers liegt in der Zusammenstellung und Präsentation der Informationen für die und in der View. Er sollte sich nicht darum kümmern müssen, wie er die Daten bekommt, sondern wen er dazu ansprechen muss. Die Datenservices zu trennen verlagert die Logik der Datenermittlung in den Datenservice und belässt den Controller in seiner Einfachheit und seinem Fokus auf die View. + *Warum?*: Die Verantwortung des Controllers liegt in der Zusammenstellung und Präsentation der Informationen für die und in der View. Er sollte sich nicht darum kümmern müssen, wie er die Daten bekommt, sondern wen er dazu ansprechen muss. Die Datenservices zu trennen verlagert die Logik der Datenermittlung in den Datenservice und belässt den Controller in seiner Einfachheit und seinem Fokus auf den View. *Warum?*: Das macht das Testen der Datenabrufe (simuliert oder real) einfacher, wenn man einen Controller testet, der einen Datenservice nutzt. - *Warum?*: Datenserivce-Implementierungen enthalten spezifischen Code, um die Daten zu handhaben. Dies können bestimmte Header sein, die beschreiben, wie mit den Datenquellen oder anderen Services wie `$http` kommuniziert werden muss. Die Separierung dieser Logik in einem Datenservice kapselt sie an einem einzigen Platz und verbirgt die Implementierung vor den Konsumenten dieses Service (z. B. einem Controller). Das macht es auch einfacher, die Implementierung auszutauschen. + *Warum?*: Datenservice-Implementierungen enthalten spezifischen Code, um die Daten zu handhaben. Dies können bestimmte Header sein, die beschreiben, wie mit den Datenquellen oder anderen Services wie `$http` kommuniziert werden muss. Die Separierung dieser Logik in einem Datenservice kapselt sie an einem einzigen Platz und verbirgt die Implementierung vor den Konsumenten dieses Service (z. B. einem Controller). Das macht es auch einfacher, die Implementierung auszutauschen. ```javascript /* empfohlen */ @@ -1108,21 +1108,21 @@ Während diese Anleitung das *Was*, *Warum* und *Wie* erklärt, finde ich es ebe } ``` - Anmerkung: Es gibt viele Bennennungsmöglichkeiten für Direktiven, weil sie in einem schmalen oder weiten Gültigkeitsbereich genutzt werden können. Wählen sie eine, die den Namen der Direktive und ihren Dateinamen eindeutig und klar verständlich macht. Einige Beispiele befinden sich weiter unten, aber schauen Sie sich den Abschnitt zur [Namensgebung](#naming) an, um weitere Empfehlungen zu sehen. + Anmerkung: Es gibt viele Benennungsmöglichkeiten für Direktiven, weil sie in einem schmalen oder weiten Gültigkeitsbereich genutzt werden können. Wählen Sie eine, die den Namen der Direktive und ihren Dateinamen eindeutig und klar verständlich macht. Einige Beispiele befinden sich weiter unten, aber schauen Sie sich den Abschnitt zur [Namensgebung](#naming) an, um weitere Empfehlungen zu sehen. ### DOM-Maniuplation in einer Directive ###### [Style [Y072](#style-y072)] - - Benutzen Sie zur direkten Manipulation des DOM eine Direktive. Wenn es alternative Wege gibt, wie zum Beispiel CSS, um Stile zu setzen oder [Animation Services](https://docs.angularjs.org/api/ngAnimate), Angular Templates, [`ngShow`](https://docs.angularjs.org/api/ng/directive/ngShow) oder [`ngHide`](https://docs.angularjs.org/api/ng/directive/ngHide), dann nutzen sie diese anstatt. Wenn die Direktive zum Beispiel einfach nur etwas versteckt oder zeigt, dann benutzen Sie ngHide/ngShow. + - Benutzen Sie zur direkten Manipulation des DOM eine Direktive. Wenn es alternative Wege gibt, wie zum Beispiel CSS, um Stile zu setzen oder [Animation Services](https://docs.angularjs.org/api/ngAnimate), Angular Templates, [`ngShow`](https://docs.angularjs.org/api/ng/directive/ngShow) oder [`ngHide`](https://docs.angularjs.org/api/ng/directive/ngHide), dann nutzen Sie diese anstatt. Wenn die Direktive zum Beispiel einfach nur etwas versteckt oder zeigt, dann benutzen Sie ngHide/ngShow. *Warum?*: DOM-Manipulationen können schwer zu testen oder zu debuggen sein und es gibt oftmals bessere Wege (z. B. CSS, Animationen oder Templates) -### Vergeben sie einen eindeutigen Prefix für eine Direktive +### Vergeben Sie einen eindeutigen Präfix für eine Direktive ###### [Style [Y073](#style-y073)] - - Vergeben sie einen kurzen, eindeutigen und beschreibenden Prefix für die Direktive, wie `acmeSalesCustomerInfo`. Dieser würde in HTML als `acme-sales-customer-info` genutzt. + - Vergeben Sie einen kurzen, eindeutigen und beschreibenden Präfix für die Direktive, wie `acmeSalesCustomerInfo`. Dieser würde in HTML als `acme-sales-customer-info` genutzt. - *Warum?*: Der eindeutige kurze Prefix gibt den Kontext und den Ursprung der Direktive wieder. Ein Prefix wie `cc-` könnte ausweisen, dass die Direktive Teil einer "CodeCamper"-Anwendung ist, wohingegegen `acme-` auf eine Direktive der Firma Acme hinweisen könnte. + *Warum?*: Der eindeutige kurze Präfix gibt den Kontext und den Ursprung der Direktive wieder. Ein Prefix wie `cc-` könnte ausweisen, dass die Direktive Teil einer "CodeCamper"-Anwendung ist, wohingegegen `acme-` auf eine Direktive der Firma Acme hinweisen könnte. Anmerkung: Vermeiden Sie `ng-`, weil dieser Präfix für Angular-Direktiven reserviert ist. Recherchieren Sie viel genutzte Direktiven, um einem Namenskonflikt wie zum Beispiel mit `ion-` für das [Ionic Framework](http://ionicframework.com/) vorzubeugen. @@ -1320,13 +1320,13 @@ Während diese Anleitung das *Was*, *Warum* und *Wie* erklärt, finde ich es ebe ### Promises beim Aktivieren eines Controllers ###### [Style [Y080](#style-y080)] - - Verlagern sie die Start-Logik eines Controllers in eine `activate`-Funktion. + - Verlagern Sie die Start-Logik eines Controllers in eine `activate`-Funktion. *Warum?*: Ist die Start-Logik an einem einheitlichen Platz innerhalb des Controllers, wird ihr Auffinden vereinfacht, sie ist besser zu testen und diese Methode hilft dabei, zu verhindern, dass die Startlogik überall im Controller verteilt ist. - *Warum?*: Das `activate` ist eine komfortable Art und Weise, diese Logik für einen Refresh des Controllers / der View zu nutzen. Es hält die Logik zusammen, liefert die View schneller an den Benutzer, erleichtert Animationen mit `ng-view` oder `ui-view`, und macht auch einen flotteren Eindruck beim Benutzer. + *Warum?*: Das `activate` ist eine komfortable Art und Weise, diese Logik für einen Refresh des Controllers / der View zu nutzen. Es hält die Logik zusammen, liefert den View schneller an den Benutzer, erleichtert Animationen mit `ng-view` oder `ui-view`, und macht auch einen flotteren Eindruck beim Benutzer. - Anmerkung: Wenn Sie die Routennavigation bedingt abbrechen müssen, bevor der Controller gestartet wird, dann sollten sie stattdessen ein [route resolve](#style-y081) nutzen. + Anmerkung: Wenn Sie die Routennavigation bedingt abbrechen müssen, bevor der Controller gestartet wird, dann sollten Sie stattdessen ein [route resolve](#style-y081) nutzen. ```javascript /* zu vermeiden */ @@ -1367,13 +1367,13 @@ Während diese Anleitung das *Was*, *Warum* und *Wie* erklärt, finde ich es ebe - Ist ein Controller abhängig von der Auflösung eines Promise, der vor der Aktivierung des Controllers aufgelöst sein muss, dann muss diese Abhängigkeit im `$routeProvider` aufgelöst werden, und zwar bevor die Controller-Logik ausgeführt wird. Wenn Sie eine Routen-Navigation bedingt abbrechen müssen, bevor der Controller aktiviert ist, nutzen Sie einen Route-Resolver. - - Nutzen Sie ein "route resolve" wenn Sie bestimmen wollen, ob eine Routennavigation abgebrochen werden soll, bevor die View eingeblendet wird. + - Nutzen Sie ein "route resolve" wenn Sie bestimmen wollen, ob eine Routennavigation abgebrochen werden soll, bevor der View eingeblendet wird. - *Warum?*: Es kann sein, dass ein Controller Daten benötigt, noch bevor er geladen wird. Diese Daten können von einem Promise aus einer Factory oder über [$http](https://docs.angularjs.org/api/ng/service/$http) kommen. Ein ["route resolve"](https://docs.angularjs.org/api/ngRoute/provider/$routeProvider) zu benutzen, ermöglicht, dass der Promise aufgelöst wird, bevor die Controller-Logik ausgeüfhrt wird. Also kann es notwendig werden, eine Aktion aufgrund der Daten aus dem Promis auszuführen. + *Warum?*: Es kann sein, dass ein Controller Daten benötigt, noch bevor er geladen wird. Diese Daten können von einem Promise aus einer Factory oder über [$http](https://docs.angularjs.org/api/ng/service/$http) kommen. Ein ["route resolve"](https://docs.angularjs.org/api/ngRoute/provider/$routeProvider) zu benutzen, ermöglicht, dass der Promise aufgelöst wird, bevor die Controller-Logik ausgeführt wird. Also kann es notwendig werden, eine Aktion aufgrund der Daten aus dem Promis auszuführen. *Warum?*: Der Code wird nach den Routennavigation innerhalb der activate-Funktion des Controllers ausgeführt. Der View wird ebenso geladen. Die Datenbindung steht, wenn der aktive Promise aufgelöst ist. Eine "Busy-Animation" kann während der Einblendung des views (via `ng-view` oder `ui-view`) angezeigt werden. - Anmerkung: Der Code wird vor der Routennavigation über einen Promise ausgeführt. Wird der Promise zurückgewiesen, wird die Navigation abgebrochen. Resolve bewirkt, dass die neue View auf die Auflösung der Route wartet. Ein "Busy-Indikator" kann vor dem Auflösen und während der Einblendung des Views angezeigt werden. Wenn Sie die View schneller einblenden wollen und keinen Kontrollpunkt benötigen, an dem geprüft wird, ob die View überhaupt zur Verfügung steht, sollten Sie die [Controller `activate` Technik](#style-y080) in Betracht ziehen. + Anmerkung: Der Code wird vor der Routennavigation über einen Promise ausgeführt. Wird der Promise zurückgewiesen, wird die Navigation abgebrochen. Resolve bewirkt, dass die neue View auf die Auflösung der Route wartet. Ein "Busy-Indikator" kann vor dem Auflösen und während der Einblendung des Views angezeigt werden. Wenn Sie den View schneller einblenden wollen und keinen Kontrollpunkt benötigen, an dem geprüft wird, ob der View überhaupt zur Verfügung steht, sollten Sie die [Controller `activate` Technik](#style-y080) in Betracht ziehen. ```javascript /* zu vermeiden */ @@ -1472,7 +1472,7 @@ Während diese Anleitung das *Was*, *Warum* und *Wie* erklärt, finde ich es ebe ### Unsichere Minifizierung ###### [Style [Y090](#style-y090)] - - Vermeiden Sie es, die kurze Deklarationssyntax für Ahängigkeiten ohne einen für die Minifizierung sicheren Ansatz zu verwenden. + - Vermeiden Sie es, die kurze Deklarationssyntax für Abhängigkeiten ohne einen für die Minifizierung sicheren Ansatz zu verwenden. *Warum?*: Die Parameter der Komponente (z. B. Controller, Factory, etc.) werden in abgekürzte Variablen gewandelt. So kann zum Beispiel aus `common` und `dataservice` ein `a` oder `b` werden, was von Angular nicht gefunden wird. @@ -1498,7 +1498,7 @@ Während diese Anleitung das *Was*, *Warum* und *Wie* erklärt, finde ich es ebe - Benutzen Sie `$inject` um Ihre Abhängigkeiten für Angular-Komponenten manuell zu identifizieren. - *Warum?*: Dieses Verfahren spiegelt die Technik wieder, die von [`ng-annotate`](https://github.com/olov/ng-annotate) genutzt wird, welche ich für die Automatisierung der Erstellung von minifikationssicheren Abhängigkeiten empfehleh. Wenn `ng-annotate` erkennt, dass eine solche Deklaration vorgenommen wurde, wird diese nicht dupliziert. + *Warum?*: Dieses Verfahren spiegelt die Technik wieder, die von [`ng-annotate`](https://github.com/olov/ng-annotate) genutzt wird, welche ich für die Automatisierung der Erstellung von minifikationssicheren Abhängigkeiten empfehlen. Wenn `ng-annotate` erkennt, dass eine solche Deklaration vorgenommen wurde, wird diese nicht dupliziert. *Warum?*: Dies bewahrt Ihre Abhängigkeiten vor Problemen bei einer Minifizierung, bei der die Parameter abgekürzt werden. Zum Beispiel wird aus `common` und `dataservice` ein `a` oder `b`, was von Angular nicht gefunden wird. @@ -1537,7 +1537,7 @@ Während diese Anleitung das *Was*, *Warum* und *Wie* erklärt, finde ich es ebe } ``` - Anmerkung: Wenn sich Ihre Funktion unterhalb eines returns befindet, kann `$inject` unerreichbar werden (das kann in einer Direktive passieren). Sie können dies vermeiden, indem sie den Controller aus der Direktive herauslösen. + Anmerkung: Wenn sich Ihre Funktion unterhalb eines returns befindet, kann `$inject` unerreichbar werden (das kann in einer Direktive passieren). Sie können dies vermeiden, indem Sie den Controller aus der Direktive herauslösen. ```javascript /* zu vermeiden */ @@ -1659,7 +1659,7 @@ Während diese Anleitung das *Was*, *Warum* und *Wie* erklärt, finde ich es ebe Anmerkung: Entdeckt `ng-annotate` bereits vorhandene Kommentare (z. B. bei erkanntem `@ngInject`), werden die `$inject`-Befehle nicht dupliziert. - Anmerkung: Wenn Sie einen Route Resolver nutzen, können sie die Funktion des Resolvers mit `/* @ngInject */` markieren, und es wird eine korrekte Code-Anmerkung erstellt, die alle eingefügten Abhängigkeiten minifizierungssicher hält. + Anmerkung: Wenn Sie einen Route Resolver nutzen, können Sie die Funktion des Resolvers mit `/* @ngInject */` markieren, und es wird eine korrekte Code-Anmerkung erstellt, die alle eingefügten Abhängigkeiten minifizierungssicher hält. ```javascript // Using @ngInject annotations @@ -1678,13 +1678,13 @@ Während diese Anleitung das *Was*, *Warum* und *Wie* erklärt, finde ich es ebe } ``` - > Anmerkung: Ab der 1.3er Version von Angular können Sie den `ngStrictDi` Parameter der [`ngApp`](https://docs.angularjs.org/api/ng/directive/ngApp)-Direktive nutzen, um potentiell minfizierungsunsichere Abhängigkeiten aufzuspühren. Wurde eine solche Abhängigkeit entdeckt, dann wird der Injector im "strict-di"-Modus erstellt und verursacht Fehler beim Ausfüren von Funktionen, die keine explizite Code-Anmerkung besitzen (was nicht minifizerungssicher ist). Debug-Informationen werden in der Konsole ausgegeben, um den betreffenden Code nachvollziehen zu können. Ich bevorzuge die Nutzung von `ng-strict-di` für das Debugging. + > Anmerkung: Ab der 1.3er Version von Angular können Sie den `ngStrictDi` Parameter der [`ngApp`](https://docs.angularjs.org/api/ng/directive/ngApp)-Direktive nutzen, um potentiell minfizierungsunsichere Abhängigkeiten aufzuspüren. Wurde eine solche Abhängigkeit entdeckt, dann wird der Injector im "strict-di"-Modus erstellt und verursacht Fehler beim Ausführen von Funktionen, die keine explizite Code-Anmerkung besitzen (was nicht minifizerungssicher ist). Debug-Informationen werden in der Konsole ausgegeben, um den betreffenden Code nachvollziehen zu können. Ich bevorzuge die Nutzung von `ng-strict-di` für das Debugging. `` ### Gulp oder Grunt für ng-annotate nutzen ###### [Style [Y101](#style-y101)] - - Benutzen Sie [gulp-ng-annotate](https://www.npmjs.org/package/gulp-ng-annotate) oder [grunt-ng-annotate](https://www.npmjs.org/package/grunt-ng-annotate) in einer autmatisierten Build-Task. Fügen sie `/* @ngInject */` vor jeder Funktion ein, die Abhängigkeiten hat. + - Benutzen Sie [gulp-ng-annotate](https://www.npmjs.org/package/gulp-ng-annotate) oder [grunt-ng-annotate](https://www.npmjs.org/package/grunt-ng-annotate) in einer automatisierten Build-Task. Fügen Sie `/* @ngInject */` vor jeder Funktion ein, die Abhängigkeiten hat. *Warum?*: ng-annotate erkennt die meisten Abhängigkeiten automatisch, benötigt manchmal aber Hinweise durch die `/* @ngInject */`-Syntax. @@ -1721,7 +1721,7 @@ Während diese Anleitung das *Was*, *Warum* und *Wie* erklärt, finde ich es ebe - Benutzen Sie einen [Decorator](https://docs.angularjs.org/api/auto/service/$provide#decorator) während der Konfiguration, indem Sie den [`$provide`](https://docs.angularjs.org/api/auto/service/$provide)-Service im [`$exceptionHandler`](https://docs.angularjs.org/api/ng/service/$exceptionHandler)-Service ansprechen, um eigene Aktionen bei einem auftauchenden Fehler (einer Ausnahme) auszuführen. - *Warum?*: Dies bietet einen einen stimmigen Weg, unbehandelte Angular-Fehler während der Entwicklung oder zur Laufzeit abzufangen. + *Warum?*: Dies bietet einen stimmigen Weg, unbehandelte Angular-Fehler während der Entwicklung oder zur Laufzeit abzufangen. Anmerkung: Eine weitere Option neben der Benutzung eines Decorators, stellt das Überschreiben des Service dar. Diese Möglichkeit ist gut, wenn Sie aber das Standardverhalten beibehalten wollen, dann ist die Erweiterung mit einem Decorator angebracht. @@ -1767,7 +1767,7 @@ Während diese Anleitung das *Was*, *Warum* und *Wie* erklärt, finde ich es ebe *Warum?*: Dies bietet eine konsistente Methode, Fehler abzufangen, die in Ihrem Code geworfen werden (z. B. während eines XHR-Aufrufs oder bei Fehlern in einem Promise). - Anmerkung: Eine Komponente, die die Fehler abfängt stellt eine gute Möglichkeit dar, Fehler an den Stellen abzufangen, von denen Sie wissen, dass sie auftreten können. Zum Beispiel, wenn Sie Daten über einen XHR-Aufruf von einem Webservice anfragen und Sie jegliche Art von Fehler, die von diesem Service zurück kommen, speziell behandeln wollen. + Anmerkung: Eine Komponente, die die Fehler abfängt stellt eine gute Möglichkeit dar, Fehler an den Stellen abzufangen, von denen Sie wissen, dass sie auftreten können. Zum Beispiel, wenn Sie Daten über einen XHR-Aufruf von einem Webservice anfragen und Sie jegliche Art von Fehler, die von diesem Service zurückkommen, speziell behandeln wollen. ```javascript /* empfohlen */ @@ -1798,7 +1798,7 @@ Während diese Anleitung das *Was*, *Warum* und *Wie* erklärt, finde ich es ebe *Warum?*: Bietet einen stimmigen Weg, um alle Routingfehler zu behandeln. - *Warum?*: Bietet potentiell die Möglichkeit die Akzeptanz beim Benutzer zu steigern, wenn ein Routingfehler autftritt und dieser auf informative Weise mit Möglichkeiten zur Behebung am Bildschirm angezeigt wird. + *Warum?*: Bietet potentiell die Möglichkeit die Akzeptanz beim Benutzer zu steigern, wenn ein Routingfehler auftritt und dieser auf informative Weise mit Möglichkeiten zur Behebung am Bildschirm angezeigt wird. ```javascript /* empfohlen */ @@ -1844,7 +1844,7 @@ Während diese Anleitung das *Was*, *Warum* und *Wie* erklärt, finde ich es ebe ### Richtlinien der Namensgebung ###### [Style [Y120](#style-y120)] - - Benutzen sie stimmige Namen für alle Komponenten, einem Muster folgend, welches die Hauptfunktionen (Features) einer Komponente und dann (optional) ihren Typ beschreibt. + - Benutzen Sie stimmige Namen für alle Komponenten, einem Muster folgend, welches die Hauptfunktionen (Features) einer Komponente und dann (optional) ihren Typ beschreibt. Meine empfohlenes Muster ist `feature.typ.js`. Es gibt zwei zu vergebene Namen für die meisten Komponenten: * der Dateiname (`avengers.controller.js`) * der Name der bei Angular zu registrierenden Komponente (`AvengersController`) @@ -1858,7 +1858,7 @@ Während diese Anleitung das *Was*, *Warum* und *Wie* erklärt, finde ich es ebe - Benutzen Sie stimmige Namen für alle Komponenten, die einem Muster folgen: Hauptfunktion einer Komponente, und dann (optional) gefolgt vom Typ. Mein empfohlenes Muster ist `feature.typ.js`. - *Warum?*: Bietet einen stimmigen Weg, Komponenten schnell zu identifizeren. + *Warum?*: Bietet einen stimmigen Weg, Komponenten schnell zu identifizieren. *Warum?*: Bietet ein Suchmuster für alle automatisierten Aufgaben. @@ -1925,7 +1925,7 @@ Während diese Anleitung das *Was*, *Warum* und *Wie* erklärt, finde ich es ebe - Benennen Sie Testspezifikationen gemäß der Komponente, die getestet werden soll, gefolgt vom Suffix `spec`. - *Warum?*: Bietet einen stimmigen Weg, Komponenten schnell zu indentifizieren. + *Warum?*: Bietet einen stimmigen Weg, Komponenten schnell zu identifizieren. *Warum?*: Bietet ein Suchmuster für [karma](http://karma-runner.github.io/) oder andere Testrunner. @@ -1942,11 +1942,11 @@ Während diese Anleitung das *Was*, *Warum* und *Wie* erklärt, finde ich es ebe ### Namen für Controller ###### [Style [Y123](#style-y123)] - - Nutzen Sie stimmige Namen für alle Controller und bennenen Sie diese nach ihrem Hauptmerkmal. Benutzen Sie UpperCamelCase für Controller, weil sie Konstruktoren sind. + - Nutzen Sie stimmige Namen für alle Controller und benennen Sie diese nach ihrem Hauptmerkmal. Benutzen Sie UpperCamelCase für Controller, weil sie Konstruktoren sind. - *Warum?*: Bietet einen stimmigen Weg, Controller schnell zu indentifizieren und zu referenzieren. + *Warum?*: Bietet einen stimmigen Weg, Controller schnell zu identifizieren und zu referenzieren. - *Warum?*: UpperCamelCase ist eine Konvention, ein Objekt zu identifizieren, welches über einen Konstruktor instantiiert werden kann. + *Warum?*: UpperCamelCase ist eine Konvention, ein Objekt zu identifizieren, welches über einen Konstruktor instanziiert werden kann. ```javascript /** @@ -1984,9 +1984,9 @@ Während diese Anleitung das *Was*, *Warum* und *Wie* erklärt, finde ich es ebe ### Namen für Factories ###### [Style [Y125](#style-y125)] - - Nutzen Sie stimmige Namen für alle Factories und vergeben sie diese nach deren Hauptfunktion. Benutzen Sie Camel-Casing für Services und Factroies. Vermeiden Sie es, einer Factory oder einem Service ein `$` voranzutellen. + - Nutzen Sie stimmige Namen für alle Factories und vergeben Sie diese nach deren Hauptfunktion. Benutzen Sie Camel-Casing für Services und Factories. Vermeiden Sie es, einer Factory oder einem Service ein `$` voranzustellen. - *Warum?*: Bietet einen stimmigen Weg, Factories schnell zu identifizeren und zu referenzieren. + *Warum?*: Bietet einen stimmigen Weg, Factories schnell zu identifizieren und zu referenzieren. *Warum?*: Verhindert Namenskollisionen mit eingebauten Factories und Serivces, die `$` als Präfix nutzen. @@ -2008,7 +2008,7 @@ Während diese Anleitung das *Was*, *Warum* und *Wie* erklärt, finde ich es ebe - Benutzen Sie stimmige Namen für alle Direktiven gemäß der Camel-Case-Regel. Nutzen Sie einen kurzen Präfix, um den Bereich zu beschreiben, zu dem die Direktive gehört (Firmen- oder Projekt-Präfix). - *Warum?*: Bietet einen stimmigen Weg, Direktiven schnell zu identifizeren und zu referenzieren. + *Warum?*: Bietet einen stimmigen Weg, Direktiven schnell zu identifizieren und zu referenzieren. ```javascript /** @@ -2037,11 +2037,11 @@ Während diese Anleitung das *Was*, *Warum* und *Wie* erklärt, finde ich es ebe ### Konfiguration ###### [Style [Y128](#style-y128)] - - Trennen Sie die Konfiguration vom Modul und lagern sie diese in eine eigene Datei aus, die nach dem Modul benannt wird. Eine Konfigurationsdatei für das Hauptmodul `app` wird `app.config.js` genannt (oder einfach `config.js`). Eine Konfigurationsdatei für ein Modul namens `admin.module.js` wird `admin.config.js` genannt. + - Trennen Sie die Konfiguration vom Modul und lagern Sie diese in eine eigene Datei aus, die nach dem Modul benannt wird. Eine Konfigurationsdatei für das Hauptmodul `app` wird `app.config.js` genannt (oder einfach `config.js`). Eine Konfigurationsdatei für ein Modul namens `admin.module.js` wird `admin.config.js` genannt. *Warum?*: Trennt Konfiguration von der Moduldefinition, den Komponenten und dem "aktiven" Code. - *Warum?*: Bietet einen leicht zu identifizierenden Platz, um die Kofiguration eines Moduls vorzunehmen. + *Warum?*: Bietet einen leicht zu identifizierenden Platz, um die Konfiguration eines Moduls vorzunehmen. ### Routen ###### [Style [Y129](#style-y129)] @@ -2054,9 +2054,9 @@ Während diese Anleitung das *Was*, *Warum* und *Wie* erklärt, finde ich es ebe ### LIFT ###### [Style [Y140](#style-y140)] - - LIFT steht für `L`ocate (auffinden), `I`dentify (identifizieren), `F`lat (flach), T`ry to stay DRY` (versuchen Sie, Ihren Code nicht zu wiederholen). Das bedeutet also, sie sollten Ihre Anwendung so strukturieren, dass sie Ihren Code schnell auffinden und auf einen Blick identifizieren können, für was der Code gut ist. Dabei sollten Sie die Struktur so flach wie möglich halten. Vermeiden Sie es unbedingt, Ihren Code zu wiederholen. + - LIFT steht für `L`ocate (auffinden), `I`dentify (identifizieren), `F`lat (flach), T`ry to stay DRY` (versuchen Sie, Ihren Code nicht zu wiederholen). Das bedeutet also, Sie sollten Ihre Anwendung so strukturieren, dass Sie Ihren Code schnell auffinden und auf einen Blick identifizieren können, für was der Code gut ist. Dabei sollten Sie die Struktur so flach wie möglich halten. Vermeiden Sie es unbedingt, Ihren Code zu wiederholen. - *Warum LIFT?*: Bietet eine konsistente und gut skalierbare Stuktur, ist modular und macht es einfacher die Effizienz eines Entwicklers zu steigern, weil er seinen Code schneller finden kann. Prüfen Sie Ihre Andwendungsstruktur, indem Sie sich fragen: Wie schnell kann ich all die Dateien, die zu einem Feature gehören öffnen und mit ihnen arbeiten?" + *Warum LIFT?*: Bietet eine konsistente und gut skalierbare Struktur, ist modular und macht es einfacher die Effizienz eines Entwicklers zu steigern, weil er seinen Code schneller finden kann. Prüfen Sie Ihre Anwendungsstruktur, indem Sie sich fragen: Wie schnell kann ich all die Dateien, die zu einem Feature gehören öffnen und mit ihnen arbeiten?" Falls ich mich mit meiner nicht mehr wohl fühle, dann schaue ich mir die LIFT-Anweisungen an: @@ -2093,7 +2093,7 @@ Während diese Anleitung das *Was*, *Warum* und *Wie* erklärt, finde ich es ebe ### Identify (Code identifizieren) ###### [Style [Y142](#style-y142)] - - Wenn Sie einen Dateinamen sehen, sollten sie sofort wissen, was die Datei beinhaltet und für was sie steht. + - Wenn Sie einen Dateinamen sehen, sollten Sie sofort wissen, was die Datei beinhaltet und für was sie steht. *Warum?*: Sie brauchen weniger Zeit, um nach Ihrem Code zu suchen und werden so effizienter. Wenn das bedeutet, dass Sie längere Dateinamen brauchen, dann sei es so. Seien Sie beschreibend bei der Namensvergabe und sorgen Sie dafür, dass eine Datei nur eine Komponente enthält. Vermeiden Sie Dateien mir mehreren Controllern, Services oder gar mit beidem. Ich weiche von dieser Regel ab, wenn ich sehr kleine Features habe, die alle miteinander verbunden und leicht identifizierbar sind. @@ -2102,14 +2102,14 @@ Während diese Anleitung das *Was*, *Warum* und *Wie* erklärt, finde ich es ebe - Halten Sie die Verzeichnisstruktur so lange es geht so flach wie möglich. Sollten mehr als sieben Dateien in einem Verzeichnis stehen, denken Sie über eine Neuaufteilung nach. - *Warum?*: Niemand will Dateien in einer Verzeichnisstruktur über sieben Ebenen suchen. Denken Sie an Menüs von Webseiten ... Alles, was über mehr als zwei Ebenen geht, sollte ernsthaft überdacht werden. Für eine Verzeichnisstruktur gibt es keine feste Regelung, aber sollte ein Verzeichnis sieben bis zehn Dateien enthalten, dann ist es vielleicht an der Zeit, Unterverzeichnisse einzurichten. Machen Sie es für sich selbst an Ihrem Wohlbefinden mit der Struktur fest. Benutzen sie eine flachere Struktur, bis Sie den Punkt erreichen, an dem es Sinn macht, ein neues Verzeichnis zu erstellen. + *Warum?*: Niemand will Dateien in einer Verzeichnisstruktur über sieben Ebenen suchen. Denken Sie an Menüs von Webseiten ... Alles, was über mehr als zwei Ebenen geht, sollte ernsthaft überdacht werden. Für eine Verzeichnisstruktur gibt es keine feste Regelung, aber sollte ein Verzeichnis sieben bis zehn Dateien enthalten, dann ist es vielleicht an der Zeit, Unterverzeichnisse einzurichten. Machen Sie es für sich selbst an Ihrem Wohlbefinden mit der Struktur fest. Benutzen Sie eine flachere Struktur, bis Sie den Punkt erreichen, an dem es Sinn macht, ein neues Verzeichnis zu erstellen. ### T-DRY (Versuchen Sie Ihren Code nicht zu wiederholen) ###### [Style [Y144](#style-y144)] - Seien Sie "DRY": Versuchen Sie Ihren Code nicht zu wiederholen. Aber übertreiben Sie es nicht, indem Sie die Lesbarkeit Ihres Codes dafür opfern. - *Warum?*: Sich nicht ständig zu wiederholen ist wichtig, aber nicht entscheident, wenn Sie dafür andere Punkte von LIFT opfern. Ich möchte für eine View nicht session-view.html tippen, da es ja offentlichtlich eine View ist. Wenn etwas nicht offensichtlich oder einer Konvention unterliegt, dann benenne ich es. + *Warum?*: Sich nicht ständig zu wiederholen ist wichtig, aber nicht entscheidend, wenn Sie dafür andere Punkte von LIFT opfern. Ich möchte für eine View nicht session-view.html tippen, da es ja öffentlich eine View ist. Wenn etwas nicht offensichtlich oder einer Konvention unterliegt, dann benenne ich es. **[Zurück zum Anfang](#table-of-contents)** @@ -2118,21 +2118,21 @@ Während diese Anleitung das *Was*, *Warum* und *Wie* erklärt, finde ich es ebe ### Allgemeine Richtlinien ###### [Style [Y150](#style-y150)] - - Sie sollten eine kurzfristige und langfristive Sicht auf Ihre Implemtierung haben. Das bedeutet: Fangen Sie klein an, behalten Sie dabei aber im Auge, wohin Sie mir Ihrer Anwendung wollen. Jeder Code der Anwendung wird in einem Stammverzeichnis namens `app` abgelegt. Für den Inhalt gilt: Ein Feature pro Datei. Jeder Controller, Service, jedes Modul, jede View befindet sich in ihrer/seiner eigenen Datei. Alle externen Scripts (3rd Party Bibliotheken) werden in einem anderen Stammverzeichnis, nicht aber im `app`-Verzeichnis abgelegt. Ich habe sie nicht geschrieben und ich möchte nicht, dass sie meine Anwendung durcheinander bringen.(`bower_components`, `scripts`, `lib`). + - Sie sollten eine kurzfristige und langfristige Sicht auf Ihre Implementierung haben. Das bedeutet: Fangen Sie klein an, behalten Sie dabei aber im Auge, wohin Sie mir Ihrer Anwendung wollen. Jeder Code der Anwendung wird in einem Stammverzeichnis namens `app` abgelegt. Für den Inhalt gilt: Ein Feature pro Datei. Jeder Controller, Service, jedes Modul, jede View befindet sich in ihrer/seiner eigenen Datei. Alle externen Scripts (3rd Party Bibliotheken) werden in einem anderen Stammverzeichnis, nicht aber im `app`-Verzeichnis abgelegt. Ich habe sie nicht geschrieben und ich möchte nicht, dass sie meine Anwendung durcheinander bringen.(`bower_components`, `scripts`, `lib`). Anmerkung: Sie finden mehr Details und Gründe für diese Struktur in [diesem Originalbeitrag zur Anwendungsstruktur](http://www.johnpapa.net/angular-app-structuring-guidelines/). ### Layout ###### [Style [Y151](#style-y151)] - - Platzieren Sie Komponenten, die das allgemeingültige Layout der Anwendung ausmachen, in einem Verzeichnis namens `layout`. Dieses sollte eine Shell-View mit Controller enthalten. Die View agiert als Container für die Anwendung und enthält die Anwendung an sich: Navigation, Menüs, Bereiche für die Inhalte und andere Bereiche. + - Platzieren Sie Komponenten, die das allgemeingültige Layout der Anwendung ausmachen, in einem Verzeichnis namens `layout`. Dieses sollte eine Shell-View mit Controller enthalten. Der View agiert als Container für die Anwendung und enthält die Anwendung an sich: Navigation, Menüs, Bereiche für die Inhalte und andere Bereiche. - *Warum?*: Organzisieren Sie das Layout an einem einzigen Ort, damit es innerhalb der Anwendung von überall her genutzt werden kann. + *Warum?*: Organisieren Sie das Layout an einem einzigen Ort, damit es innerhalb der Anwendung von überall her genutzt werden kann. -### Vezeichnisse nach Hauptmerkmalen +### Verzeichnisse nach Hauptmerkmalen ###### [Style [Y152](#style-y152)] - - Erstellen Sie Verzeichnisse gemäß der Hauptmerkmale, die sie darstellen. Wenn der Inhalt eines Verzeichnisse wächst und mehr als sieben Dateien fasst, sollten Sie darüber nachdenken, ein neues Verzeichnis zu erstellen. Dabei ist der Grenzwert aber individuell. + - Erstellen Sie Verzeichnisse gemäß der Hauptmerkmale, die sie darstellen. Wenn der Inhalt eines Verzeichnisses wächst und mehr als sieben Dateien fasst, sollten Sie darüber nachdenken, ein neues Verzeichnis zu erstellen. Dabei ist der Grenzwert aber individuell. *Warum?*: En Entwickler kann den gesuchten Code schnell auffinden, auf einen Blick identifizieren für was jede Datei steht, die Struktur ist so flach wie möglich und es gibt keine redundanten Namen. @@ -2229,26 +2229,26 @@ Während diese Anleitung das *Was*, *Warum* und *Wie* erklärt, finde ich es ebe ## Modularität -### Viele kleine, eigentsändige Module +### Viele kleine, eigenständige Module ###### [Style [Y160](#style-y160)] - Erstellen Sie kleine Module, die für eine einzige Aufgabe zuständig sind und diese in sich kapseln. - *Warum?*: Modulare Anwendungen machen es möglich, dass Funktionsmerkmale (Features) einfach eingeklinkt werden können. Somit kann ein Entwicklungsteam vertikale Stücke einer Applikation sukzessive ausrollen. Das bedeutet, dass neue Funtionsmerkmale nach ihrer Entwicklung einfach eingeklink werden können. + *Warum?*: Modulare Anwendungen machen es möglich, dass Funktionsmerkmale (Features) einfach eingeklinkt werden können. Somit kann ein Entwicklungsteam vertikale Stücke einer Applikation sukzessive ausrollen. Das bedeutet, dass neue Funktionsmerkmale nach ihrer Entwicklung einfach eingeklinkt werden können. ### Erstellen Sie ein Modul für die Hauptanwendung (App-Modul) ###### [Style [Y161](#style-y161)] - Erstellen Sie ein Hauptmodul für die Anwendung, dessen Rolle es ist, alle Module und Funktionen der Anwendung zusammenzutragen. Nennen Sie das Modul nach Ihrer Anwendung. - *Warum?*: Angular begünstigt Modularität und Muster für die Aufteilung von Code. Ein Hauptmodul für eine Anwendung zu erstellen, die andere Module zusammenzieht, ist ein einfacher Weg, um Module in eine Anwendung einzuklinken oder aus ihr auskzuklinken. + *Warum?*: Angular begünstigt Modularität und Muster für die Aufteilung von Code. Ein Hauptmodul für eine Anwendung zu erstellen, die andere Module zusammenzieht, ist ein einfacher Weg, um Module in eine Anwendung einzuklinken oder aus ihr auszuklinken. ### Halten Sie das App-Modul klein ###### [Style [Y162](#style-y162)] - Stellen Sie nur Logik ins App-Modul, die dazu dient, die Anwendungsbestandteile zusammenzuziehen. Features bleiben in ihren eigenen Feature-Modulen. - *Warum?*: Weitere Logik außerhalb der ursprünglichen Aufgabe ins Hauptmodul einzubinden, wie zum Beispiel Datenabfragen, darstellen von Views, oder eine Logik, die nicht zum zusammenziehen der Module dient, bringt Verwirrung. Es wird schwierig, diese Features zu verwalten und auch zu testen. + *Warum?*: Weitere Logik außerhalb der ursprünglichen Aufgabe ins Hauptmodul einzubinden, wie zum Beispiel Datenabfragen, darstellen von Views, oder eine Logik, die nicht zum Zusammenziehen der Module dient, bringt Verwirrung. Es wird schwierig, diese Features zu verwalten und auch zu testen. *Warum?*: Das App-Modul wird zum Manifest, welches die Module aufführt, die die Applikation ausmachen. @@ -2261,7 +2261,7 @@ Während diese Anleitung das *Was*, *Warum* und *Wie* erklärt, finde ich es ebe *Warum?*: Sprints oder Iterationen können sich auf Funktionsbereiche beziehen. Diese können am Ende eines Sprints oder einer Iteration eingebunden werden. - *Warum?*: Die Trennung von Funkstionsbereichen in Module erleichtert das isolierte Testen der Module und deren Wiederverwengung. + *Warum?*: Die Trennung von Funktionsbereichen in Module erleichtert das isolierte Testen der Module und deren Wiederverwendung. ### Wiederverwendbare Bausteine sind Module ###### [Style [Y164](#style-y164)] @@ -2273,7 +2273,7 @@ Während diese Anleitung das *Was*, *Warum* und *Wie* erklärt, finde ich es ebe ### Modulabhängigkeiten ###### [Style [Y165](#style-y165)] - - Das Hauptmodul einer Applikation ist abhängig von den applikationsspezifischen Funktionsmodulen und den allgemeingültigen oder wiedervendbaren Modulen. + - Das Hauptmodul einer Applikation ist abhängig von den applikationsspezifischen Funktionsmodulen und den allgemeingültigen oder wiederverwendbaren Modulen. ![Modularität und Abhängigkeiten](https://raw.githubusercontent.com/johnpapa/angular-styleguide/master/assets/modularity-1.png) @@ -2283,7 +2283,7 @@ Während diese Anleitung das *Was*, *Warum* und *Wie* erklärt, finde ich es ebe *Warum?*: Interne Anwendungsfunktionen wie allgemeingültige Datenservices werden einfach aufgefunden und innerhalb von `app.core` (wählen Sie ihren Lieblingsnamen für diese Modul) genutzt. - Anmerkung: Dies ist eine Strategie, die die Konstistenz innerhalb einer Anwendung begünstigt. Es gibt hierzu viele gute Möglichkeiten. Wählen Sie eine für sich aus, die stimmig ist, den Regeln von Angular in Puncto Abhängigkeiten folgt und einfach zu verwalten und zu skalieren ist. + Anmerkung: Dies ist eine Strategie, die die Konsistenz innerhalb einer Anwendung begünstigt. Es gibt hierzu viele gute Möglichkeiten. Wählen Sie eine für sich aus, die stimmig ist, den Regeln von Angular in Puncto Abhängigkeiten folgt und einfach zu verwalten und zu skalieren ist. > Meine Strukturen unterscheiden sich von Projekt zu Projekt, aber sie folgen allesamt diesen Richtlinien zur Struktur und Modularität. Auch die Implementierung kann sich in Abhängigkeit der benötigten Funktionen und dem Team unterscheiden. Mit anderen Worten: Bestehen Sie nicht auf die exakte Nachbildung der hier vorgestellten Struktur, sondern passen Sie sie Ihren Gegebenheiten an. Behalten Sie dabei Konsistenz, Wartbarkeit und Effizienz im Hinterkopf. @@ -2373,7 +2373,7 @@ Unit-Tests tragen dazu bei, sauberen Code zu erhalten. Daher habe ich einige mei - Schreiben Sie Ihre Tests für jede Anforderung. Beginnen Sie mit einem leeren Test und füllen Sie diesen, während Sie den Code für die Anforderung schreiben. - *Warum?*: Testbeschreibungen zu zu verfassen, hilft dabei festzulegen, was in der Anforderung passiert, was nicht passiert und wie ein Testerfolg gemessen werden kann. + *Warum?*: Testbeschreibungen zu verfassen, hilft dabei festzulegen, was in der Anforderung passiert, was nicht passiert und wie ein Testerfolg gemessen werden kann. ```javascript it('Soll einen Avengers-Controller enthalten', function() { @@ -2402,7 +2402,7 @@ Unit-Tests tragen dazu bei, sauberen Code zu erhalten. Daher habe ich einige mei *Warum?*: Die Nutzung von Jasmin und Mocha ist sehr verbreitet in der Angular-Community. Beide sind stabil, gut gepflegt und liefern robuste Testfunktionen. - Anmerkung: Wenn Sie Moche nutzen, sollten Sie in Erwägung ziehen, eine sogenannte Assert-Library, wie [Chai](http://chaijs.com) zu nutzen. Ich ziehe dem Mocha vor. + Anmerkung: Wenn Sie Mocha nutzen, sollten Sie in Erwägung ziehen, eine sogenannte Assert-Library, wie [Chai](http://chaijs.com) zu nutzen. Ich ziehe dem Mocha vor. ### Testrunner ###### [Style [Y192](#style-y192)] @@ -2413,7 +2413,7 @@ Unit-Tests tragen dazu bei, sauberen Code zu erhalten. Daher habe ich einige mei *Warum?*: Karma hängt sich leicht von allein in einen CI-Prozess (in Grunt oder Gulb) ein. - *Warum?*: Verschiedene IDE'n wie [WebStorm](http://www.jetbrains.com/webstorm/) und [Visual Studio](http://visualstudiogallery.msdn.microsoft.com/02f47876-0e7a-4f6c-93f8-1af5d5189225) haben damit begonnen, Karma einzubinden. + *Warum?*: Verschiedene IDEs wie [WebStorm](http://www.jetbrains.com/webstorm/) und [Visual Studio](http://visualstudiogallery.msdn.microsoft.com/02f47876-0e7a-4f6c-93f8-1af5d5189225) haben damit begonnen, Karma einzubinden. *Warum?*: Karma arbeitet wunderbar mit Task-Managern für Automatisierte Aufgaben wie [Grunt](http://www.gruntjs.com) (with [grunt-karma](https://github.com/karma-runner/grunt-karma)) und [Gulp](http://www.gulpjs.com) (with [gulp-karma](https://github.com/lazd/gulp-karma)) zusammen. @@ -2424,7 +2424,7 @@ Unit-Tests tragen dazu bei, sauberen Code zu erhalten. Daher habe ich einige mei *Warum?*: Sinon arbeitet wunderbar mit Jasmine und Mocha zusammen und erweitert deren Fähigkeiten der Simulation von Komponenten. - *Warum?*: Sinon erleichtert den Wechsel zwischen Jasmine and Mocha, wenn Sie beide ausprobieren möchten. + *Warum?*: Sinon erleichtert den Wechsel zwischen Jasmine und Mocha, wenn Sie beide ausprobieren möchten. *Warum?*: Sinon liefert gut verständliche, beschreibende Meldung, für den Fall, dass ein Test fehlschlägt. @@ -2442,9 +2442,9 @@ Unit-Tests tragen dazu bei, sauberen Code zu erhalten. Daher habe ich einige mei - Lassen Sie JSHint über ihre Tests laufen. - *Warum?*: Tests sind Code. JSHint prüft die Codequalität und kann Qualitätsprobleme aufdecken, die dazu führen können, dass Tests nicht saber laufen. + *Warum?*: Tests sind Code. JSHint prüft die Codequalität und kann Qualitätsprobleme aufdecken, die dazu führen können, dass Tests nicht sauber laufen. -### Erleichternde Rahmenbedingungen for JSHint und Regeln für Tests +### Erleichternde Rahmenbedingungen fur JSHint und Regeln für Tests ###### [Style [Y196](#style-y196)] - Lockern sie die JSHint-Regeln für Ihren Testcode, damit `describe` und `expect` erlaubt werden. Lockern sie die Regeln auch für Ausdrücke, da Mocha diese benutzt. @@ -2470,7 +2470,7 @@ Unit-Tests tragen dazu bei, sauberen Code zu erhalten. Daher habe ich einige mei *Warum?*: Unit-Tests stehen in direktem Bezug zu einer spezifischen Komponente und Datei im Quellcode. - *Warum?*: Es ist einfacher, sie auf dem neuesten Stand zu halten, weil Sie sie immer im Blick haben. Während Sie programmieren (ob Sie jetzt TDD betreiben oder während oder nach der Entwicklung testen), sind die Testspezifikationen weder aus der Sicht noch aus Ihren Gedanken. Deshalt ist es wahrscheinlicher, dass sie auch gepflegt werden, das dazu beiträgt, die Abdeckung des Codes durch Tests zu verbessern. + *Warum?*: Es ist einfacher, sie auf dem neuesten Stand zu halten, weil Sie sie immer im Blick haben. Während Sie programmieren (ob Sie jetzt TDD betreiben oder während oder nach der Entwicklung testen), sind die Testspezifikationen weder aus der Sicht noch aus Ihren Gedanken. Deshalb ist es wahrscheinlicher, dass sie auch gepflegt werden, das dazu beiträgt, die Abdeckung des Codes durch Tests zu verbessern. *Warum?*: Wenn Sie Code aktualisieren ist es einfacher, auch die Tests im gleichen Zuge zu aktualisieren. @@ -2497,7 +2497,7 @@ Unit-Tests tragen dazu bei, sauberen Code zu erhalten. Daher habe ich einige mei ### Anwendung ###### [Style [Y210](#style-y210)] - - Benutzen Sie die ["subtle" Animationen von Angular](https://docs.angularjs.org/guide/animations) um zwischen Stati, Views oder primären sichtbaren Elementen hin und her zu wechseln. Binden Sie das [ngAnimate-Modul](https://docs.angularjs.org/api/ngAnimate) ein. Die drei Schlüssel hierzu sind "subtle", "smooth", "seamless". + - Benutzen Sie die ["subtle" Animationen von Angular](https://docs.angularjs.org/guide/animations) um zwischen Status, Views oder primären sichtbaren Elementen hin und her zu wechseln. Binden Sie das [ngAnimate-Modul](https://docs.angularjs.org/api/ngAnimate) ein. Die drei Schlüssel hierzu sind "subtle", "smooth", "seamless". *Warum?*: Angulars "subtle" Animationen können die User-Experience erhöhen, wenn sie entsprechend eingesetzt werden. @@ -2506,9 +2506,9 @@ Unit-Tests tragen dazu bei, sauberen Code zu erhalten. Daher habe ich einige mei ### Sub Second ###### [Style [Y211](#style-y211)] - - Nutzen Sie eine Kurze Dauer für Animationen. Ich starte immer bei 300ms und passe diese dann entsprechend an. + - Nutzen Sie eine kurze Dauer für Animationen. Ich starte immer bei 300ms und passe diese dann entsprechend an. - *Warum?*: Lange Animationen können sich negativ auf die wahrgenomme Performance auswirken und einen gegentiligen Einfluss auf die User Experience haben und die Anwendung langsam aussehen lassen. + *Warum?*: Lange Animationen können sich negativ auf die wahrgenommene Performance auswirken und einen gegenteiligen Einfluss auf die User Experience haben und die Anwendung langsam aussehen lassen. ### animate.css ###### [Style [Y212](#style-y212)] @@ -2519,7 +2519,7 @@ Unit-Tests tragen dazu bei, sauberen Code zu erhalten. Daher habe ich einige mei *Warum?*: Bietet Konsistenz Ihrer Animationen. - *Warum?*: animate.css ist weit verbeitet und gut getestet. + *Warum?*: animate.css ist weit verbreitet und gut getestet. Anmerkung: Schauen Sie sich diesen [tollen Beitrag von Matias Niemelä über Angular Animationen](http://www.yearofmoo.com/2013/08/remastered-animation-in-angularjs-1-2.html) an. @@ -2749,7 +2749,7 @@ Unit-Tests tragen dazu bei, sauberen Code zu erhalten. Daher habe ich einige mei - Erstellen Sie eine Angular-Konstante für die globalen Variablen aus Bibliotheken von Drittanbietern. - *Warum?*: Bietet einen Weg, Bibliotheken von Drittanbietern in einem sicheren Umfeld anzubieten, die andererseits "Globals" wären. Dies verbessert die Testbarkeit, weil Sie so einfacher die Abhängigkeiten Ihres Codes erfahren (verindert lückenhafte Abstraktionen). Auch die Simulation dieser Abhängigkeiten wird zugelassen, wo sie Sinn macht. + *Warum?*: Bietet einen Weg, Bibliotheken von Drittanbietern in einem sicheren Umfeld anzubieten, die andererseits "Globals" wären. Dies verbessert die Testbarkeit, weil Sie so einfacher die Abhängigkeiten Ihres Codes erfahren (verhindert lückenhafte Abstraktionen). Auch die Simulation dieser Abhängigkeiten wird zugelassen, wo sie Sinn macht. ```javascript // constants.js @@ -2767,13 +2767,13 @@ Unit-Tests tragen dazu bei, sauberen Code zu erhalten. Daher habe ich einige mei ###### [Style [Y241](#style-y241)] - - Benutzen Sie Konstanten für Wete, die sich nicht ändern und nicht aus einem anderen Service kommen. Wenn Konstanten nur für ein bestimmtes Modul gebraucht werden, welches zudem wiederverwendbar sein soll, dann platzieren Sie die Konstanten in einer Datei (pro Modul) und benennen Sie die Datei nach dem Modul. Bis dahin halten Sie die Konstanten im Hauptmodul in einer `constants.js`-Datei. + - Benutzen Sie Konstanten für Werte, die sich nicht ändern und nicht aus einem anderen Service kommen. Wenn Konstanten nur für ein bestimmtes Modul gebraucht werden, welches zudem wiederverwendbar sein soll, dann platzieren Sie die Konstanten in einer Datei (pro Modul) und benennen Sie die Datei nach dem Modul. Bis dahin halten Sie die Konstanten im Hauptmodul in einer `constants.js`-Datei. *Warum?*: Ein Wert, der sich ändert - wenn auch nur unregelmäßig - sollte von einem Service ermittelt werden, so dass er nicht im Quellcode geändert werden muss. Zum Beispiel könnte eine URL für einen Datenservice in einer Konstanten abgelegt werden. Besser wäre es aber, diesen Wert über einen WebService zu ermitteln. *Warum?*: Konstanten können in jede Angular-Komponente (auch in einen Provider) eingefügt werden. - *Warum?*: Ist eine Anwendung in Module unterteilt, die in anderen Anwendungen genutzt werden können, so solte jedes alleinstehende Modul für sich selbst funktionieren, eingeschlossen seiner Konstanten. + *Warum?*: Ist eine Anwendung in Module unterteilt, die in anderen Anwendungen genutzt werden können, so sollte jedes alleinstehende Modul für sich selbst funktionieren, eingeschlossen seiner Konstanten. ```javascript // Konstanten für die gesamte Anwendung @@ -2793,7 +2793,7 @@ Unit-Tests tragen dazu bei, sauberen Code zu erhalten. Daher habe ich einige mei **[Zurück zum Anfang](#table-of-contents)** ## Dateitemplates und Snippets -Nutzen Sie Templates oder Snippets, um stimmigen Richtlinien und Mustern zu folgen. Hier sind Templates oder Snippets für einige Editoren und IDE'n zur Webentwicklung. +Nutzen Sie Templates oder Snippets, um stimmigen Richtlinien und Mustern zu folgen. Hier sind Templates oder Snippets für einige Editoren und IDEs zur Webentwicklung. ### Sublime Text ###### [Style [Y250](#style-y250)] @@ -2830,7 +2830,7 @@ Nutzen Sie Templates oder Snippets, um stimmigen Richtlinien und Mustern zu folg - Angular Dateitemplates, die diesen Mustern und Richtlinien folgen. Sie können sie in Ihre WebStorm-Einstellungen importieren: - Laden Sie die [WebStorm Angular Dateitemplates und Snippets](assets/webstorm-angular-file-template.settings.jar?raw=true) herunter - - Öffnen Sie WebStorm and gehen Sie ins `File`-Menü + - Öffnen Sie WebStorm und gehen Sie ins `File`-Menü - Wählen Sie die `Import Settings` Menüoption - Wählen Sie die Datei aus und klicken Sie `OK` @@ -2890,7 +2890,7 @@ Nutzen Sie Templates oder Snippets, um stimmigen Richtlinien und Mustern zu folg // Dies sind Teilsnippets, die zum Verketten gedacht sind: ngmodule // erstellt einen Angular module getter - ngstate // erstellt eine Angular UI Router State-Defintion + ngstate // erstellt eine Angular UI Router State-Definition ngconfig // definiert eine Funktion für die Konfigurationsphase ngrun // definiert eine Funktion für die Run-Phase ngroute // definiert eine Angular ngRoute 'when'-Definition @@ -2949,7 +2949,7 @@ Das Routing auf der Client-Seite ist für die Erstellung eines Navigationsflusse - Benutzen Sie den [AngularUI Router](http://angular-ui.github.io/ui-router/) für das clientseitige Routing. - *Warum?*: Der UI Router bietet alle Funktionen des Angular Routers und zusätzlich Weitere, wie geschachtelte Routen und Stati. + *Warum?*: Der UI Router bietet alle Funktionen des Angular Routers und zusätzlich Weitere, wie geschachtelte Routen und Status. *Warum?*: Die Syntax ähnelt der des Angular Routers und ist einfach auf den UI Router umzustellen. @@ -3025,24 +3025,24 @@ Das Routing auf der Client-Seite ist für die Erstellung eines Navigationsflusse ###### [Style [Y271](#style-y271)] - - Definieren sie die Routen für die Views in den Modulen, in denen sie enthalten sind. Jedes Modul sollte die Routen seiner Views enthalten. + - Definieren Sie die Routen für die Views in den Modulen, in denen sie enthalten sind. Jedes Modul sollte die Routen seiner Views enthalten. *Warum?*: Jedes Modul sollte für sich allein lauffähig sein. *Warum?*: Wird ein Modul zur Anwendung hinzugefügt oder aus ihr ausgeklinkt, enthält die Anwendung nur Routen, die zu vorhanden Views führen. - *Warum?*: Dies erleichtert es, Teile eine Anwendung zu aktivieren oder zu deaktiveren, ohne dass man sich um verwaiste Routen Sorgen machen muss. + *Warum?*: Dies erleichtert es, Teile eine Anwendung zu aktivieren oder zu deaktivieren, ohne dass man sich um verwaiste Routen Sorgen machen muss. **[Zurück zum Anfang](#table-of-contents)** ## Automatisierung von Aufgaben Nutzen Sie [Gulp](http://gulpjs.com) oder [Grunt](http://gruntjs.com), um Aufgaben zu automatisieren. Bei Gulp geht der Code vor Konfiguration, bei Grund Konfiguration vor Code. Ich persönlich bevorzuge Gulp, weil ich denke, es ist einfacher zu lesen und zu schreiben, aber beide sind erstklassig. -> Erfahren Sie mehr über Gulp und Muster für die Automatisierung von Aufgabenin meinem [Gulp Pluralsight Kurs](http://jpapa.me/gulpps) +> Erfahren Sie mehr über Gulp und Muster für die Automatisierung von Aufgaben in meinem [Gulp Pluralsight Kurs](http://jpapa.me/gulpps) ###### [Style [Y400](#style-y400)] - - Nutzen sie die Automatisierung von Aufgaben, um die Moduldefinitionsdateien `*.module.js` vor allen anderen JavaScript-Dateien in der Anwendung aufzulisten. + - Nutzen Sie die Automatisierung von Aufgaben, um die Moduldefinitionsdateien `*.module.js` vor allen anderen JavaScript-Dateien in der Anwendung aufzulisten. *Warum?*: Angular muss die Moduldefinitionen registrieren, bevor die Module benutzt werden können. @@ -3066,7 +3066,7 @@ Nutzen Sie [Gulp](http://gulpjs.com) oder [Grunt](http://gruntjs.com), um Aufgab - Vermeiden Sie es, Filter dazu zu nutzen, alle Eigenschaften in einem komplexen Objektgraphen zu prüfen. Nutzen Sie Filter um Eigenschaften auszuwählen. - *Warum?*: Filter können sehr leicht missbraucht werden und dann die Performance einer Anwendung negativ beeinflussen, wenn sie nicht überlegt eingesetzt werden. Zum Beispiel: Wenn ein Filter auf einen großen und tief geschachtelten Objektgraphen angewendet wird. + *Warum?*: Filter können sehr leicht missbraucht werden und dann die Performance einer Anwendung negativ beeinflussen, wenn Sie nicht überlegt eingesetzt werden. Zum Beispiel: Wenn ein Filter auf einen großen und tief geschachtelten Objektgraphen angewendet wird. **[Zurück zum Anfang](#table-of-contents)** From 837ebb272efedd2b7280d119256c0ed9ad502f97 Mon Sep 17 00:00:00 2001 From: Jonathas Amaral Date: Sun, 12 Jul 2015 16:45:16 -0300 Subject: [PATCH 329/567] Spelling corrections. --- i18n/PT-BR.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/i18n/PT-BR.md b/i18n/PT-BR.md index 0289257e..376949ad 100644 --- a/i18n/PT-BR.md +++ b/i18n/PT-BR.md @@ -317,7 +317,7 @@ ou *Controladores* ### controllerAs Controller Syntax - - Utilize a sintaxe `controllerAs` ao invés invés da sintaxe `clássica controller com $scope`. + - Utilize a sintaxe `controllerAs` ao invés da sintaxe `clássica controller com $scope`. - A sintaxe `controllerAs` usa o `this` dentro dos controllers que fica ligado ao `$scope`. @@ -1683,7 +1683,7 @@ ou *Nomenclatura* * o nome do arquivo (`avengers.controllers.js`) * o nome de componente registrado pelo Angular (`AvengersController`) - *Por que?*: As convenções de nomenclatura ajudam a fornecer uma maneira consistente de encontrar algo à primeira vista. Consistência dentro do projeto e vital. Consistência dentro de um time é importante. Consistência em toda a empresa proporciona uma enorme eficiência. + *Por que?*: As convenções de nomenclatura ajudam a fornecer uma maneira consistente de encontrar algo à primeira vista. Consistência dentro do projeto é vital. Consistência dentro de um time é importante. Consistência em toda a empresa proporciona uma enorme eficiência. *Por que?*: As convenções de nomenclatura deveriam simplesmente te ajudar a encontrar trechos do seu código mais rápido e torná-lo mais fácil de se entender. From 13b14f918b4be415d06d797a402e2098ce568848 Mon Sep 17 00:00:00 2001 From: mseancole Date: Tue, 14 Jul 2015 22:06:38 -0400 Subject: [PATCH 330/567] Modify Sublime Text Snippets Modify snippets so that they may be used not only on JavaScript files, but also on plain text files (new files). Caveat: Autocompletion does not work on plain text files. You must type "ngcontroller" in full to activate the snippet. --- .../sublime-angular-snippets/angular.controller.sublime-snippet | 2 +- .../sublime-angular-snippets/angular.directive.sublime-snippet | 2 +- assets/sublime-angular-snippets/angular.factory.sublime-snippet | 2 +- assets/sublime-angular-snippets/angular.filter.sublime-snippet | 2 +- assets/sublime-angular-snippets/angular.module.sublime-snippet | 2 +- assets/sublime-angular-snippets/angular.service.sublime-snippet | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/assets/sublime-angular-snippets/angular.controller.sublime-snippet b/assets/sublime-angular-snippets/angular.controller.sublime-snippet index 5e3c7c5f..5a46e787 100644 --- a/assets/sublime-angular-snippets/angular.controller.sublime-snippet +++ b/assets/sublime-angular-snippets/angular.controller.sublime-snippet @@ -23,5 +23,5 @@ })(); ]]> ngcontroller - source.js + text.plain, source.js diff --git a/assets/sublime-angular-snippets/angular.directive.sublime-snippet b/assets/sublime-angular-snippets/angular.directive.sublime-snippet index f2bcf719..4c1c91bf 100644 --- a/assets/sublime-angular-snippets/angular.directive.sublime-snippet +++ b/assets/sublime-angular-snippets/angular.directive.sublime-snippet @@ -36,5 +36,5 @@ })(); ]]> ngdirective - source.js + text.plain, source.js diff --git a/assets/sublime-angular-snippets/angular.factory.sublime-snippet b/assets/sublime-angular-snippets/angular.factory.sublime-snippet index 94dab353..64ed5656 100644 --- a/assets/sublime-angular-snippets/angular.factory.sublime-snippet +++ b/assets/sublime-angular-snippets/angular.factory.sublime-snippet @@ -23,5 +23,5 @@ })(); ]]> ngfactory - source.js + text.plain, source.js diff --git a/assets/sublime-angular-snippets/angular.filter.sublime-snippet b/assets/sublime-angular-snippets/angular.filter.sublime-snippet index 7e1bc54e..784c3673 100644 --- a/assets/sublime-angular-snippets/angular.filter.sublime-snippet +++ b/assets/sublime-angular-snippets/angular.filter.sublime-snippet @@ -19,5 +19,5 @@ })(); ]]> ngfilter - source.js + text.plain, source.js diff --git a/assets/sublime-angular-snippets/angular.module.sublime-snippet b/assets/sublime-angular-snippets/angular.module.sublime-snippet index 663b8666..afb742f9 100644 --- a/assets/sublime-angular-snippets/angular.module.sublime-snippet +++ b/assets/sublime-angular-snippets/angular.module.sublime-snippet @@ -9,5 +9,5 @@ })(); ]]> ngmodule - source.js + text.plain, source.js diff --git a/assets/sublime-angular-snippets/angular.service.sublime-snippet b/assets/sublime-angular-snippets/angular.service.sublime-snippet index e980c4b1..c57ed25f 100644 --- a/assets/sublime-angular-snippets/angular.service.sublime-snippet +++ b/assets/sublime-angular-snippets/angular.service.sublime-snippet @@ -20,5 +20,5 @@ })(); ]]> ngservice - source.js + text.plain, source.js From 4f165472c99ec870f7a78647841418305de44d27 Mon Sep 17 00:00:00 2001 From: Cristopher Jonas de Faria Date: Sat, 18 Jul 2015 13:17:43 -0300 Subject: [PATCH 331/567] update PT-BR - Spelling Correction MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Correction the word "matê-la" for "mantê-la". --- i18n/PT-BR.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/i18n/PT-BR.md b/i18n/PT-BR.md index 376949ad..e1e38852 100644 --- a/i18n/PT-BR.md +++ b/i18n/PT-BR.md @@ -434,7 +434,7 @@ ou *Controladores* ![Controller Using "Above the Fold"](https://raw.githubusercontent.com/johnpapa/angularjs-styleguide/master/assets/above-the-fold-1.png) - Nota: Se a função possuir apenas 1 linha considere matê-la no topo, desde que a legibilidade não seja afetada. + Nota: Se a função possuir apenas 1 linha considere mantê-la no topo, desde que a legibilidade não seja afetada. ```javascript /* evite */ From cad8bdf9079790ebfbac5bda77dfb49a9b497efc Mon Sep 17 00:00:00 2001 From: Benjamin Barbier Date: Tue, 21 Jul 2015 14:54:59 +0200 Subject: [PATCH 332/567] fix(spelling): replace nivigation by navigation --- i18n/fr-FR.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/i18n/fr-FR.md b/i18n/fr-FR.md index ece93b52..65fee277 100644 --- a/i18n/fr-FR.md +++ b/i18n/fr-FR.md @@ -2093,7 +2093,7 @@ Alors que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'a ét ### Layout ###### [Style [Y151](#style-y151)] - - Placez les composants qui définissent le layout principal de l'application dans un répertoire nommé `layout`. Il devrait inclure une vue noyau et le controlleur devrait agir comme conteneur pour l'appli, la nivigation, les menus, les zones de contenu, et les autres régions. + - Placez les composants qui définissent le layout principal de l'application dans un répertoire nommé `layout`. Il devrait inclure une vue noyau et le controlleur devrait agir comme conteneur pour l'appli, la navigation, les menus, les zones de contenu, et les autres régions. *Pourquoi ?* : Organise tout le layout à un seul endroit réutilisé dans l'application. From e1d5180023d865ea321743c118d4e1c0bee6c9e0 Mon Sep 17 00:00:00 2001 From: Randy Date: Wed, 29 Jul 2015 21:43:39 +0800 Subject: [PATCH 333/567] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E9=94=99=E5=AD=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- i18n/zh-CN.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/i18n/zh-CN.md b/i18n/zh-CN.md index 5ed3cf0f..8cfa3bca 100644 --- a/i18n/zh-CN.md +++ b/i18n/zh-CN.md @@ -293,7 +293,7 @@ Angular社区是一个热衷于分享经验的令人难以置信的社区,尽 - 使用[`controllerAs`](http://www.johnpapa.net/do-you-like-your-angular-controllers-with-or-without-sugar/) 语法代替直接用经典的$scope定义的controller的方式。 - *为什么?*:congtroller被构建的时候,就会有一个新的实例,`controllerAs` 的语法比`经典的$scope语法`更接近JavaScript构造函数。 + *为什么?*:controller被构建的时候,就会有一个新的实例,`controllerAs` 的语法比`经典的$scope语法`更接近JavaScript构造函数。 *为什么?*:这促进在View中对绑定到“有修饰”的对象的使用(例如用`customer.name` 代替`name`),这将更有语境、更容易阅读,也避免了任何没有“修饰”而产生的引用问题。 From f5d25dfb32c58c905e9b1c5b77b600f266f5eba5 Mon Sep 17 00:00:00 2001 From: Randy Date: Wed, 29 Jul 2015 23:28:51 +0800 Subject: [PATCH 334/567] Update zh-CN.md --- i18n/zh-CN.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/i18n/zh-CN.md b/i18n/zh-CN.md index 8cfa3bca..9fc68053 100644 --- a/i18n/zh-CN.md +++ b/i18n/zh-CN.md @@ -1247,8 +1247,8 @@ Angular社区是一个热衷于分享经验的令人难以置信的社区,尽 ```html
hello world
-
max={{vm.max}}
-
min={{vm.min}}
+
max={{vm.max}}
+
min={{vm.min}}
``` 注意:当你把controller注入到link的函数或可访问的directive的attributes时,你可以把它命名为控制器的属性。 From 289ed9df500f0a9a5b7387f14a77ca27ded04ba4 Mon Sep 17 00:00:00 2001 From: Denis Ciccale Date: Wed, 29 Jul 2015 19:42:25 +0200 Subject: [PATCH 335/567] fix typo --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 72602a74..635a4788 100644 --- a/README.md +++ b/README.md @@ -1322,7 +1322,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see *Why?*: The controller `activate` makes it convenient to re-use the logic for a refresh for the controller/View, keeps the logic together, gets the user to the View faster, makes animations easy on the `ng-view` or `ui-view`, and feels snappier to the user. - Note: If you need to conditionally cancel the route before you start use the controller, use a [route resolve](#style-y081) instead. + Note: If you need to conditionally cancel the route before you start using the controller, use a [route resolve](#style-y081) instead. ```javascript /* avoid */ From 0b6ae08972cefe7d39d9a15e0ec97252a897f6af Mon Sep 17 00:00:00 2001 From: natee Date: Fri, 31 Jul 2015 17:10:26 +0800 Subject: [PATCH 336/567] shorter text --- i18n/zh-CN.md | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/i18n/zh-CN.md b/i18n/zh-CN.md index f41f989d..64c712b6 100644 --- a/i18n/zh-CN.md +++ b/i18n/zh-CN.md @@ -389,14 +389,14 @@ Angular社区是一个热衷于分享经验的令人难以置信的社区,尽 ``` -###可绑定成员放到顶部 +###置顶绑定成员 ###### [Style [Y033](#style-y033)] - 把可绑定的成员放到controller的顶部,按字母排序,并且不要通过controller的代码传播。 *为什么?*:易读,可以让你立即识别controller中的哪些成员可以在View中绑定和使用。 - *为什么?*:虽然设置单行匿名函数很容易,但是当这些函数的代码超过一行时,这将极大降低代码的可读性。在可绑定成员下面定义函数(这些函数被提出来),把具体的实现细节放到下面,可绑定成员放到顶部,这会提高代码的可读性。 + *为什么?*:虽然设置单行匿名函数很容易,但是当这些函数的代码超过一行时,这将极大降低代码的可读性。在可绑定成员下面定义函数(这些函数被提出来),把具体的实现细节放到下面,可绑定成员置顶,这会提高代码的可读性。 ```javascript /* avoid */ @@ -481,13 +481,13 @@ Angular社区是一个热衷于分享经验的令人难以置信的社区,尽 ###函数声明隐藏实现细节 ###### [Style [Y034](#style-y034)] - - 使用函数声明来隐藏实现细节,把绑定成员放到顶部,当你需要在controller中绑定一个函数时,把它指向一个在文件的后面会出现函数声明。更多详情请看[这里](http://www.johnpapa.net/angular-function-declarations-function-expressions-and-readable-code)。 + - 使用函数声明来隐藏实现细节,置顶绑定成员,当你需要在controller中绑定一个函数时,把它指向一个在文件的后面会出现函数声明。更多详情请看[这里](http://www.johnpapa.net/angular-function-declarations-function-expressions-and-readable-code)。 *为什么?*:易读,易识别哪些成员可以在View中绑定和使用。 *为什么?*:把函数的实现细节放到后面,你可以更清楚地看到重要的东西。 - *为什么?*:由于函数声明会被提到顶部,所以没有必要担心在声明它之前就使用函数的问题。 + *为什么?*:由于函数声明会被置顶,所以没有必要担心在声明它之前就使用函数的问题。 *为什么?*:你再也不用担心当 `a`依赖于 `b`时,把`var a`放到`var b`之前会中断你的代码的函数声明问题。 @@ -730,7 +730,7 @@ Angular社区是一个热衷于分享经验的令人难以置信的社区,尽 注:[所有的Angular services都是单例](https://docs.angularjs.org/guide/services),这意味着每个injector都只有一个实例化的service。 -###可访问的成员放到顶部### +###可访问的成员置顶### ###### [Style [Y052](#style-y052)] - 使用从[显露模块模式](http://addyosmani.com/resources/essentialjsdesignpatterns/book/#revealingmodulepatternjavascript)派生出来的技术把service(它的接口)中可调用的成员暴露到顶部, @@ -739,7 +739,7 @@ Angular社区是一个热衷于分享经验的令人难以置信的社区,尽 *为什么?*:当文件内容很长时,这可以避免需要滚动才能看到暴露了哪些东西。 - *为什么?*:虽然你可以随意写一个函数,但当函数代码超过一行时就会降低可读性并造成滚动。通过把实现细节放下面、可调用接口放到顶部的返回service的方式来定义可调用的接口,从而使代码更加易读。 + *为什么?*:虽然你可以随意写一个函数,但当函数代码超过一行时就会降低可读性并造成滚动。通过把实现细节放下面、把可调用接口置顶的形式返回service的方式来定义可调用的接口,从而使代码更加易读。 ```javascript /* avoid */ @@ -790,13 +790,13 @@ Angular社区是一个热衷于分享经验的令人难以置信的社区,尽 ###函数声明隐藏实现细节 ###### [Style [Y053](#style-y053)] - - 函数声明隐藏实现细节,把绑定成员放到顶部,当你需要在controller中绑定一个函数时,把它指向一个函数声明,这个函数声明在文件的后面会出现。 + - 函数声明隐藏实现细节,置顶绑定成员,当你需要在controller中绑定一个函数时,把它指向一个函数声明,这个函数声明在文件的后面会出现。 *为什么?*:易读,易识别哪些成员可以在View中绑定和使用。 *为什么?*:把函数的实现细节放到后面,你可以更清楚地看到重要的东西。 - *为什么?*:由于函数声明会被提到顶部,所以没有必要担心在声明它之前就使用函数的问题。 + *为什么?*:由于函数声明会被置顶,所以没有必要担心在声明它之前就使用函数的问题。 *为什么?*:你再也不用担心当 `a`依赖于 `b`时,把`var a`放到`var b`之前会中断你的代码的函数声明问题。 From 7afcbe00f9b39701a55d663289838439462af178 Mon Sep 17 00:00:00 2001 From: robsonbittencourt Date: Sun, 2 Aug 2015 14:41:19 -0300 Subject: [PATCH 337/567] Fixed little error Portuguese --- i18n/PT-BR.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/i18n/PT-BR.md b/i18n/PT-BR.md index e1e38852..460a448c 100644 --- a/i18n/PT-BR.md +++ b/i18n/PT-BR.md @@ -22,7 +22,7 @@ Vários de meus estilos vieram de várias sessões de pair-programming (programa Embora este guia explique o **o quê**, **porque** e **como**, acho útil ver tudo isso em prática. Este guia é acompanhado de uma aplicação de exemplo que segue estes estilos e padrões. Você pode encontrar a [aplicação de exemplo (chamada "modular") aqui](https://github.com/johnpapa/ng-demos) na pasta `modular`. Sinta-se livre para pegá-la, cloná-la e *forká-la*. [Instruções de como rodar o aplicativo estão em seu README](https://github.com/johnpapa/ng-demos/tree/master/modular). -> **Nota de tradução**: Os títulos originais de cada seção será mantido, pois caso você queira buscar mais sobre estes assuntos futuramente, fazendo tal busca em inglês será obtido um resultado **imensamente** melhor. +> **Nota de tradução**: Os títulos originais de cada seção serão mantidos, pois caso você queira buscar mais sobre estes assuntos futuramente, fazendo tal busca em inglês será obtido um resultado **imensamente** melhor. > > Após o título, estará a tradução auxiliar, quando necessária, visto que alguns termos são mais facilmente entendidos quando não traduzidos, por fazerem parte do núcleo do estudo em questão. > From 484f001eedd6a006ee1aa60ce584f0f411a37848 Mon Sep 17 00:00:00 2001 From: Vinicius Sabadim Fernandes Date: Mon, 3 Aug 2015 12:01:22 -0300 Subject: [PATCH 338/567] update PT-BR - Spelling Correction --- i18n/PT-BR.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/i18n/PT-BR.md b/i18n/PT-BR.md index e1e38852..77becbf0 100644 --- a/i18n/PT-BR.md +++ b/i18n/PT-BR.md @@ -64,7 +64,7 @@ ou *Responsabilidade Única* - Defina um componente por arquivo. - O exemplo seguinte define um módulo `app` e suas dependências, define um controller e define um factory, todos no mesmo arquivo. + O exemplo seguinte define um módulo `app` e suas dependências, define um controller e define uma factory, todos no mesmo arquivo. ```javascript /* evite */ @@ -145,7 +145,7 @@ ou *Responsabilidade Única* /** * recomendado * - * nenhuma global é deixada para trás + * nada global é deixado para trás */ // logger.js @@ -220,7 +220,7 @@ ou *Evitando Colisão de Nomes* ### *Getters* - - Quando usando um módulo, evite usar as variáveis e então use o encadeamento com a sintaxe *getter*. + - Quando usando um módulo, evite usar uma variável. Em vez disso, use encadeamento com a sintaxe *getter*. **Por que?** Isso produz um código mais legível e evita colisão de variáveis ou vazamentos. @@ -295,7 +295,7 @@ ou *Controladores* - Utilize a sintaxe [`controllerAs`](http://www.johnpapa.net/do-you-like-your-angular-controllers-with-or-without-sugar/) ao invés da sintaxe `clássica controller com $scope`. - **Por que?**: Controllers são construídos, "iniciados", e fornecem um nova instância única, e a sintaxe `controlerAs` é mais próxima de um construtor JavaScript do que a `sintaxe clássica do $scope`. + **Por que?**: Controllers são construídos, "iniciados", e fornecem um nova instância única, e a sintaxe `controllerAs` é mais próxima de um construtor JavaScript do que a `sintaxe clássica do $scope`. **Por que?**: Isso promove o uso do binding de um objeto "pontuado", ou seja, com propriedades na View (ex. `customer.name` ao invés de `name`), que é mais contextual, legível, e evita qualquer problema com referências que podem ocorrer sem a "pontuação" @@ -323,7 +323,7 @@ ou *Controladores* **Por que?**: O `controllerAs` é uma forma mais simples de lidar com o `$scope`. Você ainda poderá fazer o bind para a View e ainda poderá acessar os métodos do `$scope`. - **Por que?**: Ajuda a evitar a tentação de usar o métodos do `$scope` dentro de um controller quando seria melhor evitá-los ou movê-los para um factory. Considere utilizar o `$scope` em um factory, ou em um controller apenas quando necessário. Por exemplo, quando publicar e subscrever eventos usando [`$emit`](https://docs.angularjs.org/api/ng/type/$rootScope.Scope#$emit), [`$broadcast`](https://docs.angularjs.org/api/ng/type/$rootScope.Scope#$broadcast), ou [`$on`](https://docs.angularjs.org/api/ng/type/$rootScope.Scope#$on) considere mover estes casos para um factory e invocá-los a partir do controller. + **Por que?**: Ajuda a evitar a tentação de usar os métodos do `$scope` dentro de um controller quando seria melhor evitá-los ou movê-los para um factory. Considere utilizar o `$scope` em um factory, ou em um controller apenas quando necessário. Por exemplo, quando publicar e subscrever eventos usando [`$emit`](https://docs.angularjs.org/api/ng/type/$rootScope.Scope#$emit), [`$broadcast`](https://docs.angularjs.org/api/ng/type/$rootScope.Scope#$broadcast), ou [`$on`](https://docs.angularjs.org/api/ng/type/$rootScope.Scope#$on) considere mover estes casos para um factory e invocá-los a partir do controller. ```javascript /* evite */ From e59e4fcdd9e2b9d475c766557701bfc1e79813ff Mon Sep 17 00:00:00 2001 From: Vinicius Sabadim Fernandes Date: Mon, 3 Aug 2015 15:00:27 -0300 Subject: [PATCH 339/567] Translating some words and spelling errors --- i18n/PT-BR.md | 48 ++++++++++++++++++++++++------------------------ 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/i18n/PT-BR.md b/i18n/PT-BR.md index e1e38852..265c80d3 100644 --- a/i18n/PT-BR.md +++ b/i18n/PT-BR.md @@ -6,7 +6,7 @@ >The [original English version](http://jpapa.me/ngstyles) is the source of truth, as it is maintained and updated first. -Se você procura por um guia de estilo opinativo para sintaxe, convenções e estruturação de aplicações AngularJS, então siga em frente! Estes estilos são baseados em minha experiência com desenvolvimento com [AngularJS](//angularjs.org), apresentações, [cursos de treinamento na Pluralsight](http://pluralsight.com/training/Authors/Details/john-papa) e trabalhando em equipe. +Se você procura por um guia de estilo opinativo para sintaxe, convenções e estruturação de aplicações AngularJS, então siga em frente! Estes estilos são baseados em minha experiência com desenvolvimento com [AngularJS](//angularjs.org), apresentações, [cursos de treinamento nae Pluralsight](http://pluralsight.com/training/Authors/Details/john-papa) e trabalhando em equipe. > Se você gostar deste guia, confira meu curso [Angular Patterns: Clean Code](http://jpapa.me/ngclean) na Pluralsight. @@ -1074,12 +1074,12 @@ ou *Limite 1 por arquivo* } ``` - Nota: Há diferentes opções de nomear diretivas (directives), especialmente quando elas podem ser usadas em escopes (scopes) variados. Escolha uma que faça a diretiva e o nome do arquivo distinto e simples. Alguns exemplos são mostrados abaixo, mas veja a seção de nomeação para mais recomendações. + Nota: Há diferentes opções de nomear diretivas (directives), especialmente quando elas podem ser usadas em escopos (scopes) variados. Escolha uma que faça a diretiva e o nome do arquivo distinto e simples. Alguns exemplos são mostrados abaixo, mas veja a seção de nomeação para mais recomendações. ### Limit DOM Manipulation ou *Limite a manipulação do DOM* - - Quando estiver manipulando o DOM diretamente, utilize uma diretiva (directive). Se formas alternativas podem ser utilizadas, como utilizar CSS para setar estilos ou [serviços de animação (animation services)](https://docs.angularjs.org/api/ngAnimate), Angular templating, [`ngShow`](https://docs.angularjs.org/api/ng/directive/ngShow) ou [`ngHide`](https://docs.angularjs.org/api/ng/directive/ngHide), então prefira utilizá-los. Por exemplo, se uma diretiva simplesmente esconde ou mostra um elemento, use ngHide/ngShow. + - Quando estiver manipulando o DOM diretamente, utilize uma diretiva (directive). Se formas alternativas podem ser utilizadas, como: utilizar CSS para setar estilos ou [serviços de animação (animation services)](https://docs.angularjs.org/api/ngAnimate), Angular templating, [`ngShow`](https://docs.angularjs.org/api/ng/directive/ngShow) ou [`ngHide`](https://docs.angularjs.org/api/ng/directive/ngHide), então prefira utilizá-los. Por exemplo, se uma diretiva simplesmente esconde ou mostra um elemento, use ngHide/ngShow. **Por que?**: A manipulação do DOM pode ser difícil de testar, debugar, e há melhores maneiras (ex: CSS, animações (animations), templates). @@ -1090,7 +1090,7 @@ ou *Forneça um prefixo único para as diretivas* **Por que?**: Um prefixo curto e único identifica o contexto e a origem da diretiva. Por exemplo, o prefixo `cc-` pode indicar que a diretiva é parte de um aplicativo da CodeCamper, enquanto a diretiva `acme-` pode indicar uma diretiva para a companhia Acme. - Nota: Evite `ng-`, pois são reservadas para as diretivas do AngularJS. Pesquisa largamente as diretivas utilizadas para evitar conflitos de nomes, como `ion-` que são utilizadas para o [Ionic Framework](http://ionicframework.com/). + Nota: Evite `ng-`, pois são reservadas para as diretivas do AngularJS. Pesquise largamente as diretivas utilizadas para evitar conflitos de nomes, como `ion-` que são utilizadas para o [Ionic Framework](http://ionicframework.com/). ### Restrict to Elements and Attributes ou *Restringir para elementos e atributos* @@ -1207,7 +1207,7 @@ ou *Diretivas e "ControladorComo"* ``` ```html - /* example.directive.html */ +
hello world
max={{vm.max}}
min={{vm.min}}
@@ -1266,7 +1266,7 @@ ou *Resolução de promessas na rota* - Quando o controlador (controller) depende de uma promessa ser resolvida, resolva as dependências no `$routeProvider` antes da lógica do controlador (controller) ser executada. Se vocẽ precisa cancelar a rota condicionalmente antes do controlador (controller) ser ativado, utilize uma resolução de rota (route resolve). - **Por que?**: Um controlador (controller) pode precisar de dados antes de ser carregado. Esses dados podem vir de uma promessa (promise) através de uma factory personalizada ou [$http](https://docs.angularjs.org/api/ng/service/$http). Utilizando [resolução de rota (route resolve)](https://docs.angularjs.org/api/ngRoute/provider/$routeProvider) permite as promessas (promises) serem resolvidas antes da lógica do controlador (controller) ser executada, então ele pode executar ações através dos dados dessa promessa (promise). + **Por que?**: Um controlador (controller) pode precisar de dados antes de ser carregado. Esses dados podem vir de uma promessa (promise) através de uma factory personalizada ou [$http](https://docs.angularjs.org/api/ng/service/$http). Utilizar [resolução de rota (route resolve)](https://docs.angularjs.org/api/ngRoute/provider/$routeProvider) permite as promessas (promises) serem resolvidas antes da lógica do controlador (controller) ser executada, então ele pode executar ações através dos dados dessa promessa (promise). ```javascript /* evite */ @@ -1332,7 +1332,7 @@ ou *Não seguro para Minificação* - Evite usar o atalho de sintaxe de declarar dependências sem usar uma abordagem segura para minificação. - *Por que?*: Os parâmetros do componente (por ex. controller, factory, etc) serão convertidos em variáveis encurtadas. Por exemplo, `common` e `dataservice` podem virar `a` ou `b` e não serem encontrados pelo AngularJS. + **Por que?**: Os parâmetros do componente (por ex. controller, factory, etc) serão convertidos em variáveis encurtadas. Por exemplo, `common` e `dataservice` podem virar `a` ou `b` e não serem encontrados pelo AngularJS. ```javascript /* evite - não seguro para minificação*/ @@ -1356,11 +1356,11 @@ ou *Identifique Dependências Manualmente* - Use `$inject` para identificar manualmente suas dependências de componentes do AngularJS. - *Por que?*: Esta técnica espelha a técnica usada por [`ng-annotate`](https://github.com/olov/ng-annotate), a qual eu recomendo para automatizar a criação de dependências seguras para minificação. Se `ng-annotate` detectar que a injeção já foi feita, ela não será duplicada. + **Por que?**: Esta técnica espelha a técnica usada por [`ng-annotate`](https://github.com/olov/ng-annotate), a qual eu recomendo para automatizar a criação de dependências seguras para minificação. Se `ng-annotate` detectar que a injeção já foi feita, ela não será duplicada. - *Por que?*: Isto salvaguarda suas dependências de serem vulneráveis a problemas de minificação quando parâmetros podem ser encurtados. Por exemplo, `common` e `dataservice` podem se tornar `a` ou `b` e não serem encontrados pelo AngularJS. + **Por que?**: Isto salvaguarda suas dependências de serem vulneráveis a problemas de minificação quando parâmetros podem ser encurtados. Por exemplo, `common` e `dataservice` podem se tornar `a` ou `b` e não serem encontrados pelo AngularJS. - *Por que?*: Evite criar dependências in-line pois listas longas podem ser difíceis de ler no array. Além disso, pode ser confuso o array ser uma série de strings enquanto o último item é a função do componente. + **Por que?**: Evite criar dependências in-line pois listas longas podem ser difíceis de ler no array. Além disso, pode ser confuso o array ser uma série de strings enquanto o último item é a função do componente. ```javascript /* evite */ @@ -1430,9 +1430,9 @@ ou *Identifique Dependências do Resolvedor de Rotas Manualmente* - Use $inject para identificar manualmente as dependências do seu resolvedor de rotas para componentes do AngularJS. - *Por que?*: Esta técnica separa a função anônima do resolvedor de rota, tornando-a mais fácil de ler. + **Por que?**: Esta técnica separa a função anônima do resolvedor de rota, tornando-a mais fácil de ler. - *Por que?*: Uma chamada a `$inject` pode facilmente preceder o resolvedor para fazer qualquer dependência segura para minificação. + **Por que?**: Uma chamada a `$inject` pode facilmente preceder o resolvedor para fazer qualquer dependência segura para minificação. ```javascript /* recomendado */ @@ -1463,9 +1463,9 @@ ou *Minificação e Anotação* - Use [ng-annotate](//github.com/olov/ng-annotate) para [Gulp](http://gulpjs.com) ou [Grunt](http://gruntjs.com) e comente as funções que precisam de injeção de dependência automatizada usando `/** @ngInject */` - *Por que?*: Isso protege seu código de qualquer dependência que pode não estar usando práticas seguras para minificação. + **Por que?**: Isso protege seu código de qualquer dependência que pode não estar usando práticas seguras para minificação. - *Por que?*: [`ng-min`](https://github.com/btford/ngmin) está deprecated. + **Por que?**: [`ng-min`](https://github.com/btford/ngmin) está deprecated. > Eu prefiro Gulp pois sinto que é mais fácil de escrever, de ler, e de debugar. @@ -1532,14 +1532,14 @@ ou *Minificação e Anotação* } ``` - > Nota: Apartir do Angular 1.3 use o parâmetro `ngStrictDi` da diretiva [`ngApp`](https://docs.angularjs.org/api/ng/directive/ngApp). Quando presente, o injetor será criado no modo "strict-di" fazendo com que a aplicação falhe ao tentar invocar funções que não usem anotação explícita de função (elas podem não ser seguras para minificação). Informação de debug será logada no console para ajudar a rastrear o código ofensivo. + > Nota: A partir do Angular 1.3 use o parâmetro `ngStrictDi` da diretiva [`ngApp`](https://docs.angularjs.org/api/ng/directive/ngApp). Quando presente, o injetor será criado no modo "strict-di" fazendo com que a aplicação falhe ao tentar invocar funções que não usem anotação explícita de função (elas podem não ser seguras para minificação). Informação de debug será logada no console para ajudar a rastrear o código ofensivo. `` ### Utilize Gulp ou Grunt para o ng-annotate - Utilize [gulp-ng-annotate](https://www.npmjs.org/package/gulp-ng-annotate) ou [grunt-ng-annotate](https://www.npmjs.org/package/grunt-ng-annotate) para tarefas de build automatizadas. Injete `/* @ngInject */` antes de qualquer função que tenha dependências. - *Por que?*: ng-annotate vai capturar todas as dependências, mas as vezes requer dicas utilizando a sintaxe `/* @ngInject */` . + **Por que?**: ng-annotate vai capturar todas as dependências, mas as vezes requer dicas utilizando a sintaxe `/* @ngInject */` . O código abaixo é um exemplo de uma task Gulp utilizando ngAnnotate @@ -1615,7 +1615,7 @@ ou *Coletores de exceção* - Criar um factory que expôe uma interface para capturar e tratar adequadamente as exceções. - *Por que?*: Fornece uma forma consistente de coletar exceções que podem ser lançadas no seu código (ex. durante uma chamada XHR ou uma promessa (promise) que falhou). + **Por que?**: Fornece uma forma consistente de coletar exceções que podem ser lançadas no seu código (ex. durante uma chamada XHR ou uma promessa (promise) que falhou). Nota: O coletor de exceção é bom para coletar e reagir às exceções específicas das chamadas que você sabe que podem ser lançadas. Por exemplo, quando realizar uma chamada XHR que retorna dados de um serviço remoto e você quer coletar qualquer exceção desse serviço, reagindo de uma maneira única. @@ -1645,17 +1645,17 @@ ou *Coletores de exceção* - Gerencie e log todos os erros de routing utilizando o [`$routeChangeError`](https://docs.angularjs.org/api/ngRoute/service/$route#$routeChangeError). - *Por que?*: Fornece uma maneira consistente de gerenciar erros relacionados a routing. + **Por que?**: Fornece uma maneira consistente de gerenciar erros relacionados a routing. - *Por que?*: Potencialmente fornece uma melhor experiência de usuário se um erro de routing ocorrer e você redirecionar o usuário para uma tela amigável com mais detalhes ou opções de recuperação. + **Por que?**: Potencialmente fornece uma melhor experiência de usuário se um erro de routing ocorrer e você redirecionar o usuário para uma tela amigável com mais detalhes ou opções de recuperação. ```javascript /* recomendado */ function handleRoutingErrors() { /** - * Route cancellation: - * On routing error, go to the dashboard. - * Provide an exit clause if it tries to do it twice. + * Cancelamento de rota: + * Quando houver erro no roteamento, vá para o dashboard. + * Forneça uma cláusula de saída se ele tentar fazer isso 2 vezes. */ $rootScope.$on('$routeChangeError', function(event, current, previous, rejection) { @@ -1663,8 +1663,8 @@ ou *Coletores de exceção* 'unknown target'; var msg = 'Error routing to ' + destination + '. ' + (rejection.msg || ''); /** - * Optionally log using a custom service or $log. - * (Don't forget to inject custom service) + * Opcionalmente log usando um serviço customizado ou $log. + * (Não se esqueça de injetar o serviço customizado) */ logger.warning(msg, [current]); } From 1c82ab7b704148ba16638d636320611cf6eb8d89 Mon Sep 17 00:00:00 2001 From: Vinicius Sabadim Fernandes Date: Mon, 3 Aug 2015 15:02:53 -0300 Subject: [PATCH 340/567] Fixing typo --- i18n/PT-BR.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/i18n/PT-BR.md b/i18n/PT-BR.md index 265c80d3..33bd19a0 100644 --- a/i18n/PT-BR.md +++ b/i18n/PT-BR.md @@ -6,7 +6,7 @@ >The [original English version](http://jpapa.me/ngstyles) is the source of truth, as it is maintained and updated first. -Se você procura por um guia de estilo opinativo para sintaxe, convenções e estruturação de aplicações AngularJS, então siga em frente! Estes estilos são baseados em minha experiência com desenvolvimento com [AngularJS](//angularjs.org), apresentações, [cursos de treinamento nae Pluralsight](http://pluralsight.com/training/Authors/Details/john-papa) e trabalhando em equipe. +Se você procura por um guia de estilo opinativo para sintaxe, convenções e estruturação de aplicações AngularJS, então siga em frente! Estes estilos são baseados em minha experiência com desenvolvimento com [AngularJS](//angularjs.org), apresentações, [cursos de treinamento na Pluralsight](http://pluralsight.com/training/Authors/Details/john-papa) e trabalhando em equipe. > Se você gostar deste guia, confira meu curso [Angular Patterns: Clean Code](http://jpapa.me/ngclean) na Pluralsight. From f8d0095c59dec9de7d5f37d65d75e4bc11d43185 Mon Sep 17 00:00:00 2001 From: Vinicius Sabadim Fernandes Date: Mon, 3 Aug 2015 15:50:56 -0300 Subject: [PATCH 341/567] update PT-BR - Spelling Correction --- i18n/PT-BR.md | 46 +++++++++++++++++++++++----------------------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/i18n/PT-BR.md b/i18n/PT-BR.md index 33bd19a0..de37a830 100644 --- a/i18n/PT-BR.md +++ b/i18n/PT-BR.md @@ -1679,13 +1679,13 @@ ou *Nomenclatura* ### Diretrizes de Nomenclatura - - Use nomes consistentes para todos os componentes seguindo um padrão que descreve a funcionalidade do componente e (opcionalmente) seu tipo. Meu padrão recomendado é `característica.tipo.js`. Existem dois nomes para a maioria dos componentes: - * o nome do arquivo (`avengers.controllers.js`) - * o nome de componente registrado pelo Angular (`AvengersController`) + - Use nomes consistentes para todos os componentes seguindo um padrão que descreva a funcionalidade do componente e (opcionalmente) seu tipo. Meu padrão recomendado é `característica.tipo.js`. Existem dois nomes para a maioria dos componentes: + * o nome do arquivo (`avengers.controllers.js`) + * o nome de componente registrado pelo Angular (`AvengersController`) - *Por que?*: As convenções de nomenclatura ajudam a fornecer uma maneira consistente de encontrar algo à primeira vista. Consistência dentro do projeto é vital. Consistência dentro de um time é importante. Consistência em toda a empresa proporciona uma enorme eficiência. + **Por que?**: As convenções de nomenclatura ajudam a fornecer uma maneira consistente de encontrar algo à primeira vista. Consistência dentro do projeto é vital. Consistência dentro de um time é importante. Consistência em toda a empresa proporciona uma enorme eficiência. - *Por que?*: As convenções de nomenclatura deveriam simplesmente te ajudar a encontrar trechos do seu código mais rápido e torná-lo mais fácil de se entender. + **Por que?**: As convenções de nomenclatura deveriam simplesmente te ajudar a encontrar trechos do seu código mais rápido e torná-lo mais fácil de se entender. ### Feature File Names ou *Nome para funcionalidades* @@ -1743,7 +1743,7 @@ ou *Nome para funcionalidades* avenger-profile.directive.spec.js ``` - Nota: Outra convenção comum é nomear arquivos dos controllers sem a palavra `controller` no nome do arquivo como` avengers.js` em vez de `avengers.controller.js`. Todas as outras convenções ainda mantem o uso de um sufixo do tipo. Controllers são o tipo mais comum de componente, portanto isso só economiza digitação e ainda é facilmente identificável. Eu recomendo que você escolha uma convenção que seja mais coerente para sua equipe. + Nota: Outra convenção comum é nomear arquivos dos controllers sem a palavra `controller` no nome do arquivo como` avengers.js` em vez de `avengers.controller.js`. Todas as outras convenções ainda mantêm o uso de um sufixo do tipo. Controllers são o tipo mais comum de componente, portanto isso só economiza digitação e ainda é facilmente identificável. Eu recomendo que você escolha uma convenção que seja mais coerente para sua equipe. ```javascript /** @@ -1759,9 +1759,9 @@ ou *Nome para aquivos de testes* - Nomeie as especificações de testes de forma similar aos componentes que elas testam, com o sufixo `spec`. - *Por que?*: Fornece um modo consistente para identificar rapidamente os componentes. + **Por que?**: Fornece um modo consistente para identificar rapidamente os componentes. - *Por que?*: Fornece padrões de correspondência para o [karma](http://karma-runner.github.io/) ou outros test runners. + **Por que?**: Fornece padrões de correspondência para o [karma](http://karma-runner.github.io/) ou outros test runners. ```javascript /** @@ -1774,13 +1774,13 @@ ou *Nome para aquivos de testes* ``` ### Controller Names -ou *Nome para controllers* +ou *Nomes para controller* - - Use nomes consistentes para todos os controlers nomeados após as sua funcionalidade. Use UpperCamelCase para os controllers, assim como para seus construtores. + - Use nomes consistentes para todos os controllers nomeados após as sua funcionalidade. Use UpperCamelCase para os controllers, assim como para seus construtores. - *Por que?*: Fornece um modo consistente para identificar e referenciar os controllers. + **Por que?**: Fornece um modo consistente para identificar e referenciar os controllers. - *Por que?*: O UpperCamelCase é o modo mais comum para identificar objetos que serão instanciados através de construtores. + **Por que?**: O UpperCamelCase é o modo mais comum para identificar objetos que serão instanciados através de construtores. ```javascript /** @@ -1800,7 +1800,7 @@ ou *sufixo "Controllers"* - Complemente o nome do controller com ou sem o sufixo `Controller`. Escolha uma opção, não ambas. - *Por que?*: O sufixo `Controller` é mais usado e mais descritivo. + **Por que?**: O sufixo `Controller` é mais usado e mais descritivo. ```javascript /** @@ -1829,13 +1829,13 @@ ou *sufixo "Controllers"* ``` ### Factory Names -ou *Nome para factory* +ou *Nomes para factory* - - Use nomes consistentes para todas as factories nomeadas após sua funcionalidade. Use a conveção camelCase para services e factories, e evite prefixos com `$`. + - Use nomes consistentes para todas as factories nomeadas após sua funcionalidade. Use a conveção camelCase para services e factories. Evite prefixos com `$`. - *Por que?*: Fornece um modo consistende de identificar e referenciar rapidamente as factories. + **Por que?**: Fornece um modo consistente de identificar e referenciar rapidamente as factories. - *Por que?*: Evite colisão de nomes com factories e services pré-programadas que usam o prefixo `$`. + **Por que?**: Evite colisão de nomes com factories e services pré-programados que usam o prefixo `$`. ```javascript /** @@ -1851,11 +1851,11 @@ ou *Nome para factory* ``` ### Directive Component Names -ou *Nome para directive* +ou *Nomes para directive* - Use nomes consistentes para todas as directives usando a convenção camelCase. Use um prefixo curto para descrever a área a qual a directive pertence (como prefixo da compania ou do projeto). - *Por que?*: Fornece um modo consistente de identificar e referenciar rapidamente os componentes. + **Por que?**: Fornece um modo consistente de identificar e referenciar rapidamente os componentes. ```javascript /** @@ -1877,18 +1877,18 @@ ou *Módulos* - Quando há vários módulos, o arquivo principal deste módulo é nomeado `app.module.js`, enquanto os módulos dependentes são nomeados de acordo com o que eles representam. Por exemplo, um módulo admin é nomeado `admin.module.js`. Os nomes dos respectivos módulos registrados seriam `app` e `admin`. - *Por que?*: Fornece consistência para múltiplos módulos, e para expansão para grandes aplicações. + **Por que?**: Fornece consistência para múltiplos módulos, e para expansão para grandes aplicações. - *Por que?*: Fornece um modo fácil para automação de tarefas, a fim de carregar todos as definições dos módulos em primeiro lugar, então os demais arquivos (empacotamento). + **Por que?**: Fornece um modo fácil para automação de tarefas, a fim de carregar todos as definições dos módulos em primeiro lugar, então os demais arquivos (empacotamento). ### Configuration ou *Configuração* - Separe a configuração do módulo em seu próprio arquivo, nomeado após o módulo. Um arquivo de configuração para o módulo principal `app` é nomeado `app.config.js` (ou simplesmente `config.js`). Uma configuração para o módulo `admin.module.js` é nomeada `admin.config.js`. - *Por que?*: Separe a configuração do módulo da definição, dos componentes e do código ativo. + **Por que?**: Separa a configuração do módulo da definição, dos componentes e do código ativo. - *Por que?*: Fornece um local identificável para definir as configurações de um módulo. + **Por que?**: Fornece um local identificável para definir as configurações de um módulo. ### Routes ou *Rotas* From a44b1347771ae7eb0312b4d361652d8e9d942bc8 Mon Sep 17 00:00:00 2001 From: John Papa Date: Mon, 3 Aug 2015 21:55:24 -0400 Subject: [PATCH 342/567] jsdoc updated for v2. imitted strict enforcement, but its a good idea --- README.md | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index aaf6b464..cb259d8c 100644 --- a/README.md +++ b/README.md @@ -2712,9 +2712,12 @@ Unit testing helps maintain clean code, as such I included some of my recommenda "disallowSpacesInsideArrayBrackets": "all", "disallowSpacesInsideParentheses": true, - "validateJSDoc": { + "jsDoc": { + "checkAnnotations": true, "checkParamNames": true, - "requireParamTypes": true + "requireParamTypes": true, + "checkReturnTypes": true, + "checkTypes": true }, "disallowMultipleLineBreaks": true, From 0a06e59f4479e4b77da660e7c1b4ad89754ca349 Mon Sep 17 00:00:00 2001 From: Vinicius Sabadim Fernandes Date: Tue, 4 Aug 2015 10:43:03 -0300 Subject: [PATCH 343/567] Translating some words on dependecies chapter --- i18n/PT-BR.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/i18n/PT-BR.md b/i18n/PT-BR.md index 169aaad7..62b463a5 100644 --- a/i18n/PT-BR.md +++ b/i18n/PT-BR.md @@ -1406,7 +1406,7 @@ ou *Identifique Dependências Manualmente* controller: DashboardPanel, }; - DashboardPanel.$inject = ['logger']; // Unreachable + DashboardPanel.$inject = ['logger']; // inacessível function DashboardPanel(logger) { } } @@ -1415,7 +1415,7 @@ ou *Identifique Dependências Manualmente* ```javascript // dentro da definição de diretiva function outer() { - DashboardPanel.$inject = ['logger']; // reachable + DashboardPanel.$inject = ['logger']; // acessível return { controller: DashboardPanel, }; From 9f910cad3986997143de3d1d131df39817e4beae Mon Sep 17 00:00:00 2001 From: John Papa Date: Wed, 5 Aug 2015 08:42:51 -0400 Subject: [PATCH 344/567] karma from gulp --- README.md | 46 +++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 45 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index cb259d8c..9bd99bbc 100644 --- a/README.md +++ b/README.md @@ -2406,7 +2406,51 @@ Unit testing helps maintain clean code, as such I included some of my recommenda *Why?*: Some IDE's are beginning to integrate with Karma, such as [WebStorm](http://www.jetbrains.com/webstorm/) and [Visual Studio](http://visualstudiogallery.msdn.microsoft.com/02f47876-0e7a-4f6c-93f8-1af5d5189225). - *Why?*: Karma works well with task automation leaders such as [Grunt](http://www.gruntjs.com) (with [grunt-karma](https://github.com/karma-runner/grunt-karma)) and [Gulp](http://www.gulpjs.com) (with [gulp-karma](https://github.com/lazd/gulp-karma)). + *Why?*: Karma works well with task automation leaders such as [Grunt](http://www.gruntjs.com) (with [grunt-karma](https://github.com/karma-runner/grunt-karma)) and [Gulp](http://www.gulpjs.com). When using Gulp, use [Karma](https://github.com/karma-runner/karma) directly and not with a plugin as the API can be called directly. + + ```javascript + /// Gulp example with Karma directly + function startTests(singleRun, done) { + var child; + var excludeFiles = []; + var fork = require('child_process').fork; + var karma = require('karma').server; + var serverSpecs = config.serverIntegrationSpecs; + + if (args.startServers) { + log('Starting servers'); + var savedEnv = process.env; + savedEnv.NODE_ENV = 'dev'; + savedEnv.PORT = 8888; + child = fork(config.nodeServer); + } else { + if (serverSpecs && serverSpecs.length) { + excludeFiles = serverSpecs; + } + } + + karma.start({ + configFile: __dirname + '/karma.conf.js', + exclude: excludeFiles, + singleRun: !!singleRun + }, karmaCompleted); + + //////////////// + + function karmaCompleted(karmaResult) { + log('Karma completed'); + if (child) { + log('shutting down the child process'); + child.kill(); + } + if (karmaResult === 1) { + done('karma: tests failed with code ' + karmaResult); + } else { + done(); + } + } + } + ``` ### Stubbing and Spying ###### [Style [Y193](#style-y193)] From 82fa40b40610253cecec8ad4636d0470a121c748 Mon Sep 17 00:00:00 2001 From: John Papa Date: Wed, 5 Aug 2015 08:47:29 -0400 Subject: [PATCH 345/567] formatting --- README.md | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 9bd99bbc..9cd17fb5 100644 --- a/README.md +++ b/README.md @@ -246,8 +246,15 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see *Why?*: A module should only be created once, then retrieved from that point and after. - - Use `angular.module('app', []);` to set a module. - - Use `angular.module('app');` to get a module. + ```javascript + /* recommended */ + + // to set a module + angular.module('app', []); + + // to get a module + angular.module('app'); + ``` ### Named vs Anonymous Functions ###### [Style [Y024](#style-y024)] @@ -2409,7 +2416,9 @@ Unit testing helps maintain clean code, as such I included some of my recommenda *Why?*: Karma works well with task automation leaders such as [Grunt](http://www.gruntjs.com) (with [grunt-karma](https://github.com/karma-runner/grunt-karma)) and [Gulp](http://www.gulpjs.com). When using Gulp, use [Karma](https://github.com/karma-runner/karma) directly and not with a plugin as the API can be called directly. ```javascript - /// Gulp example with Karma directly + /* recommended */ + + // Gulp example with Karma directly function startTests(singleRun, done) { var child; var excludeFiles = []; From d590f617c097ce64e02218c21d9ee3228acd7fa1 Mon Sep 17 00:00:00 2001 From: angelochiello Date: Wed, 5 Aug 2015 15:33:42 +0200 Subject: [PATCH 346/567] [it-IT] PR #472 Updated as PR #472 "karma from gulp" --- i18n/it-IT.md | 48 +++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 47 insertions(+), 1 deletion(-) diff --git a/i18n/it-IT.md b/i18n/it-IT.md index aea42a6b..2407f504 100644 --- a/i18n/it-IT.md +++ b/i18n/it-IT.md @@ -2409,7 +2409,53 @@ Gli unit test aiutano a mantenere il codice più chiaro, perciò ho incluso alcu *Perché?*: Alcuni IDE cominciano ad integrarsi con Karma, come [WebStorm](http://www.jetbrains.com/webstorm/) e [Visual Studio](http://visualstudiogallery.msdn.microsoft.com/02f47876-0e7a-4f6c-93f8-1af5d5189225). - *Perché?*: Karma lavora bene con leader di automazione di processo quali [Grunt](http://www.gruntjs.com) (con [grunt-karma](https://github.com/karma-runner/grunt-karma)) e [Gulp](http://www.gulpjs.com) (con [gulp-karma](https://github.com/lazd/gulp-karma)). + *Perché?*: Karma lavora bene con leader di automazione di processo quali [Grunt](http://www.gruntjs.com) (con [grunt-karma](https://github.com/karma-runner/grunt-karma)) e [Gulp](http://www.gulpjs.com). Quando usi Gulp, usa [Karma](https://github.com/karma-runner/karma) direttamente e non con un plugin dal momento che le API possono essere richiamate direttamente. + + ```javascript + /* consigliato */ + + // Esempio di Gulp che usa direttamente Karma + function startTests(singleRun, done) { + var child; + var excludeFiles = []; + var fork = require('child_process').fork; + var karma = require('karma').server; + var serverSpecs = config.serverIntegrationSpecs; + + if (args.startServers) { + log('Starting servers'); + var savedEnv = process.env; + savedEnv.NODE_ENV = 'dev'; + savedEnv.PORT = 8888; + child = fork(config.nodeServer); + } else { + if (serverSpecs && serverSpecs.length) { + excludeFiles = serverSpecs; + } + } + + karma.start({ + configFile: __dirname + '/karma.conf.js', + exclude: excludeFiles, + singleRun: !!singleRun + }, karmaCompleted); + + //////////////// + + function karmaCompleted(karmaResult) { + log('Karma completed'); + if (child) { + log('shutting down the child process'); + child.kill(); + } + if (karmaResult === 1) { + done('karma: tests failed with code ' + karmaResult); + } else { + done(); + } + } + } + ``` ### Stubbing e Spying ###### [Stile [Y193](#stile-y193)] From d26c1f06373a7fd1737ec9ce1e4736fda4cbcca1 Mon Sep 17 00:00:00 2001 From: angelochiello Date: Wed, 5 Aug 2015 15:37:38 +0200 Subject: [PATCH 347/567] [it.IT] PR #473 Updated as PR #473 "formatting" --- i18n/it-IT.md | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/i18n/it-IT.md b/i18n/it-IT.md index 2407f504..d299de58 100644 --- a/i18n/it-IT.md +++ b/i18n/it-IT.md @@ -249,9 +249,16 @@ Invece usa la più semplice sintassi setter. - Setta solo una volta e prendi (get) per tutte le altre istanze. *Perché?*: Un modulo dovrebbe essere creato solamente una volta, quindi recuperato da lì in avanti. - - - Usa `angular.module('app', []);` per settare un modulo. - - Usa `angular.module('app');` per prendere (get) un modulo. + + ```javascript + /* consigliato */ + + // per creare un modulo + angular.module('app', []); + + // per recuperare un modulo + angular.module('app'); + ``` ### Funzioni con un nome vs funzioni anonime ###### [Stile [Y024](#stile-y024)] From 87457d726cfbf8c51e62b0dad525446b4bfb8678 Mon Sep 17 00:00:00 2001 From: John Papa Date: Wed, 5 Aug 2015 21:47:39 -0400 Subject: [PATCH 348/567] made names more consistent --- README.md | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index 9cd17fb5..f3f9e811 100644 --- a/README.md +++ b/README.md @@ -475,11 +475,11 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see ```javascript /* recommended */ - function Sessions(dataservice) { + function Sessions(sessionDataService) { var vm = this; vm.gotoSession = gotoSession; - vm.refresh = dataservice.refresh; // 1 liner is OK + vm.refresh = sessionDataService.refresh; // 1 liner is OK vm.search = search; vm.sessions = []; vm.title = 'Sessions'; @@ -505,7 +505,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see * avoid * Using function expressions. */ - function Avengers(dataservice, logger) { + function Avengers(avengersService, logger) { var vm = this; vm.avengers = []; vm.title = 'Avengers'; @@ -517,7 +517,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see } var getAvengers = function() { - return dataservice.getAvengers().then(function(data) { + return avengersService.getAvengers().then(function(data) { vm.avengers = data; return vm.avengers; }); @@ -537,7 +537,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see * Using function declarations * and bindable members up top. */ - function Avengers(dataservice, logger) { + function Avengers(avengersService, logger) { var vm = this; vm.avengers = []; vm.getAvengers = getAvengers; @@ -552,7 +552,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see } function getAvengers() { - return dataservice.getAvengers().then(function(data) { + return avengersService.getAvengers().then(function(data) { vm.avengers = data; return vm.avengers; }); @@ -615,7 +615,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see function checkCredit() { return creditService.isOrderTotalOk(vm.total) .then(function(isOk) { vm.isCreditOk = isOk; }) - .catch(showServiceError); + .catch(showError); }; } ``` @@ -1626,14 +1626,14 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see .controller('Avengers', Avengers); /* @ngInject */ - function Avengers(storageService, avengerService) { + function Avengers(storage, avengerService) { var vm = this; vm.heroSearch = ''; vm.storeHero = storeHero; function storeHero() { var hero = avengerService.find(vm.heroSearch); - storageService.save(hero.name, hero); + storage.save(hero.name, hero); } } ``` @@ -1646,18 +1646,18 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see .controller('Avengers', Avengers); /* @ngInject */ - function Avengers(storageService, avengerService) { + function Avengers(storage, avengerService) { var vm = this; vm.heroSearch = ''; vm.storeHero = storeHero; function storeHero() { var hero = avengerService.find(vm.heroSearch); - storageService.save(hero.name, hero); + storage.save(hero.name, hero); } } - Avengers.$inject = ['storageService', 'avengerService']; + Avengers.$inject = ['storage', 'avengerService']; ``` Note: If `ng-annotate` detects injection has already been made (e.g. `@ngInject` was detected), it will not duplicate the `$inject` code. From ee8d6600115f98debb4ea74f5f9789bcb0b3b3ec Mon Sep 17 00:00:00 2001 From: John Papa Date: Wed, 5 Aug 2015 21:52:38 -0400 Subject: [PATCH 349/567] added more clarity to service naming --- README.md | 28 ++++++++++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index f3f9e811..0d041686 100644 --- a/README.md +++ b/README.md @@ -1979,15 +1979,19 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see function AvengersController() { } ``` -### Factory Names +### Factory and Service Names ###### [Style [Y125](#style-y125)] - - Use consistent names for all factories named after their feature. Use camel-casing for services and factories. Avoid prefixing factories and services with `$`. + - Use consistent names for all factories and services named after their feature. Use camel-casing for services and factories. Avoid prefixing factories and services with `$`. Only suffix service and factories with `Service` when it is not clear what they are (i.e. when they are nouns). *Why?*: Provides a consistent way to quickly identify and reference factories. *Why?*: Avoids name collisions with built-in factories and services that use the `$` prefix. + *Why?*: Clear service names such as `logger` do not require a suffix. + + *Why?*: Service names such as `avengers` are nouns and require a suffix and should be named `avengersService`. + ```javascript /** * recommended @@ -2001,6 +2005,26 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see function logger() { } ``` + ```javascript + /** + * recommended + */ + + // credit.service.js + angular + .module + .factory('creditService', creditService); + + function creditService() { } + + // credit.service.js + angular + .module + .service('customersService', customersService); + + function customersService() { } + ``` + ### Directive Component Names ###### [Style [Y126](#style-y126)] From 1f7a4ccc93884ee91f2dd3b91a52c355c82d8347 Mon Sep 17 00:00:00 2001 From: vinicius-sabadim Date: Wed, 5 Aug 2015 23:09:25 -0300 Subject: [PATCH 350/567] Translate for the topic 'LIFT' --- i18n/PT-BR.md | 34 +++++++++++++++++++++------------- 1 file changed, 21 insertions(+), 13 deletions(-) diff --git a/i18n/PT-BR.md b/i18n/PT-BR.md index 62b463a5..9fd7b198 100644 --- a/i18n/PT-BR.md +++ b/i18n/PT-BR.md @@ -1898,24 +1898,28 @@ ou *Rotas* **[De volta ao topo](#tabela-de-conte%C3%BAdo)** ## Application Structure LIFT Principle +ou *Princípio da estrutura LIFT na aplicação* + ### LIFT - - Structure your app such that you can `L`ocate your code quickly, `I`dentify the code at a glance, keep the `F`lattest structure you can, and `T`ry to stay DRY. The structure should follow these 4 basic guidelines. + - Estruture a sua aplicação de um modo onde você possa: `L`ocate (Localizar) seu código rapidamente, `I`dentify (Identificar) o código facilmente, manter a estrutura a mais `F`lattest (Plana) que você conseguir, e `T`ry (Tentar) seguir o conceito de DRY (Don't Repeat Yourself - Não repita a si mesmo). A estrutura deve seguir essas 4 regras básicas. - *Why LIFT?*: Provides a consistent structure that scales well, is modular, and makes it easier to increase developer efficiency by finding code quickly. Another way to check your app structure is to ask yourself: How quickly can you open and work in all of the related files for a feature? + **Por que LIFT?**: Fornece uma estrutura consistente que escala bem, é modular, e torna mais fácil para aumentar a eficiência ao desenvolver, pois encontra-se o código rapidamente. Outra forma de verificar a estrutura da sua aplicação é se perguntar: Quão rápido é para você abrir e trabalhar em todos os arquivos relacionados com uma funcionalidade? - When I find my structure is not feeling comfortable, I go back and revisit these LIFT guidelines + Quando estou sentindo que não estou confortável com a minha estrutura, eu volto e revisito as regras do LIFT - 1. `L`ocating our code is easy - 2. `I`dentify code at a glance - 3. `F`lat structure as long as we can - 4. `T`ry to stay DRY (Don’t Repeat Yourself) or T-DRY + 1. `L`ocating (Localizar) nosso código é fácil + 2. `I`dentify (Identificar) o código rapidamente + 3. `F`lat (Plano) - Deixar a estrutura a mais plana que conseguirmos + 4. `T`ry (Tentar) se manter DRY (Don’t Repeat Yourself - Não repita a si mesmo) ou T-DRY ### Locate +ou *Localizar* - Make locating your code intuitive, simple and fast. + - Torne a localização do seu código: intuitiva, simples e rápida. - *Why?*: I find this to be super important for a project. If the team cannot find the files they need to work on quickly, they will not be able to work as efficiently as possible, and the structure needs to change. You may not know the file name or where its related files are, so putting them in the most intuitive locations and near each other saves a ton of time. A descriptive folder structure can help with this. + **Por que?**: Acho que isso é super importante para um projeto. Se a equipe não pode encontrar rapidamente os arquivos que precisam para trabalhar, eles não serão capazes de trabalhar da forma mais eficiente possível, e a estrutura precisa mudar. Você pode não saber o nome do arquivo ou onde os arquivos relacionados estão, por isso, colocando-os nos locais mais intuitivos e próximos uns dos outros, economiza uma boa parcela de tempo. Uma pasta descrevendo a estrutura pode ajudá-lo. ``` /bower_components @@ -1936,22 +1940,26 @@ ou *Rotas* ``` ### Identify +ou *Identificar* - - When you look at a file you should instantly know what it contains and represents. + - Quando você olhar para um arquivo, prontamente você deve saber o que ele contém e o que representa. - *Why?*: You spend less time hunting and pecking for code, and become more efficient. If this means you want longer file names, then so be it. Be descriptive with file names and keeping the contents of the file to exactly 1 component. Avoid files with multiple controllers, multiple services, or a mixture. There are deviations of the 1 per file rule when I have a set of very small features that are all related to each other, they are still easily identifiable. + **Por que?**: Você gasta menos tempo caçando e procurando por código, e torna-se mais eficiente. Se isso significa nomes de arquivos mais longos, então que assim seja. Seja descritivo nos nomes de arquivos e mantenha o conteúdo do arquivo somente com 1 componente. Evite arquivos com vários controladores (controllers), múltiplos serviços (services), ou uma mistura. Existem exceções de 1 regra por arquivo quando eu tenho um conjunto de recursos muito pequenos que estão todos relacionados uns aos outros, eles ainda são facilmente identificáveis. ### Flat +ou *Plano* - - Keep a flat folder structure as long as possible. When you get to 7+ files, begin considering separation. + - Mantenha uma estrutura plana de pastas o máximo que for possível. Quando você tiver 7 arquivos ou mais, comece a considerar separá-los. - *Why?*: Nobody wants to search 7 levels of folders to find a file. Think about menus on web sites … anything deeper than 2 should take serious consideration. In a folder structure there is no hard and fast number rule, but when a folder has 7-10 files, that may be time to create subfolders. Base it on your comfort level. Use a flatter structure until there is an obvious value (to help the rest of LIFT) in creating a new folder. + **Por que?**: Ninguém quer pesquisar 7 níveis de pastas para encontrar um arquivo. Pense sobre menus em web sites - nada mais profundo do que 2 níveis deve ser levado a sério. Em uma estrutura de pastas não há nenhum número mágico, mas quando uma pasta tem 7-10 arquivos, pode ser a hora de criar subpastas. Baseie-se no seu nível de conforto. Use uma estrutura mais plana até que haja um valor óbvio (para ajudar o resto do LIFT) na criação de uma nova pasta. ### T-DRY (Try to Stick to DRY) +ou *Tente manter-se em DRY - Não repita a si mesmo* - Be DRY, but don't go nuts and sacrifice readability. + - Mantenha-se DRY, mas não fique louco e sacrifique a legibilidade. - *Why?*: Being DRY is important, but not crucial if it sacrifices the others in LIFT, which is why I call it T-DRY. I don’t want to type session-view.html for a view because, well, it’s obviously a view. If it is not obvious or by convention, then I name it. + **Por que?**: Não ficar se repetindo é importante, mas não é crucial se acabar sacrificando os outros itens do LIFT, por isso eu chamo de T-DRY (Tente não ficar se repetindo). Eu não quero escrever session-view.html para uma view, porque obviamente é uma view. Se não é óbvio ou uma convenção, então eu renomeio. **[De volta ao topo](#tabela-de-conte%C3%BAdo)** From bbe0827ac236ddcffe05f270e4470ef0ba695f8c Mon Sep 17 00:00:00 2001 From: vinicius-sabadim Date: Wed, 5 Aug 2015 23:22:36 -0300 Subject: [PATCH 351/567] Forgot some phrases without translate --- i18n/PT-BR.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/i18n/PT-BR.md b/i18n/PT-BR.md index 9fd7b198..35f9cb41 100644 --- a/i18n/PT-BR.md +++ b/i18n/PT-BR.md @@ -1916,7 +1916,6 @@ ou *Princípio da estrutura LIFT na aplicação* ### Locate ou *Localizar* - - Make locating your code intuitive, simple and fast. - Torne a localização do seu código: intuitiva, simples e rápida. **Por que?**: Acho que isso é super importante para um projeto. Se a equipe não pode encontrar rapidamente os arquivos que precisam para trabalhar, eles não serão capazes de trabalhar da forma mais eficiente possível, e a estrutura precisa mudar. Você pode não saber o nome do arquivo ou onde os arquivos relacionados estão, por isso, colocando-os nos locais mais intuitivos e próximos uns dos outros, economiza uma boa parcela de tempo. Uma pasta descrevendo a estrutura pode ajudá-lo. @@ -1956,7 +1955,6 @@ ou *Plano* ### T-DRY (Try to Stick to DRY) ou *Tente manter-se em DRY - Não repita a si mesmo* - - Be DRY, but don't go nuts and sacrifice readability. - Mantenha-se DRY, mas não fique louco e sacrifique a legibilidade. **Por que?**: Não ficar se repetindo é importante, mas não é crucial se acabar sacrificando os outros itens do LIFT, por isso eu chamo de T-DRY (Tente não ficar se repetindo). Eu não quero escrever session-view.html para uma view, porque obviamente é uma view. Se não é óbvio ou uma convenção, então eu renomeio. From b7f31527cc370ca50d2252be8206428f0adc3ac9 Mon Sep 17 00:00:00 2001 From: angelochiello Date: Thu, 6 Aug 2015 14:44:23 +0200 Subject: [PATCH 352/567] [it-IT] PR #476 Updated as PR #476 "Fix/naming" --- i18n/it-IT.md | 52 +++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 38 insertions(+), 14 deletions(-) diff --git a/i18n/it-IT.md b/i18n/it-IT.md index d299de58..0a9558c8 100644 --- a/i18n/it-IT.md +++ b/i18n/it-IT.md @@ -479,11 +479,11 @@ Invece usa la più semplice sintassi setter. ```javascript /* consigliato */ - function Sessions(dataservice) { + function Sessions(sessionDataService) { var vm = this; vm.gotoSession = gotoSession; - vm.refresh = dataservice.refresh; // codice di 1 liena è OK + vm.refresh = sessionDataService.refresh; // codice di 1 liena è OK vm.search = search; vm.sessions = []; vm.title = 'Sessions'; @@ -509,7 +509,7 @@ Invece usa la più semplice sintassi setter. * evitare * Uso di espressioni di funzione. */ - function Avengers(dataservice, logger) { + function Avengers(avengersService, logger) { var vm = this; vm.avengers = []; vm.title = 'Avengers'; @@ -521,7 +521,7 @@ Invece usa la più semplice sintassi setter. } var getAvengers = function() { - return dataservice.getAvengers().then(function(data) { + return avengersService.getAvengers().then(function(data) { vm.avengers = data; return vm.avengers; }); @@ -541,7 +541,7 @@ Invece usa la più semplice sintassi setter. * Usare dichiarazione di funzione * e membri che fanno in binding in alto. */ - function Avengers(dataservice, logger) { + function Avengers(avengersService, logger) { var vm = this; vm.avengers = []; vm.getAvengers = getAvengers; @@ -556,7 +556,7 @@ Invece usa la più semplice sintassi setter. } function getAvengers() { - return dataservice.getAvengers().then(function(data) { + return avengersService.getAvengers().then(function(data) { vm.avengers = data; return vm.avengers; }); @@ -618,7 +618,7 @@ Invece usa la più semplice sintassi setter. function checkCredit() { return creditService.isOrderTotalOk(vm.total) .then(function(isOk) { vm.isCreditOk = isOk; }) - .catch(showServiceError); + .catch(showError); }; } ``` @@ -1630,14 +1630,14 @@ Invece usa la più semplice sintassi setter. .controller('Avengers', Avengers); /* @ngInject */ - function Avengers(storageService, avengerService) { + function Avengers(storage, avengerService) { var vm = this; vm.heroSearch = ''; vm.storeHero = storeHero; function storeHero(){ var hero = avengerService.find(vm.heroSearch); - storageService.save(hero.name, hero); + storage.save(hero.name, hero); } } ``` @@ -1650,18 +1650,18 @@ Invece usa la più semplice sintassi setter. .controller('Avengers', Avengers); /* @ngInject */ - function Avengers(storageService, avengerService) { + function Avengers(storage, avengerService) { var vm = this; vm.heroSearch = ''; vm.storeHero = storeHero; function storeHero(){ var hero = avengerService.find(vm.heroSearch); - storageService.save(hero.name, hero); + storage.save(hero.name, hero); } } - Avengers.$inject = ['storageService', 'avengerService']; + Avengers.$inject = ['storage', 'avengerService']; ``` Nota: Se `ng-annotate` rileva che l'iniezione è già stata fatta (p.e. `@ngInject` è stato rilevato), non duplicherà il codice di `$inject`. @@ -1982,14 +1982,18 @@ Invece usa la più semplice sintassi setter. function AvengersController(){ } ``` -### Nomi delle factory +### Nomi delle factory e dei service ###### [Stile [Y125](#stile-y125)] - - Usa una nomenclatura consistente per tutte le factory dando i nomi a seguito delle loro funzionalità. Usa il camel-case per service e factory. Evita di pre-nominare factory e service con `$` + - Usa una nomenclatura consistente per tutte le factory e i service dando i nomi a seguito delle loro funzionalità. Usa il camel-case per service e factory. Evita di pre-nominare factory e service con `$`. Aggiungi il suffisso `Service` a service e factory soltanto quando non è chiaro cosa siano (p. es. quando si tratta di nomi). *Perché?*: Fornisce un modo consistente per identificare facilmente e referenziare le factory. *Perché?*: Evita collisione di nomi con factory e servizi di Angular esistenti che usano il prefisso `$`. + + *Perché?*: Service con nomi evidenti quali `logger` on richiedono il suffisso. + + *Perché?*: Nomi di service quali `avengers` sono nomi, richiedono in suffisso e dovrebbero essere nominati `avengersService`. ```javascript /** @@ -2004,6 +2008,26 @@ Invece usa la più semplice sintassi setter. function logger(){ } ``` + ```javascript + /** + * consigliato + */ + + // credit.service.js + angular + .module + .factory('creditService', creditService); + + function creditService() { } + + // credit.service.js + angular + .module + .service('customersService', customersService); + + function customersService() { } + ``` + ### Nomi dei componenti directive ###### [Stile [Y126](#stile-y126)] From a4791466571fa183da1c1b059f251ef0cb6aa8ab Mon Sep 17 00:00:00 2001 From: Yannick Baron Date: Wed, 12 Aug 2015 12:04:25 +0900 Subject: [PATCH 353/567] fixed minor grammatical mistake. #482 --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 0d041686..6c61ffca 100644 --- a/README.md +++ b/README.md @@ -2320,7 +2320,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see - Inject code into [module configuration](https://docs.angularjs.org/guide/module#module-loading-dependencies) that must be configured before running the angular app. Ideal candidates include providers and constants. - *Why?*: This makes it easier to have a less places for configuration. + *Why?*: This makes it easier to have less places for configuration. ```javascript angular From 5436d46d926e68d299d826e8a23e6a84dcf2c2b9 Mon Sep 17 00:00:00 2001 From: zach_lysobey Date: Thu, 13 Aug 2015 09:29:32 -0400 Subject: [PATCH 354/567] Fix typo in README --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 6c61ffca..3f5ef258 100644 --- a/README.md +++ b/README.md @@ -1610,7 +1610,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see ### ng-annotate ###### [Style [Y100](#style-y100)] - - Use [ng-annotate](//github.com/olov/ng-annotate) for [Gulp](http://gulpjs.com) or [Grunt](http://gruntjs.com) and comment functions that need automated dependency injection using `/** @ngInject */` + - Use [ng-annotate](//github.com/olov/ng-annotate) for [Gulp](http://gulpjs.com) or [Grunt](http://gruntjs.com) and comment functions that need automated dependency injection using `/* @ngInject */` *Why?*: This safeguards your code from any dependencies that may not be using minification-safe practices. From 0a042edd20642b15fd7cb7b05d798dcaae8976ea Mon Sep 17 00:00:00 2001 From: Johannes Weber Date: Fri, 14 Aug 2015 11:21:14 +0200 Subject: [PATCH 355/567] fix table of contents anchor links in de-DE translation resolved issue #486 --- i18n/de-DE.md | 46 +++++++++++++++++++++++----------------------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/i18n/de-DE.md b/i18n/de-DE.md index 7eba3555..eb60d867 100644 --- a/i18n/de-DE.md +++ b/i18n/de-DE.md @@ -29,36 +29,36 @@ Während diese Anleitung das *Was*, *Warum* und *Wie* erklärt, finde ich es ebe 1. [Single Responsibility](#single-responsibility) 1. [IIFE](#iife) - 1. [Module](#modules) - 1. [Controller](#controllers) + 1. [Module](#module) + 1. [Controller](#controller) 1. [Services](#services) 1. [Factories](#factories) - 1. [Dataservices](#data-services) - 1. [Direktiven](#directives) - 1. [Promises für einen Controller auflösen](#resolving-promises-for-a-controller) - 1. [Manuelle Code-Anmerkungen für das Einfügen von Abhängigkeiten (Dependency Injection)](#manual-annotating-for-dependency-injection) - 1. [Minifizierung und Code-Anmerkungen](#minification-and-annotation) - 1. [Fehlerbehandlung](#exception-handling) - 1. [Namensgebung](#naming) - 1. [Anwendungsstruktur: LIFT Prinzip](#application-structure-lift-principle) - 1. [Anwendungsstruktur](#application-structure) - 1. [Modularität](#modularity) - 1. [Startlogik](#startup-logic) + 1. [Datenservices](#datenservices) + 1. [Direktiven](#direktiven) + 1. [Promises für einen Controller auflösen](#promises-für-einen-controller-auflösen) + 1. [Manuelle Code-Anmerkungen für das Einfügen von Abhängigkeiten (Dependency Injection)](#manuelle-code-anmerkungen-für-das-einfügen-von-abhängigkeiten-dependency-injection) + 1. [Minifizierung und Code-Anmerkungen](#minifizierung-und-code-anmerkungen) + 1. [Fehlerbehandlung](#fehlerbehandlung) + 1. [Namensgebung](#namensgebung) + 1. [Anwendungsstruktur: LIFT Prinzip](#anwendungsstruktur-das-lift-prinzip) + 1. [Anwendungsstruktur](#anwendungsstruktur) + 1. [Modularität](#modularität) + 1. [Startlogik](#startlogik) 1. [Angular $ Wrapper Services](#angular--wrapper-services) - 1. [Testen](#testing) - 1. [Animationen](#animations) - 1. [Kommentare](#comments) + 1. [Testen](#testen) + 1. [Animationen](#animationen) + 1. [Kommentare](#kommentare) 1. [JS Hint](#js-hint) 1. [JSCS](#jscs) - 1. [Konstanten](#constants) - 1. [Dateitemplates und Snippets](#file-templates-and-snippets) + 1. [Konstanten](#konstanten) + 1. [Dateitemplates und Snippets](#dateitemplates-und-snippets) 1. [Yeoman Generator](#yeoman-generator) 1. [Routing](#routing) - 1. [Automatisierung von Aufgaben](#task-automation) - 1. [Filter](#filters) - 1. [Angular Dokumentation](#angular-docs) - 1. [Beiträge](#contributing) - 1. [Lizenz](#license) + 1. [Automatisierung von Aufgaben](#automatisierung-von-aufgaben) + 1. [Filter](#filter) + 1. [Angular Dokumentation](#angular-dokumentation) + 1. [Beiträge](#beiträge) + 1. [Lizenz](#lizenz) ## Single Responsibility From 839e2dd20abde78f8978228ad388df44fe3d43e3 Mon Sep 17 00:00:00 2001 From: vinicius-sabadim Date: Mon, 17 Aug 2015 16:32:14 -0300 Subject: [PATCH 356/567] Translate in pt-br for the topic 'application structure' --- i18n/PT-BR.md | 33 ++++++++++++++++++--------------- 1 file changed, 18 insertions(+), 15 deletions(-) diff --git a/i18n/PT-BR.md b/i18n/PT-BR.md index 35f9cb41..22ef8192 100644 --- a/i18n/PT-BR.md +++ b/i18n/PT-BR.md @@ -1962,34 +1962,37 @@ ou *Tente manter-se em DRY - Não repita a si mesmo* **[De volta ao topo](#tabela-de-conte%C3%BAdo)** ## Application Structure +ou *Estrutura da aplicação* ### Overall Guidelines +ou *Orientações gerais* - - Have a near term view of implementation and a long term vision. In other words, start small and but keep in mind on where the app is heading down the road. All of the app's code goes in a root folder named `app`. All content is 1 feature per file. Each controller, service, module, view is in its own file. All 3rd party vendor scripts are stored in another root folder and not in the `app` folder. I didn't write them and I don't want them cluttering my app (`bower_components`, `scripts`, `lib`). + - Tenha uma visão de curto prazo da implementação e uma visão de longo prazo. Em outras palavras, comece pequeno, mas tenha em mente o caminho que o aplicativo pode tomar. Todos do código do aplicativo vão em uma pasta raiz chamada `app`. Todo o conteúdo é feito com um recurso por arquivo. Cada controlador (controller), serviço (service), módulo (module), visão (view) está em seu próprio arquivo. Todos os scripts de terceiros são armazenados em uma outra pasta raiz e não na pasta `app`. Não foi eu que escrevi esses scripts, então eu não quero que eles baguncem meu aplicativo (`bower_components`,` scripts`, `lib`). - Note: Find more details and reasoning behind the structure at [this original post on application structure](http://www.johnpapa.net/angular-app-structuring-guidelines/). + Nota: Encontre mais detalhes sobre essa estrutura em [esse post original sobre a estrutura da aplicação](http://www.johnpapa.net/angular-app-structuring-guidelines/). ### Layout - - Place components that define the overall layout of the application in a folder named `layout`. These may include a shell view and controller may act as the container for the app, navigation, menus, content areas, and other regions. + - Coloque os componentes que definem o layout geral do aplicativo em uma pasta chamada `layout`. Eles podem incluir uma view e uma controller que agem como recipiente para o app, navegação, menus, áreas de conteúdo, e outras regiões. - *Why?*: Organizes all layout in a single place re-used throughout the application. + **Por que?**: Organize todos os layouts em um único lugar reutilizado em toda a aplicação. ### Folders-by-Feature Structure +ou *Estrutura de Pastas-por-Recurso* - - Create folders named for the feature they represent. When a folder grows to contain more than 7 files, start to consider creating a folder for them. Your threshold may be different, so adjust as needed. + - Crie pastas nomeadas para cada recurso que elas representam. Quando uma pasta cresce ao ponto de conter mais de 7 arquivos, comece considerar a criação de uma pasta para eles. O seu limite pode ser diferente, por isso, ajuste conforme necessário. - *Why?*: A developer can locate the code, identify what each file represents at a glance, the structure is flat as can be, and there is no repetitive nor redundant names. + **Por que?**: O desenvolvedor pode localizar o código, identificar o que cada arquivo representa em resumo, a estrutura é plana como deve ser, e não há nenhum nome repetido ou redundante. - *Why?*: The LIFT guidelines are all covered. + **Por que?**: As orientações LIFT estão todas sendo respeitadas. - *Why?*: Helps reduce the app from becoming cluttered through organizing the content and keeping them aligned with the LIFT guidelines. + **Por que?**: Ajuda a reduzir o app de tornar-se desordenado através da organização do conteúdo e mantêm alinhado com as diretrizes LIFT. - *Why?*: When there are a lot of files (10+) locating them is easier with a consistent folder structures and more difficult in flat structures. + **Por que?**: Quando há um grande número de arquivos (10+) localizá-los é mais fácil com estruturas de pastas consistentes e mais difícil em estruturas planas. ```javascript /** - * recommended + * recomendado */ app/ @@ -2025,15 +2028,15 @@ ou *Tente manter-se em DRY - Não repita a si mesmo* session-detail.controller.js ``` - ![Sample App Structure](https://raw.githubusercontent.com/johnpapa/angularjs-styleguide/master/assets/modularity-2.png) + ![Exemplo de estrutura na aplicação](https://raw.githubusercontent.com/johnpapa/angularjs-styleguide/master/assets/modularity-2.png) - Note: Do not use structuring using folders-by-type. This requires moving to multiple folders when working on a feature and gets unwieldy quickly as the app grows to 5, 10 or 25+ views and controllers (and other features), which makes it more difficult than folder-by-feature to locate files. + Nota: Não estruture seu aplicativo usando pastas-por-tipo. Isto requer alternar entre várias pastas ao trabalhar em um recurso e fica difícil de manejar quando o aplicativo cresce rapidamente para 5, 10 ou 25+ views e controllers (e outros recursos), o que torna mais difícil do que pasta-por-recurso para localizar arquivos. ```javascript /* - * avoid - * Alternative folders-by-type. - * I recommend "folders-by-feature", instead. + * evite + * Alternativa pastas-por-tipo. + * Eu recomendo "pastas-por-recurso". */ app/ From 1e2ca801338209d8f47b2694c4b7fc6b88fa5cad Mon Sep 17 00:00:00 2001 From: vinicius-sabadim Date: Mon, 17 Aug 2015 16:35:56 -0300 Subject: [PATCH 357/567] Better translation --- i18n/PT-BR.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/i18n/PT-BR.md b/i18n/PT-BR.md index 22ef8192..ce166365 100644 --- a/i18n/PT-BR.md +++ b/i18n/PT-BR.md @@ -1986,7 +1986,7 @@ ou *Estrutura de Pastas-por-Recurso* **Por que?**: As orientações LIFT estão todas sendo respeitadas. - **Por que?**: Ajuda a reduzir o app de tornar-se desordenado através da organização do conteúdo e mantêm alinhado com as diretrizes LIFT. + **Por que?**: Através da organização do conteúdo, ajuda a reduzir o app de tornar-se desordenado e mantêm alinhado com as diretrizes LIFT. **Por que?**: Quando há um grande número de arquivos (10+) localizá-los é mais fácil com estruturas de pastas consistentes e mais difícil em estruturas planas. From d99b3a4da6615dff84dc96cc3ea0788a4b58fc71 Mon Sep 17 00:00:00 2001 From: Wolverine Date: Tue, 18 Aug 2015 16:28:21 +0800 Subject: [PATCH 358/567] Update zh-CN.md --- i18n/zh-CN.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/i18n/zh-CN.md b/i18n/zh-CN.md index f41f989d..241855c3 100644 --- a/i18n/zh-CN.md +++ b/i18n/zh-CN.md @@ -1013,7 +1013,7 @@ Angular社区是一个热衷于分享经验的令人难以置信的社区,尽 **[返回顶部](#目录)** ## Directives -###一个dirctive一个文件 +###一个directive一个文件 ###### [Style [Y070](#style-y070)] - 一个文件中只创建一个directive,并依照directive来命名文件。 From f696a293930f8e5995e9a4fd24fa7045082a7658 Mon Sep 17 00:00:00 2001 From: Xavier Haniquaut Date: Tue, 18 Aug 2015 14:08:50 +0200 Subject: [PATCH 359/567] [fr-FR] Refresh french translation : Intro --- i18n/fr-FR.md | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/i18n/fr-FR.md b/i18n/fr-FR.md index 65fee277..727321e4 100644 --- a/i18n/fr-FR.md +++ b/i18n/fr-FR.md @@ -1,16 +1,12 @@ -# Le Guide de Style Angular +# Charte stylistique Angular -*Le guide d'un point de vue personnel sur le style Angular par [@john_papa](//twitter.com/john_papa)* +*Guide de style par subjectif pour Angular par [@john_papa](//twitter.com/john_papa)* -*Translated by [Eric Lemerdy](https://github.com/ericlemerdy)* +Si vous cherchez un guide de style pour la syntaxe, les conventions, et la structuration d'applications Angular, alors vous êtes au bon endroit. Ces styles sont basés sur mon expérience de développement avec [Angular](//angularjs.org), mes présentations, [mes cours sur Pluralsight](http://pluralsight.com/training/Authors/Details/john-papa) et mon travail au sein de diverses équipes. ->The [original English version](http://jpapa.me/ngstyles) is the source of truth, as it is maintained and updated first. +Le but de ce guide de style est de proposer des conseils sur le développement d'applications Angular en exposant les conventions que j'utilise et plus important encore, pourquoi je les ai choisies. -Si vous cherchez un guide de style pour la syntaxe, les conventions, et la structuration d'application Angular, alors vous êtes au bon endroit. Ces styles sont basés sur mon expérience de dévelopement avec [Angular](//angularjs.org), mes présentations, [mes cours sur Pluralsight](http://pluralsight.com/training/Authors/Details/john-papa) et mon travail au sein des équipes. - -Le but de ce guide de style est de proposer des conseils sur le développement d'applications Angular en montrant les conventions que j'utilise et, plus important encore, les raisons des choix que j'ai pris. - ->Si vous appréciez ce guide, visitez mon cours [Angular Patterns: Clean Code](http://jpapa.me/ngclean) sur Pluralsight. +>Si vous appréciez ce guide, visitez mon cours [Angular Patterns: Clean Code](http://jpapa.me/ngclean) sur Pluralsight qui va de pair avec ce guide. [![Angular Patterns: Clean Code](https://raw.githubusercontent.com/johnpapa/angular-styleguide/master/assets/ng-clean-code-banner.png)](http://jpapa.me/ngclean) From f918bea566cea3aac4f33b4789113e67afbafdbd Mon Sep 17 00:00:00 2001 From: Xavier Haniquaut Date: Tue, 18 Aug 2015 14:31:58 +0200 Subject: [PATCH 360/567] [fr-FR] Refresh french translation : Credits --- i18n/fr-FR.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/i18n/fr-FR.md b/i18n/fr-FR.md index 727321e4..c30c15a7 100644 --- a/i18n/fr-FR.md +++ b/i18n/fr-FR.md @@ -10,10 +10,10 @@ Le but de ce guide de style est de proposer des conseils sur le développement d [![Angular Patterns: Clean Code](https://raw.githubusercontent.com/johnpapa/angular-styleguide/master/assets/ng-clean-code-banner.png)](http://jpapa.me/ngclean) -## Suprématie de la Communauté et Remerciements -Ne jamais travailler dans le vide. J'ai trouvé que la communauté Angular est un incroyable groupe dont les membres ont à coeur de partager leurs expériences. Ainsi, un ami et expert Angular Todd Motto et moi avons collaboré sur de nombreux styles et conventions. Nous sommes d'accord sur la plupart, et nous divergeons sur d'autres. Je vous encourage à visiter [les guideslines de Todd](https://github.com/toddmotto/angularjs-styleguide) pour vous faire un sentiment sur son approche et en quoi elle est comparable. +## Remerciements individuels et à la communauté +Ne jamais travailler en vase clos. J'ai trouvé que la communauté Angular est une incroyable communauté dont les membres ont à cœur de partager leurs expériences. Ainsi, avec mon ami et expert d'Angular, Todd Motto, nous avons collaboré sur de nombreux styles et conventions. Nous sommes d'accord sur la plupart, et nous divergeons sur d'autres. Je vous encourage à visiter [le guide de style de Todd](https://github.com/toddmotto/angularjs-styleguide) pour vous faire votre propre avis sur son approche et en quoi elle diverge. -De nombreux de mes styles proviennent des maintes scéances de pair programming que [Ward Bell](http://twitter.com/wardbell) et moi avons eu. Même si nous n'étions pas toujours d'accord, mon ami Ward a assurément contribué à influencer l'évolution ultime de ce guide. +Beaucoup de mes styles proviennent des nombreuses séances de pair programming avec [Ward Bell](http://twitter.com/wardbell). Mon ami Ward a assurément contribué à influencer l'évolution ultime de ce guide. ## Visualiser les Styles dans une Application d'Exemple Alors que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'a été utile de les visualiser dans la pratique. Ce guide est accompagné par une application d'exemple qui suit ces styles et ces motifs. Vous pouvez trouver l'[application d'exemple (appellée modular) ici](https://github.com/johnpapa/ng-demos) dans le répertoire `modular`. Vous pouvez librement le récupérer, le cloner, ou le dupliquer pour le modifier. [Les instructions pour l'éxécuter sont contenues dans ce readme](https://github.com/johnpapa/ng-demos/tree/master/modular). From a07f4d62d5fd1e3ef7d49bd8ae5045560f5686da Mon Sep 17 00:00:00 2001 From: Xavier Haniquaut Date: Tue, 18 Aug 2015 14:48:41 +0200 Subject: [PATCH 361/567] [fr-FR] Refresh french translation : Sample app --- i18n/fr-FR.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/i18n/fr-FR.md b/i18n/fr-FR.md index c30c15a7..504acd30 100644 --- a/i18n/fr-FR.md +++ b/i18n/fr-FR.md @@ -15,8 +15,8 @@ Ne jamais travailler en vase clos. J'ai trouvé que la communauté Angular est u Beaucoup de mes styles proviennent des nombreuses séances de pair programming avec [Ward Bell](http://twitter.com/wardbell). Mon ami Ward a assurément contribué à influencer l'évolution ultime de ce guide. -## Visualiser les Styles dans une Application d'Exemple -Alors que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'a été utile de les visualiser dans la pratique. Ce guide est accompagné par une application d'exemple qui suit ces styles et ces motifs. Vous pouvez trouver l'[application d'exemple (appellée modular) ici](https://github.com/johnpapa/ng-demos) dans le répertoire `modular`. Vous pouvez librement le récupérer, le cloner, ou le dupliquer pour le modifier. [Les instructions pour l'éxécuter sont contenues dans ce readme](https://github.com/johnpapa/ng-demos/tree/master/modular). +## Visualiser les styles dans une application d'exemple +Bien que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'est utile de pouvoir les visualiser dans la pratique. Ce guide est accompagné par une application d'exemple qui suit ces styles et ces modèles. Vous pouvez trouver l'[application d'exemple (intitulée modular) ici](https://github.com/johnpapa/ng-demos) dans le répertoire `modular`. Vous pouvez librement le récupérer, le cloner, ou le **forker**. [Les instructions pour l’exécuter sont contenues dans ce readme](https://github.com/johnpapa/ng-demos/tree/master/modular). ## Traductions [Des traductions de ce guide stylistique Angular](https://github.com/johnpapa/angular-styleguide/tree/master/i18n) sont maintenues par la communauté et peuvent être trouvées ici. From 33ba276ab0cd602e7c61cbcc4b943b9bf70f90af Mon Sep 17 00:00:00 2001 From: Xavier Haniquaut Date: Tue, 18 Aug 2015 14:50:25 +0200 Subject: [PATCH 362/567] [fr-FR] Refresh french translation : Translations --- i18n/fr-FR.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/i18n/fr-FR.md b/i18n/fr-FR.md index 504acd30..f37bdf22 100644 --- a/i18n/fr-FR.md +++ b/i18n/fr-FR.md @@ -19,7 +19,7 @@ Beaucoup de mes styles proviennent des nombreuses séances de pair programming a Bien que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'est utile de pouvoir les visualiser dans la pratique. Ce guide est accompagné par une application d'exemple qui suit ces styles et ces modèles. Vous pouvez trouver l'[application d'exemple (intitulée modular) ici](https://github.com/johnpapa/ng-demos) dans le répertoire `modular`. Vous pouvez librement le récupérer, le cloner, ou le **forker**. [Les instructions pour l’exécuter sont contenues dans ce readme](https://github.com/johnpapa/ng-demos/tree/master/modular). ## Traductions -[Des traductions de ce guide stylistique Angular](https://github.com/johnpapa/angular-styleguide/tree/master/i18n) sont maintenues par la communauté et peuvent être trouvées ici. +[Les traductions de ce guide stylistique pour Angular](https://github.com/johnpapa/angular-styleguide/tree/master/i18n) sont maintenues par la communauté et peuvent être trouvées ici. ## Table des matières From 98d7b8c9eab07aa263e56d173610ce38b902a0bd Mon Sep 17 00:00:00 2001 From: Xavier Haniquaut Date: Tue, 18 Aug 2015 15:03:04 +0200 Subject: [PATCH 363/567] [fr-FR] Refresh french translation : Table of contents --- i18n/fr-FR.md | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/i18n/fr-FR.md b/i18n/fr-FR.md index f37bdf22..6be6fa69 100644 --- a/i18n/fr-FR.md +++ b/i18n/fr-FR.md @@ -26,35 +26,35 @@ Bien que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'est ut 1. [Responsabilité Unique](#responsabilité-unique) 1. [IIFE](#iife) 1. [Modules](#modules) - 1. [Controlleurs](#controlleurs) + 1. [Contrôleurs](#controlleurs) 1. [Services](#services) 1. [Factories](#factories) 1. [Services de données](#services-de-données) 1. [Directives](#directives) - 1. [Résolution des Promesses pour un controlleur](#résolution-des-promesses-pour-un-controlleur) - 1. [Annoter Manuellement pour l'Injection de Dépendances](#annoter-manuellement-pour-linjection-de-dépendances) - 1. [Minification et Annotation](#minification-et-annotation) - 1. [Gestion des Exceptions](#gestion-des-exceptions) + 1. [Résolution de promesses pour un contrôleur](#résolution-de-promesses-pour-un-contrôleur) + 1. [Annoter manuellement les dépendances à injecter](#annoter-manuellement-les-dépendances-à-injecter) + 1. [Minification et annotation](#minification-et-annotation) + 1. [Gestion des exceptions](#gestion-des-exceptions) 1. [Nommage](#nommage) - 1. [Le Principe LIFT de Structuration de l'Application](#le-principe-lift-de-structuration-de-lapplication) - 1. [Structure de l'Application](#structure-de-lapplication) + 1. [Architecture L.I.F.T.](#architecture-lift) + 1. [Architecture de l'application](#architecture-de-lapplication) 1. [Modularité](#modularité) - 1. [Logique de Démarrage](#logique-de-démarrage) - 1. [Les Services de Wrapper $ de Angular](#les-services-de-wrapper--de-angular) - 1. [Le Test](#le-test) + 1. [Logique d'initialisation](#logique-d-initialisation) + 1. [Services $ d'Angular](#services-dollar-d-angular) + 1. [Tests](#tests) 1. [Animations](#animations) 1. [Commentaires](#commentaires) 1. [JSHint](#js-hint) 1. [JSCS](#jscs) 1. [Constantes](#constantes) - 1. [Templates de Fichiers et Fragments](#templates-de-fichiers-et-fragments) + 1. [Templates et snippets](#templates-et-snippets) 1. [Générateur Yeoman](#générateur-yeoman) 1. [Routage](#routage) - 1. [Automatisation des Tâches](#automatisation-des-taches) + 1. [Automatisation des tâches](#automatisation-des-taches) 1. [Filtres](#filtres) 1. [Documentation Angular](#documentation-angular) 1. [Contribuer](#contribuer) - 1. [License](#license) + 1. [Licence](#license) ## Responsabilité Unique From 91731d33d659db354c8ff68abb64df0c2330d0cb Mon Sep 17 00:00:00 2001 From: Xavier Haniquaut Date: Tue, 18 Aug 2015 15:06:09 +0200 Subject: [PATCH 364/567] [fr-FR] Refresh french translation : Single responsability --- i18n/fr-FR.md | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/i18n/fr-FR.md b/i18n/fr-FR.md index 6be6fa69..bb4e33b5 100644 --- a/i18n/fr-FR.md +++ b/i18n/fr-FR.md @@ -58,33 +58,33 @@ Bien que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'est ut ## Responsabilité Unique -### La règle de l'unicité +### Règle d'unicité ###### [Style [Y001](#style-y001)] - - Définir 1 composant par fichier. + - Définir un composant par fichier. - L'exemple suivant définit le module `app` et ses dépendances, définit un controlleur, et définit une factory le tout dans le même fichier. + L'exemple suivant définit le module `app` et ses dépendances, définit un contrôleur, et définit une factory le tout dans le même fichier. ```javascript /* à éviter */ angular - .module('app', ['ngRoute']) - .controller('SomeController', SomeController) - .factory('someFactory', someFactory); + .module('app', ['ngRoute']) + .controller('SomeController', SomeController) + .factory('someFactory', someFactory); function SomeController() { } function someFactory() { } ``` - Les même composants sont maintenant séparés dans leurs propres fichiers. + Les même composants sont maintenant séparés dans leurs propres fichiers. ```javascript /* recommandé */ // app.module.js angular - .module('app', ['ngRoute']); + .module('app', ['ngRoute']); ``` ```javascript @@ -92,8 +92,8 @@ Bien que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'est ut // someController.js angular - .module('app') - .controller('SomeController', SomeController); + .module('app') + .controller('SomeController', SomeController); function SomeController() { } ``` @@ -103,8 +103,8 @@ Bien que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'est ut // someFactory.js angular - .module('app') - .factory('someFactory', someFactory); + .module('app') + .factory('someFactory', someFactory); function someFactory() { } ``` From 183360a5641bc3e36cba06231e99a66135154265 Mon Sep 17 00:00:00 2001 From: Xavier Haniquaut Date: Tue, 18 Aug 2015 15:07:05 +0200 Subject: [PATCH 365/567] transform tabs to spaces --- i18n/fr-FR.md | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/i18n/fr-FR.md b/i18n/fr-FR.md index bb4e33b5..3a30f594 100644 --- a/i18n/fr-FR.md +++ b/i18n/fr-FR.md @@ -207,7 +207,7 @@ Bien que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'est ut ```javascript /* recommandé */ angular - .module('app', [ + .module('app', [ 'ngAnimate', 'ngRoute', 'app.shared', @@ -246,8 +246,8 @@ Bien que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'est ut *Pourquoi ?* : Un module ne devrait être créé qu'une seule fois, et ensuite récupéré à partir de ce point et après. - - Utilisez `angular.module('app', []);` pour setter un module. - - Utilisez `angular.module('app');` pour getter un module. + - Utilisez `angular.module('app', []);` pour setter un module. + - Utilisez `angular.module('app');` pour getter un module. ### Fonctions Nommées ou Anonymes ###### [Style [Y024](#style-y024)] @@ -293,11 +293,11 @@ Bien que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'est ut - Utilisez la syntaxe [`controllerAs`](http://www.johnpapa.net/do-you-like-your-angular-controllers-with-or-without-sugar/) au lieu de la syntaxe de `controlleur classique avec $scope`. - *Pourquoi ?* : Les controlleurs sont construits, recréés, et fournissent une unique nouvelle instance, et la syntaxe `controllerAs` est plus proche de celle d'un contructeur Javascript que la `syntaxe $scope classique`. + *Pourquoi ?* : Les controlleurs sont construits, recréés, et fournissent une unique nouvelle instance, et la syntaxe `controllerAs` est plus proche de celle d'un contructeur Javascript que la `syntaxe $scope classique`. - *Pourquoi ?* : Il encourage l'usage du binding entre un objet avec "point" et la Vue (ex. `customer.name` au lieu de `name`), ce qui est plus contextuel, plus facile à lire, et évite tout problème de référence qui peut arriver sans "point". + *Pourquoi ?* : Il encourage l'usage du binding entre un objet avec "point" et la Vue (ex. `customer.name` au lieu de `name`), ce qui est plus contextuel, plus facile à lire, et évite tout problème de référence qui peut arriver sans "point". - *Pourquoi ?* : Permet d'éviter l'usage des appels à `$parent` dans les Vues avec des controlleurs imbriqués. + *Pourquoi ?* : Permet d'éviter l'usage des appels à `$parent` dans les Vues avec des controlleurs imbriqués. ```html @@ -584,8 +584,8 @@ Bien que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'est ut // Utilise JSONP pour ce navigateur s'il ne supporte pas CORS return $http.get(settings) .then(function(data) { - // Décompresse les données JSON dans l'objet réponse - // afin de rechercher maxRemainingAmount + // Décompresse les données JSON dans l'objet réponse + // afin de rechercher maxRemainingAmount vm.isCreditOk = vm.total <= maxRemainingAmount }) .catch(function(error) { @@ -607,7 +607,7 @@ Bien que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'est ut function checkCredit() { return creditService.isOrderTotalOk(vm.total) - .then(function(isOk) { vm.isCreditOk = isOk; }) + .then(function(isOk) { vm.isCreditOk = isOk; }) .catch(showServiceError); }; } @@ -1709,7 +1709,7 @@ Bien que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'est ut Note : Une autre possibilité serait de surcharger le service au lieu d'utiliser un décorateur. C'est une bonne possibilité, mais si vou voulez garder le comportement par défaut et l'étendre, un décorateur est plus approprié. - ```javascript + ```javascript /* recommandé */ angular .module('blocks.exception') @@ -1739,7 +1739,7 @@ Bien que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'est ut toastr.error(exception.msg, errorData); }; } - ``` + ``` ### Catcher d'Exceptions ###### [Style [Y111](#style-y111)] From 37595ddf6764fc96f8d1e0e914a89fb234818d7b Mon Sep 17 00:00:00 2001 From: Xavier Haniquaut Date: Tue, 18 Aug 2015 15:18:24 +0200 Subject: [PATCH 366/567] [fr-FR] Refresh french translation : IIFE --- i18n/fr-FR.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/i18n/fr-FR.md b/i18n/fr-FR.md index 3a30f594..cc57a10c 100644 --- a/i18n/fr-FR.md +++ b/i18n/fr-FR.md @@ -112,14 +112,14 @@ Bien que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'est ut **[Retour en haut de page](#table-des-matières)** ## IIFE -### Les Closures JavaScript +### Les fermetures (**closures**) JavaScript ###### [Style [Y010](#style-y010)] - - Encapsuler les composants Angular dans une Immediately Invoked Function Expression (IIFE) ou Expression de Fonction Immédiatement Invoquée. + - Encapsuler les composants Angular dans une **Immediately Invoked Function Expression** (IIFE) ou Expression de Fonction Immédiatement Invoquée. - *Pourquoi ?* : Une IIFE supprime les variables du scope global. Cela aide à éviter que les déclarations de variables et de fonctions ne vivent plus longtemps qu'attendu dans le scope global, ce qui aide aussi à éviter les collisions de variables. + *Pourquoi ?* : Une IIFE supprime les variables du scope global. Cela aide à éviter que les déclarations de variables et de fonctions ne vivent plus longtemps que prévu dans le scope global, ce qui aide aussi à éviter les collisions de variables. - *Pourquoi ?* : Lorsque votre code est minifié et embarqué dans un unique fichier pour le déploiement dans un serveur de production, vous pouvez avoir des collisions de variables et de nombreuses variables globales. Une IIFE protège contre ces derniers en fournissant un scope de variable pour chaque fichier. + *Pourquoi ?* : Lorsque votre code est minifié et embarqué dans un unique fichier pour le déploiement dans un serveur de production, vous pouvez avoir des collisions de variables et de nombreuses variables globales. Une IIFE vous protège contre ces dernières en fournissant un scope différent pour chaque fichier. ```javascript /* à éviter */ @@ -128,7 +128,7 @@ Bien que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'est ut .module('app') .factory('logger', logger); - // la fonction de logger est ajoutée en tant que variable globale + // la fonction logger est ajoutée en tant que variable globale function logger() { } // storage.js @@ -170,9 +170,9 @@ Bien que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'est ut })(); ``` - - Note : Pour des raisons de concision seulement, le reste des examples de ce guide peuvent avoir omis la syntaxe IIFE. + - Note : Pour des raisons de concision seulement, le reste des exemples de ce guide seront pas écrits avec la syntaxe IIFE. - - Note : Les IIFE empêchent le code code de test d'atteindre des membres privés comme des expressions régulières ou des fonctions helper ce qui est bon pour tester unitairement directement indépendamment. Cependant, vous pouvez les tester à travers des membres accessibles ou en les exposant à travers leur propre composant. Par exemple en plaçant des fonctions helper, des expressions régulières ou des constantes dans leur propre factory ou contante. + - Note : Les IIFE empêchent le code de test d'atteindre des membres privés, comme les expressions régulières ou les fonctions utilitaires (**helpers**), qu'il est souvent meilleur de tester indépendamment. Cependant, vous pouvez les tester à travers les membres accessibles ou en les exposant à travers leur propre composant. Par exemple en les plaçant dans leur propre factory ou constante. **[Retour en haut de page](#table-des-matières)** From 21aaca4162a8edd9aedddb2434b69e1255c75291 Mon Sep 17 00:00:00 2001 From: Xavier Haniquaut Date: Tue, 18 Aug 2015 15:38:10 +0200 Subject: [PATCH 367/567] [fr-FR] Refresh french translation : Modules --- i18n/fr-FR.md | 55 +++++++++++++++++++++++++++++---------------------- 1 file changed, 31 insertions(+), 24 deletions(-) diff --git a/i18n/fr-FR.md b/i18n/fr-FR.md index cc57a10c..7418ba2b 100644 --- a/i18n/fr-FR.md +++ b/i18n/fr-FR.md @@ -16,7 +16,7 @@ Ne jamais travailler en vase clos. J'ai trouvé que la communauté Angular est u Beaucoup de mes styles proviennent des nombreuses séances de pair programming avec [Ward Bell](http://twitter.com/wardbell). Mon ami Ward a assurément contribué à influencer l'évolution ultime de ce guide. ## Visualiser les styles dans une application d'exemple -Bien que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'est utile de pouvoir les visualiser dans la pratique. Ce guide est accompagné par une application d'exemple qui suit ces styles et ces modèles. Vous pouvez trouver l'[application d'exemple (intitulée modular) ici](https://github.com/johnpapa/ng-demos) dans le répertoire `modular`. Vous pouvez librement le récupérer, le cloner, ou le **forker**. [Les instructions pour l’exécuter sont contenues dans ce readme](https://github.com/johnpapa/ng-demos/tree/master/modular). +Bien que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'est utile de pouvoir les visualiser dans la pratique. Ce guide est accompagné par une application d'exemple qui suit ces styles et ces modèles. Vous pouvez trouver l'[application d'exemple (intitulée modular) ici](https://github.com/johnpapa/ng-demos) dans le répertoire `modular`. Vous pouvez librement le récupérer, le cloner, ou le *forker*. [Les instructions pour l’exécuter sont contenues dans ce readme](https://github.com/johnpapa/ng-demos/tree/master/modular). ## Traductions [Les traductions de ce guide stylistique pour Angular](https://github.com/johnpapa/angular-styleguide/tree/master/i18n) sont maintenues par la communauté et peuvent être trouvées ici. @@ -61,7 +61,7 @@ Bien que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'est ut ### Règle d'unicité ###### [Style [Y001](#style-y001)] - - Définir un composant par fichier. + - Définissez un composant par fichier. L'exemple suivant définit le module `app` et ses dépendances, définit un contrôleur, et définit une factory le tout dans le même fichier. @@ -112,10 +112,10 @@ Bien que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'est ut **[Retour en haut de page](#table-des-matières)** ## IIFE -### Les fermetures (**closures**) JavaScript +### Les fermetures (*closures*) JavaScript ###### [Style [Y010](#style-y010)] - - Encapsuler les composants Angular dans une **Immediately Invoked Function Expression** (IIFE) ou Expression de Fonction Immédiatement Invoquée. + - Encapsulez les composants Angular dans une *Immediately Invoked Function Expression* (IIFE) ou Expression de Fonction Immédiatement Invoquée. *Pourquoi ?* : Une IIFE supprime les variables du scope global. Cela aide à éviter que les déclarations de variables et de fonctions ne vivent plus longtemps que prévu dans le scope global, ce qui aide aussi à éviter les collisions de variables. @@ -172,25 +172,25 @@ Bien que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'est ut - Note : Pour des raisons de concision seulement, le reste des exemples de ce guide seront pas écrits avec la syntaxe IIFE. - - Note : Les IIFE empêchent le code de test d'atteindre des membres privés, comme les expressions régulières ou les fonctions utilitaires (**helpers**), qu'il est souvent meilleur de tester indépendamment. Cependant, vous pouvez les tester à travers les membres accessibles ou en les exposant à travers leur propre composant. Par exemple en les plaçant dans leur propre factory ou constante. + - Note : Les IIFE empêchent le code de test d'atteindre des membres privés, comme les expressions régulières ou les fonctions utilitaires (*helpers*), qu'il est souvent meilleur de tester indépendamment. Cependant, vous pouvez les tester à travers les membres accessibles ou en les exposant à travers leur propre composant. Par exemple en les plaçant dans leur propre factory ou constante. **[Retour en haut de page](#table-des-matières)** ## Modules -### Éviter les Collisions de Nommage +### Éviter les collisions de nommage ###### [Style [Y020](#style-y020)] - - Utilisez des conventions de nommages uniques avec des séparations pour les sous-modules. + - Utilisez des conventions de nommages uniques avec des séparateurs pour les sous-modules. - *Pourquoi ?* : Les noms uniques aident à éviter les collisions de nom de module. Les séparateurs aident à définir les modules et leur hiérarchie de sous-modules. Par exemple, `app` pourrait être le module racine tandis que `app.dashboard` et `app.users` serait les modules qui sont utilisés en tant que dépendances de `app`. + *Pourquoi ?* : Les noms uniques aident à éviter les collisions de nom de module. Les séparateurs aident à définir les modules et la hiérarchie de leurs sous-modules. Par exemple, `app` pourrait être le module principal (*root*) tandis que `app.dashboard` et `app.users` seraient des sous-modules utilisés en tant que dépendances de `app`. -### Définitions (i.e. Setters) +### Mutateurs (*Setters*) ###### [Style [Y021](#style-y021)] - - Déclarer des modules sans variable en utilisant la syntaxe setter. + - Déclarez les modules sans variables en utilisant la syntaxe *setter*. - *Pourquoi ?* : Avec 1 composant par fichier, on ne devrait pas avoir besoin d'introduire une variable pour le module. + *Pourquoi ?* : Avec un composant par fichier, on ne devrait pas avoir besoin d'introduire une variable pour le module. ```javascript /* à éviter */ @@ -202,7 +202,7 @@ Bien que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'est ut ]); ``` - Utilisez à la place la syntaxe setter simple. + Utilisez à la place la syntaxe *setter*. ```javascript /* recommandé */ @@ -215,12 +215,12 @@ Bien que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'est ut ]); ``` -### Getters +### Accesseurs (*Getters*) ###### [Style [Y022](#style-y022)] - - Lorsque vous utilisez un module, évitez d'utiliser une variable en utilisant plutôt le chaînage avec la syntaxe du getter. + - Lorsque vous utilisez un module, évitez d'utiliser une variable en utilisant plutôt le chaînage avec la syntaxe *getter*. - *Pourquoi ?* : Cela produit du code plus lisible et évite les collisions de variable ou les fuites. + *Pourquoi ?* : le code est plus lisible et évite les collisions de variables ou les fuites. ```javascript /* à éviter */ @@ -242,19 +242,26 @@ Bien que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'est ut ### Setting ou Getting ###### [Style [Y023](#style-y023)] - - Ne settez qu'une fois et gettez pour toutes les autres instances. + - N'utilisez le *setter* qu'une fois et le *getter* pour toutes les autres instances. - *Pourquoi ?* : Un module ne devrait être créé qu'une seule fois, et ensuite récupéré à partir de ce point et après. + *Pourquoi ?* : Un module ne devrait être créé qu'une seule fois, et ensuite récupéré à partir de ce point. - - Utilisez `angular.module('app', []);` pour setter un module. - - Utilisez `angular.module('app');` pour getter un module. + ```javascript + /* recommended */ -### Fonctions Nommées ou Anonymes + // pour setter un module + angular.module('app', []); + + // pour getter un module + angular.module('app'); + ``` + +### Fonctions nommées ou anonymes ###### [Style [Y024](#style-y024)] - - Utilisez des fonctions nommées au lieu de passer une fonction anonyme comme callback. + - Utilisez des fonctions nommées au lieu de passer des fonction anonymes dans les *callbacks*. - *Pourquoi ?* : Celà produit du code plus lisible, est plus facile à débugguer, et réduit la quantité de code callback imbriqué. + *Pourquoi ?* : le code plus lisible, est plus facile à déboguer, et réduit l'imbrication des *callbacks*. ```javascript /* à éviter */ @@ -265,7 +272,7 @@ Bien que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'est ut ``` ```javascript - /* recommendé */ + /* recommandé */ // dashboard.js angular @@ -307,7 +314,7 @@ Bien que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'est ut ``` ```html - +
{{ customer.name }}
From 14aa5812f341b9e0d8e15adc5be88ac958f6a7f3 Mon Sep 17 00:00:00 2001 From: Xavier Haniquaut Date: Tue, 18 Aug 2015 17:16:06 +0200 Subject: [PATCH 368/567] [fr-FR] Refresh french translation : Controllers --- i18n/fr-FR.md | 204 +++++++++++++++++++++++++------------------------- 1 file changed, 102 insertions(+), 102 deletions(-) diff --git a/i18n/fr-FR.md b/i18n/fr-FR.md index 7418ba2b..2baee656 100644 --- a/i18n/fr-FR.md +++ b/i18n/fr-FR.md @@ -26,7 +26,7 @@ Bien que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'est ut 1. [Responsabilité Unique](#responsabilité-unique) 1. [IIFE](#iife) 1. [Modules](#modules) - 1. [Contrôleurs](#controlleurs) + 1. [Contrôleurs](#controleurs) 1. [Services](#services) 1. [Factories](#factories) 1. [Services de données](#services-de-données) @@ -220,7 +220,7 @@ Bien que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'est ut - Lorsque vous utilisez un module, évitez d'utiliser une variable en utilisant plutôt le chaînage avec la syntaxe *getter*. - *Pourquoi ?* : le code est plus lisible et évite les collisions de variables ou les fuites. + *Pourquoi ?* : Le code est plus lisible et évite les collisions de variables ou les fuites. ```javascript /* à éviter */ @@ -261,7 +261,7 @@ Bien que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'est ut - Utilisez des fonctions nommées au lieu de passer des fonction anonymes dans les *callbacks*. - *Pourquoi ?* : le code plus lisible, est plus facile à déboguer, et réduit l'imbrication des *callbacks*. + *Pourquoi ?* : Le code plus lisible, est plus facile à déboguer, et réduit l'imbrication des *callbacks*. ```javascript /* à éviter */ @@ -293,18 +293,18 @@ Bien que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'est ut **[Retour en haut de page](#table-des-matières)** -## Controlleurs +## Contrôleurs -### La Syntaxe Vue controllerAs +### Syntaxe de la vue avec `controllerAs` ###### [Style [Y030](#style-y030)] - - Utilisez la syntaxe [`controllerAs`](http://www.johnpapa.net/do-you-like-your-angular-controllers-with-or-without-sugar/) au lieu de la syntaxe de `controlleur classique avec $scope`. + - Utilisez la syntaxe avec [`controllerAs`](http://www.johnpapa.net/do-you-like-your-angular-controllers-with-or-without-sugar/) au lieu de la syntaxe classique avec `$scope`. - *Pourquoi ?* : Les controlleurs sont construits, recréés, et fournissent une unique nouvelle instance, et la syntaxe `controllerAs` est plus proche de celle d'un contructeur Javascript que la `syntaxe $scope classique`. + *Pourquoi ?* : Les contrôleurs sont construits, recréés, et fournissent une unique nouvelle instance. La syntaxe utilisant `controllerAs` est plus proche de celle d'un constructeur Javascript que la syntaxe classique avec `$scope`. - *Pourquoi ?* : Il encourage l'usage du binding entre un objet avec "point" et la Vue (ex. `customer.name` au lieu de `name`), ce qui est plus contextuel, plus facile à lire, et évite tout problème de référence qui peut arriver sans "point". + *Pourquoi ?* : Elle encourage l'usage du *binding* entre un objet (avec la notation pointée) et la vue (ex. `customer.name` au lieu de `name`). Elle est plus contextuelle, plus facile à lire, et évite tout problème de référence qui peut arriver sans la notation « point ». - *Pourquoi ?* : Permet d'éviter l'usage des appels à `$parent` dans les Vues avec des controlleurs imbriqués. + *Pourquoi ?* : Elle permet d'éviter l'usage des appels à `$parent` dans les vues avec des contrôleurs imbriqués. ```html @@ -320,16 +320,16 @@ Bien que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'est ut ``` -### La Syntaxe de Controlleur controllerAs +### Syntaxe du contrôleur avec `controllerAs` ###### [Style [Y031](#style-y031)] - - Utilisez la syntaxe `controllerAs` au lieu de la syntaxe de `controlleur classique avec $scope`. + - Utilisez la syntaxe avec `controllerAs` au lieu de la syntaxe de classique avec `$scope`. - - La syntaxe `controllerAs` utilise `this` à l'intérieur des controlleurs qui se font relier au `$scope`. + - La syntaxe avec `controllerAs` utilise `this` à l'intérieur des contrôleurs qui se fait *binder* à `$scope` implicitement. - *Pourquoi ?* : `controllerAs` est un sucre syntaxique sur le `$scope`. Vous pouvez toujours vous relier à la Vue et toujours accéder aux métodes du `$scope`. + *Pourquoi ?* : `controllerAs` est une simplification (sucre) syntaxique de `$scope`. Vous pouvez toujours vous *binder* dans la vue et accéder aux méthodes de `$scope`. - *Pourquoi ?* : Permet d'éviter la tentation d'utiliser les méthodes du `$scope` à l'intérieur d'un controlleur alors qu'il serait par ailleurs meilleur de les éviter ou de les déplacer dans une factory. Considérez utiliser le `$scope` dans une factory, ou seulement si nécessaire dans un controlleur. Par exemple lorsqu'il faut publier ou souscrire des événements en utilisant [`$emit`](https://docs.angularjs.org/api/ng/type/$rootScope.Scope#$emit), [`$broadcast`](https://docs.angularjs.org/api/ng/type/$rootScope.Scope#$broadcast), ou [`$on`](https://docs.angularjs.org/api/ng/type/$rootScope.Scope#$on) considérez déplacer ces usages dans une factory et les invoquer depuis le controlleur. + *Pourquoi ?* : Permet d'éviter la tentation d'utiliser les méthodes de `$scope` à l'intérieur d'un contrôleur. Il est par ailleurs, meilleure pratique de les éviter dans les contrôleurs mais plutôt de les déplacer dans une factory. Considérez utiliser `$scope` dans un contrôleur seulement si nécessaire. Par exemple lorsqu'il faut publier ou souscrire à des événements en utilisant [`$emit`](https://docs.angularjs.org/api/ng/type/$rootScope.Scope#$emit), [`$broadcast`](https://docs.angularjs.org/api/ng/type/$rootScope.Scope#$broadcast), ou [`$on`](https://docs.angularjs.org/api/ng/type/$rootScope.Scope#$on) considérez déplacer ces usages dans une factory et les invoquer depuis le contrôleur. ```javascript /* à éviter */ @@ -347,12 +347,12 @@ Bien que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'est ut } ``` -### controllerAs avec vm +### `controllerAs` avec `vm` ###### [Style [Y032](#style-y032)] - - Utilisez une variable de capture pour `this` quand vous utilisez la syntaxe `controllerAs`. Choisissez un nom de variable consistant tel que `vm`, qui signifie ViewModel. + - Utilisez une variable de capture pour `this` quand vous utilisez la syntaxe avec `controllerAs`. Choisissez un nom de variable consistent tel que `vm` (pour « ViewModel »). - *Pourquoi ?* : Le mot clé `this` est contextuel et son utilisation au sein d'une fonction à l'intérieur d'un controlleur pourrait changer son contexte. Capturer le contexte de `this` évite de rencontrer ce problème. + *Pourquoi ?* : `this` est contextuel et son utilisation au sein d'une fonction à l'intérieur d'un contrôleur pourrait faire changer son contexte. Capturer le contexte de `this` évite de rencontrer ce problème. ```javascript /* à éviter */ @@ -371,14 +371,14 @@ Bien que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'est ut } ``` - Note : Vous pouvez évitez n'importe quel avertissement [jshint](http://www.jshint.com/) en plaçant le commentaire ci-dessous au dessus de la ligne de code. Cependant, ce n'est pas nécesaire lorsque la fonction est nommée en utilisant la CasseEnMajuscule, puisque cette convention signifie que c'est une fonction constructeur, ce qu'est un controlleur en Angular. + Note : Vous pouvez évitez n'importe quel avertissement [jshint](http://www.jshint.com/) en plaçant le commentaire suivant au dessus de la ligne de code. Cependant, il n'est pas nécessaire lorsque la fonction est nommée en utilisant la CasseEnMajuscule, puisque cette convention signifie que c'est la fonction est un constructeur. C'est précisément la nature d'un contrôleur dans Angular. ```javascript /* jshint validthis: true */ var vm = this; ``` - Note : Lors de la création de watchs dans un controlleur en utilisant `controller as`, vous pouvez watcher les membres `vm.*` en utilisant la syntaxe suivante. (Créez des watchs avec prudence puisqu'ils ajoutent plus de charge au cycle de digest.) + Note : Lors de la création de *watchers* dans un contrôleur en utilisant `controlleAs`, vous pouvez *watcher* les différents `vm.*` en utilisant la syntaxe suivante. (Créez des *watchers* avec prudence puisqu'ils ajoutent plus de charge au cycle de *digest*.) ```html @@ -396,15 +396,14 @@ Bien que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'est ut } ``` -### Les Membres Bindable au Début +### Placement des membres *bindables* au début ###### [Style [Y033](#style-y033)] - - Placez les membres bindables au début du controlleur, par ordre alphabétique, et non pas dispersés à travers le code du controlleur. + - Placez les membres *bindables* au début du contrôleur, par ordre alphabétique, et non pas dispersés à travers le code du contrôleur. - *Pourquoi ?* : Placer les membres bindables au début permet de faciliter la lecture et vous aide à identifier instantanément quels membres du controlleur peut être bindé et utilisés dans la Vue. + *Pourquoi ?* : Placer les membres *bindables* au début permet de faciliter la lecture et vous aide à identifier instantanément quels membres du contrôleur peuvent-être *bindés* et utilisés dans la vue. - *Pourquoi ?* : Placer les fonction anonymes sur la même ligne peut être facile, mais lorsque ces fonctions ont plus d'une ligne de code elles peuvent réduire la lisibilité. Définir les fonctions sous les membres bindables (les fonctions seront hissées) déplace les détails d'implémentation en bas, guardant les membres bindables en haut, - Setting anonymous functions in-line can be easy, but when those functions are more than 1 line of code they can reduce the readability. Defining the functions below the bindable members (the functions will be hoisted) moves the implementation details down, keeps the bindable members up top, and makes it easier to read. + *Pourquoi ?* : Définir des fonctions anonymes *in-line* peut être facile, mais lorsque ces fonctions font plus d'une ligne de code elles peuvent réduire la lisibilité. Définir les fonctions sous les membres *bindables* (les fonctions seront *hoistées*) déplace les détails d'implémentation en bas, gardant les membres *bindables* en haut, ```javascript /* avoid */ @@ -450,9 +449,9 @@ Bien que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'est ut } ``` - ![Les Controlleur Utilisant "Au dessus de la Réduction"](https://raw.githubusercontent.com/johnpapa/angular-styleguide/master/assets/above-the-fold-1.png) + ![Contrôleur utilisant la syntaxe avec les membres bindables au dessus](https://raw.githubusercontent.com/johnpapa/angular-styleguide/master/assets/above-the-fold-1.png) - Note : Si la fonction est un one-liner, considérez de la garder bien en haut, tant que la lisibilité n'est pas affectée. + Note : Si la fonction est un *oneliner* vous pouvez la garder en haut du contrôleur, tant que la lisibilité n'est pas affectée. ```javascript /* à éviter */ @@ -462,11 +461,11 @@ Bien que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'est ut vm.gotoSession = gotoSession; vm.refresh = function() { /** - * lines - * of + * Nombreuses lignes + * de * code - * affects - * readability + * affectant + * la lisibilité */ }; vm.search = search; @@ -476,35 +475,35 @@ Bien que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'est ut ```javascript /* recommandé */ - function Sessions(dataservice) { + function Sessions(sessionDataService) { var vm = this; vm.gotoSession = gotoSession; - vm.refresh = dataservice.refresh; // Le one-liner est acceptable + vm.refresh = sessionDataService.refresh; // *oneliner* acceptable vm.search = search; vm.sessions = []; vm.title = 'Sessions'; ``` -### Déclaration de Fonctions pour Cacher les Détails d'Implémentation +### Déclaration des fonctions pour cacher les détails d'implémentation ###### [Style [Y034](#style-y034)] - - Utilisez les déclarations de fonctions pour cacher les détails d'implémentation. Gardez vos membres bindables tout en haut. Quand vous avez besoin de binder une fonction dans un controlleur, faites-la pointer vers la déclaration de la fonction plus bas dans le fichier. Ceci est directement lié à la section des Membres Bindable au Début. Pour plus de détails, vous pouvez lire [cet article](http://www.johnpapa.net/angular-function-declarations-function-expressions-and-readable-code). + - Utilisez les déclarations de fonctions pour cacher les détails d'implémentation. Gardez vos membres *bindables* en haut. Quand vous avez besoin de *binder* une fonction dans un contrôleur, faites-la pointer vers la déclaration de la fonction plus bas dans le fichier. Ceci est directement lié à la section du placement des membres *bindables* au début. Pour plus de détails, vous pouvez lire [cet article](http://www.johnpapa.net/angular-function-declarations-function-expressions-and-readable-code). - *Pourquoi ?* : Placer les membres bindables en haut rend plus facile la lecture et vous aide instantanément à identifier quels membres du controlleur peuvent être bindés et utilisés dans la Vue. (Même chose que plus haut.) + *Pourquoi ?* : Placer les membres *bindables* en haut facilite la lecture et vous aide instantanément à identifier quels membres du contrôleur peuvent être *bindés* et utilisés dans la vue. - *Pourquoi ?* : Placer les détails d'implémentation d'une fonction plus bas dans le fichier déplace cette complexité en dehors du regard ainsi vous pouvez ne voir que les choses importantes en haut. + *Pourquoi ?* : Placer les détails d'implémentation d'une fonction plus bas dans le fichier permet de masquer la complexité. Ainsi vous ne pouvez voir que les choses importantes en haut. - *Pourquoi ?* : Les déclarations de fichiers sont remontées donc il n'y a aucun problème à utiliser une fonction avant qu'elle ne soit définie (alors que ça le serait avec les expressions de fonction). + *Pourquoi ?* : Les déclarations de fonctions sont *hoistées* donc il n'y a pas problème à utiliser une fonction avant qu'elle ne soit définie (alors que ça serait le cas avec les expressions de fonction). - *Pourquoi ?* : Vous ne vous préocuperez plus des déclarations de fonctions déplaçant `var a` avant `var b` cassant ainsi votre code car `a` dépend de `b`. + *Pourquoi ?* : Vous ne vous préoccuperez plus des déclarations de fonctions déplaçant `var a` avant `var b` cassant ainsi votre code car `a` dépendait de `b`. - *Pourquoi ?* : L'ordre est critique avec les expressions de fonction + *Pourquoi ?* : L'ordre est critique avec les expressions de fonctions. ```javascript /** - * à éviter - * L'utilisation des expressions de fonction. + * Evitez + * l'utilisation des expressions de fonctions. */ function Avengers(dataservice, logger) { var vm = this; @@ -530,13 +529,13 @@ Bien que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'est ut } ``` - Remarquez que les choses importantes sont dispersées dans l'exemple précédent. Dans l'exemple ci-dessous, remarquez que les choses importantes sont tout en haut. Par exemple, les membres bindés au controlleur tels que `vm.avengers` et `vm.title`. Les détails d'implémentation sont plus bas dessous. C'est simplement plus facile à lire. + Remarquez que dans l'exemple précédent les choses importantes sont dispersées. Dans l'exemple ci-dessous, vous noterez que le contenu important est en haut. Par exemple, les membres *bindables* au contrôleur tels que `vm.avengers` ou `vm.title`. Les détails d'implémentation sont plus bas. C'est simplement plus facile à lire. ```javascript /* * recommandé - * L'utilisation des déclarations de fonction - * et les membres bindables tout en haut. + * Utilisation des déclarations de fonction + * et les membres bindables au début. */ function Avengers(dataservice, logger) { var vm = this; @@ -561,16 +560,18 @@ Bien que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'est ut } ``` -### Déplacer la Logique des Controlleurs +### Déplacez la logique métier dans les services ###### [Style [Y035](#style-y035)] - - Déplacer la logique d'un controlleur en la déléguant à des services et des factories. + - Déplacer la logique d'un contrôleur en la déléguant à des services ou *factories*. + + *Pourquoi ?* : La logique peut être ré-utilisée par plusieurs contrôleurs lorsqu'elle est placée au sein d'un service et exposée via une fonction. - *Pourquoi ?* : La logique peut être ré-utilisée par plusieurs controlleurs lorsqu'elle est placée au sein d'un service et exposée via une fonction. + *Pourquoi ?* : La logique dans un service peut être facilement isolée pour les tests unitaires, tandis que la logique d'appel dans un contrôleur peut facilement être *mockée*. - *Pourquoi ?* : La logique d'un service peut plus facilement être isolée dans un test unitaire, tandis que la logique d'appel dans le controlleur peut facilement être mockée. + *Pourquoi ?* : Cela supprime des dépendances et cache les détails d'implémentation au contrôleur. - *Pourquoi ?* : Cela supprime des dépendances et cache les détails d'implémentation au controlleur. + *Pourquoi ?* : Permet de garder le contrôleur le plus minimal et focalisé possible. ```javascript @@ -583,22 +584,21 @@ Bien que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'est ut function checkCredit() { var settings = {}; - // Obtenir l'URL de base du service credit à partir de la config - // Positionne les headers requis pour le service credit + // Obtenir l'URL de base du service crédit à partir de la config + // Positionne les headers requis pour le service crédit // Prépare l'URL query string ou l'objet de données avec les données de requête. - // Ajoute les infos d'identification de l'utilsiateur afin que le service obtienne - // les bons droits de limite credit pour cet utilisateur. - // Utilise JSONP pour ce navigateur s'il ne supporte pas CORS + // Ajoute les infos d'identification de l'utilisateur afin que le service obtienne les bons droits de limite credit pour cet utilisateur. + // Utilise JSONP pour ce navigateur s'il ne supporte pas les CORS return $http.get(settings) .then(function(data) { - // Décompresse les données JSON dans l'objet réponse - // afin de rechercher maxRemainingAmount - vm.isCreditOk = vm.total <= maxRemainingAmount + // Décompresse les données JSON dans l'objet de réponse + // afin de rechercher maxRemainingAmount + vm.isCreditOk = vm.total <= maxRemainingAmount }) .catch(function(error) { // Interpréter l'erreur // Gérer le timeout ? Réessayer ? Essayer un service alternatif ? - // Re-rejetter avec une erreur appropriée à la vue de l'utilisateur + // Re-rejeter avec une erreur appropriée de l'utilisateur final }); }; } @@ -614,27 +614,27 @@ Bien que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'est ut function checkCredit() { return creditService.isOrderTotalOk(vm.total) - .then(function(isOk) { vm.isCreditOk = isOk; }) + .then(function(isOk) { vm.isCreditOk = isOk; }) .catch(showServiceError); }; } ``` -### Gardez des Controlleurs Focalisés +### Gardez les contrôleurs focalisés ###### [Style [Y037](#style-y037)] - - Définir un controlleur pour une vue, et n'essayez pas de ré-utiliser le controlleur pour d'autres vues. Au lieu de cela, déplacez la logique réutilisable vers des factories et gardez le controlleur simple et focalisé sur sa vue. + - Définissez un contrôleur pour une vue, et n'essayez pas de ré-utiliser le contrôleur pour d'autres vues. Au lieu de cela, déplacez la logique réutilisable vers les *factories* et gardez le contrôleur simple et focalisé sur sa vue. - *Pourquoi ?*: La réutilisation de controlleurs sur plusieurs vues est fragile et une bonne couverture de tests de bout en bout ("end to end" ou "e2e") est requise afin d'assurer la stabilité dans les grosses applications. + *Pourquoi ?*: La réutilisation des contrôleurs sur plusieurs vues est fragilisante pour l'application et une bonne couverture de tests *end-to-end* (*e2e*) est requise afin d'assurer la stabilité sur l'ensemble d'une grosse application. -### Assigner les Controlleurs +### Assignation des contrôleurs ###### [Style [Y038](#style-y038)] - - Lorsqu'un controlleur doit être associé à une vue et qu'un composant pourrait être ré-utilisé par d'autres controlleurs ou vues, définissez les controlleurs avec leurs routes. + - Lorsqu'un contrôleur doit être associé à une vue et qu'un composant pourraient être ré-utilisés par d'autres contrôleurs ou vues, définissez les contrôleurs avec leurs routes. - Note : Si une Vue est chargée via d'autres moyens que la route, alors utilisez la syntaxe `ng-controller="Avengers as vm"`. + Note : Si une vue est chargée via d'autres moyens qu'une route, alors utilisez la syntaxe avec `ng-controller="Avengers as vm"`. - *Pourquoi ?* : Associer le controlleur dans la route permet que différentes routes invoquent d'autres paires de controlleurs et vues. Lorsque les controlleurs sont assignés dans la vue avec [`ng-controller`](https://docs.angularjs.org/api/ng/directive/ngController), cette vue est toujours associée avec le même controlleur. + *Pourquoi ?* : Associer le contrôleur dans la route permet à différentes routes d'invoquer d'autres paires contrôleur-vue. Lorsque les contrôleurs sont assignés dans la vue avec [`ng-controller`](https://docs.angularjs.org/api/ng/directive/ngController), cette vue est toujours associée avec le même contrôleur. ```javascript /* à éviter - lorsque l'utilisation avec une route et une association dynamique est voulue */ @@ -901,11 +901,11 @@ Bien que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'est ut - Refactorer la logique pour faire les opérations sur les données et les interactions avec la donnée dans une factory. Rendez les services de données responsables des appels ajax, du local storage, du stockage en mémoire, ou toute autre opérations sur les données. - *Pourquoi ?* : La responsabilité du controlleur est la présentation et l'assemblage des informations pour la vue. Il ne devrait pas se soucier de la façon dont la donnée est récupérée, mais seulement de la façon de la demander. Séparer des services de données déplace la logique du 'comment récupérer une donnée' dans ce service de donnée, et laisse le controlleur plus simple et plus focalisé sur la vue. + *Pourquoi ?* : La responsabilité du contrôleur est la présentation et l'assemblage des informations pour la vue. Il ne devrait pas se soucier de la façon dont la donnée est récupérée, mais seulement de la façon de la demander. Séparer des services de données déplace la logique du 'comment récupérer une donnée' dans ce service de donnée, et laisse le contrôleur plus simple et plus focalisé sur la vue. - *Pourquoi ?* : Cela le rend plus facile à tester (en mockant ou avec le vrai) les appels aux données lorsque l'on teste un controlleur qui utilise un service de données. + *Pourquoi ?* : Cela le rend plus facile à tester (en mockant ou avec le vrai) les appels aux données lorsque l'on teste un contrôleur qui utilise un service de données. - *Pourquoi ?* : L'implémentation d'un service de données peut avoir du code très spécifique pour gérer le référentiel des données. Celà peut inclure des entêtes, la façon de dialoguer avec la donnée, ou des dépendances vers d'autres services tels que $http. La séparation de la logique vers un service de données encapsule cette logique dans un unique endroit en cachant les détails d'implémentation du consommateur externe (peut-être un controlleur), en rendant également plus simple les changements d'implémentation. + *Pourquoi ?* : L'implémentation d'un service de données peut avoir du code très spécifique pour gérer le référentiel des données. Celà peut inclure des entêtes, la façon de dialoguer avec la donnée, ou des dépendances vers d'autres services tels que $http. La séparation de la logique vers un service de données encapsule cette logique dans un unique endroit en cachant les détails d'implémentation du consommateur externe (peut-être un contrôleur), en rendant également plus simple les changements d'implémentation. ```javascript /* Recommandé */ @@ -938,12 +938,12 @@ Bien que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'est ut } ``` - Note : Le service de données est appellé depuis des consommateurs, tels que des controlleurs, en leur cachant l'implémentation, comme le montre l'éxemple ci-dessous. + Note : Le service de données est appellé depuis des consommateurs, tels que des contrôleurs, en leur cachant l'implémentation, comme le montre l'éxemple ci-dessous. ```javascript /* Recommandé */ - // un controlleur qui appelle la factory du service de données + // un contrôleur qui appelle la factory du service de données angular .module('app.avengers') .controller('Avengers', Avengers); @@ -1194,15 +1194,15 @@ Bien que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'est ut ### Directives et ControllerAs ###### [Style [Y075](#style-y075)] - - Utilisez la syntaxe `controller as` avec une directive pour être cohérent avec l'utilisation de `controller as` pour l'association de la vue et du controlleur. + - Utilisez la syntaxe `controller as` avec une directive pour être cohérent avec l'utilisation de `controller as` pour l'association de la vue et du contrôleur. *Pourquoi ?* : Ça fait sens et ce n'est pas difficile. - Note : La directive ci-dessous démontre une façon parmis d'autres d'utiliser le scope à l'intérieur de la fonction link et dans un controlleur de directive, par l'utilisation de controllerAs. J'ai in-liné le template que pour le mettre au même endroit. + Note : La directive ci-dessous démontre une façon parmis d'autres d'utiliser le scope à l'intérieur de la fonction link et dans un contrôleur de directive, par l'utilisation de controllerAs. J'ai in-liné le template que pour le mettre au même endroit. Note : Concernant l'injection de dépendance, voir [Identifier Manuellement les Dépendances](#manual-annotating-for-dependency-injection). - Note : Remarquez que le controlleur de la directive est à l'extérieur de la closure de la directive. Cette façon de faire évite le problème des injections plus disponibles après le `return`. + Note : Remarquez que le contrôleur de la directive est à l'extérieur de la closure de la directive. Cette façon de faire évite le problème des injections plus disponibles après le `return`. ```html
@@ -1260,9 +1260,9 @@ Bien que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'est ut ###### [Style [Y076](#style-y076)] - - Utilisez `bindToController = true` lorsque vous utilisez la syntaxe `controller as` avec une directive quand vous voulez binder le scope externe au scope du controlleur de la directive. + - Utilisez `bindToController = true` lorsque vous utilisez la syntaxe `controller as` avec une directive quand vous voulez binder le scope externe au scope du contrôleur de la directive. - *Pourquoi ?* : Cela rend plus facile de binder le scope externe au scope du controlleur de la directive. + *Pourquoi ?* : Cela rend plus facile de binder le scope externe au scope du contrôleur de la directive. Note : `bindToController` a été introduit à partir de Angular 1.3.0. @@ -1307,18 +1307,18 @@ Bien que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'est ut **[Retour en haut de page](#table-des-matières)** -## Résolution des Promesses pour un Controlleur +## Résolution des Promesses pour un Contrôleur ### Promesses d'Activation du Controller ###### [Style [Y080](#style-y080)] - - Résolvez la logique de démarrage d'un controlleur dans une fonction `activate`. + - Résolvez la logique de démarrage d'un contrôleur dans une fonction `activate`. - *Pourquoi ?* : Placer la logique de démarrage toujours au même endroit permet de le rendre plus facile à localiser, plus cohérent à tester, et permet d'éviter la dispersion de la logique d'activation à travers le controlleur. + *Pourquoi ?* : Placer la logique de démarrage toujours au même endroit permet de le rendre plus facile à localiser, plus cohérent à tester, et permet d'éviter la dispersion de la logique d'activation à travers le contrôleur. - *Pourquoi ?* : La fonction `activate` d'un controlleur rend pratique la ré-utilisation de la logique pour un refraichissement du controlleur ou de la vue, garde cette logique à un seul endroit, envoie l'utilisateur plus rapidement à la Vue, rend les animations faciles sur la `ng-view` ou l'`ui-view`, et c'est rendu plus vif à l'utilisateur. + *Pourquoi ?* : La fonction `activate` d'un contrôleur rend pratique la ré-utilisation de la logique pour un refraichissement du contrôleur ou de la vue, garde cette logique à un seul endroit, envoie l'utilisateur plus rapidement à la Vue, rend les animations faciles sur la `ng-view` ou l'`ui-view`, et c'est rendu plus vif à l'utilisateur. - Note : Si vous avez besoin d'annuler sous conditions la route avant de vous mettre à utiliser le controlleur, utilisez une [résolution de route](#style-y081) à la place. + Note : Si vous avez besoin d'annuler sous conditions la route avant de vous mettre à utiliser le contrôleur, utilisez une [résolution de route](#style-y081) à la place. ```javascript /* à éviter */ @@ -1357,15 +1357,15 @@ Bien que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'est ut ### Promesses de Résolution de Route ###### [Style [Y081](#style-y081)] - - Lorsqu'un controlleur dépend d'une promesse qui doit être résolue avant qu'un controlleur soit activé, résolvez ces dépendances dans le `$routeProvider`. Si vous avez besoin d'annuler une route sous certaines conditions avant que le controlleur soit activé, utilisez un resolver de route. + - Lorsqu'un contrôleur dépend d'une promesse qui doit être résolue avant qu'un contrôleur soit activé, résolvez ces dépendances dans le `$routeProvider`. Si vous avez besoin d'annuler une route sous certaines conditions avant que le contrôleur soit activé, utilisez un resolver de route. - Utilisez un resolver de route dès lors que vous voulez décider d'annuler la route avant même de commencer à naviguer vers la Vue. - *Pourquoi ?* : Un controlleur pourrait avoir besoin de données avant qu'il se charge. Cette donnée pourrait venir d'une promesse via une factory personnalisée ou de [$http](https://docs.angularjs.org/api/ng/service/$http). Utiliser une [resolution de route](https://docs.angularjs.org/api/ngRoute/provider/$routeProvider) permet à la promesse de se résoudre avant que la logique du controlleur s'éxécute, ainsi on peut prendre des actions basées sur cette donnée à partir de la promesse. + *Pourquoi ?* : Un contrôleur pourrait avoir besoin de données avant qu'il se charge. Cette donnée pourrait venir d'une promesse via une factory personnalisée ou de [$http](https://docs.angularjs.org/api/ng/service/$http). Utiliser une [resolution de route](https://docs.angularjs.org/api/ngRoute/provider/$routeProvider) permet à la promesse de se résoudre avant que la logique du contrôleur s'éxécute, ainsi on peut prendre des actions basées sur cette donnée à partir de la promesse. - *Pourquoi ?* : Le code s'éxécute après la route et dans la fonction activate du controlleur. La Vue commence à se charger tout de suite. Le data binding démarre quand la promesse d'activation se résoud. Une animation de "chargement" peut être affichée pendant que la vue opère la transition (via `ng-view` ou `ui-view`). + *Pourquoi ?* : Le code s'éxécute après la route et dans la fonction activate du contrôleur. La Vue commence à se charger tout de suite. Le data binding démarre quand la promesse d'activation se résoud. Une animation de "chargement" peut être affichée pendant que la vue opère la transition (via `ng-view` ou `ui-view`). - Note : Le code s'éxécute avant la route via une promesse. Le rejet de la promesse annule le routage. Sa résolution met la nouvelle vue en attente de la résolution du routage. Une animation de "chargement" peut être affichée avant la résolution et lorsque la vue entre en transition. Si vous voulez aller à la Vue plus vite et que vous n'avez pas besoin d'un point pour décider si vous voulez atteindre la Vue, il est conseillé d'utiliser la [technique de l'activation de controlleur](#style-y080) à la place. + Note : Le code s'éxécute avant la route via une promesse. Le rejet de la promesse annule le routage. Sa résolution met la nouvelle vue en attente de la résolution du routage. Une animation de "chargement" peut être affichée avant la résolution et lorsque la vue entre en transition. Si vous voulez aller à la Vue plus vite et que vous n'avez pas besoin d'un point pour décider si vous voulez atteindre la Vue, il est conseillé d'utiliser la [technique de l'activation de contrôleur](#style-y080) à la place. ```javascript /* à éviter */ @@ -1466,7 +1466,7 @@ Bien que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'est ut - Eviter l'utilisation de la syntaxe raccourcie de déclaration des dépendances sans utiliser une approche sûre pour la minification. - *Pourquoi ?* : Les paramètres du composant (ex: controlleur, factory, etc.) seront converties en variables mutilées. Par exemple, ˋcommonˋet ˋdataserviceˋ deviendraient ˋaˋet ˋbˋ et ne seraient pas trouvées par Angular. + *Pourquoi ?* : Les paramètres du composant (ex: contrôleur, factory, etc.) seront converties en variables mutilées. Par exemple, ˋcommonˋet ˋdataserviceˋ deviendraient ˋaˋet ˋbˋ et ne seraient pas trouvées par Angular. ```javascript /* à éviter - non sûr pour la minification */ @@ -1529,7 +1529,7 @@ Bien que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'est ut } ``` - Note : Lorsque votre fonction est sous une instruction de return, le $inject peut ne pas être accessible (cela pourrait arriver dans une directive). Vous pouvez vous en sortir en bougeant le controlleur en dehors de la directive. + Note : Lorsque votre fonction est sous une instruction de return, le $inject peut ne pas être accessible (cela pourrait arriver dans une directive). Vous pouvez vous en sortir en bougeant le contrôleur en dehors de la directive. ```javascript /* À éviter */ @@ -1840,7 +1840,7 @@ Bien que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'est ut * possibilités couramment rencontrées. */ - // Controlleurs + // Contrôleurs avengers.js avengers.controller.js avengersController.js @@ -1856,7 +1856,7 @@ Bien que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'est ut * recommandé */ - // controlleurs + // contrôleurs avengers.controller.js avengers.controller.spec.js @@ -1882,13 +1882,13 @@ Bien que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'est ut avenger-profile.directive.spec.js ``` - Note : Une autre convention courante consiste à nommer les fichiers de controlleurs sans le mot `controller` dans le nom de fichier comme `avengers.js`au lieu de `avengers.controller.js`. Toutes les autres conventions étant maintenues avec un suffixe par type. Les controlleurs étant les les types de composant les plus courants, ça permet d'économiser la frappe au clavier tout en étant facilement identifiable. Je vous conseille de choisir une convention et de vous y tenir dans toute l'équipe. Ma préference est `avengers.controller.js`. + Note : Une autre convention courante consiste à nommer les fichiers de contrôleurs sans le mot `controller` dans le nom de fichier comme `avengers.js`au lieu de `avengers.controller.js`. Toutes les autres conventions étant maintenues avec un suffixe par type. Les contrôleurs étant les les types de composant les plus courants, ça permet d'économiser la frappe au clavier tout en étant facilement identifiable. Je vous conseille de choisir une convention et de vous y tenir dans toute l'équipe. Ma préference est `avengers.controller.js`. ```javascript /** * recommandé */ - // Controlleurs + // Contrôleurs avengers.js avengers.spec.js ``` @@ -1912,12 +1912,12 @@ Bien que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'est ut avenger-profile.directive.spec.js ``` -### Nommage des Controlleurs +### Nommage des Contrôleurs ###### [Style [Y123](#style-y123)] - - Utilisez des noms cohérents pour tous les controlleurs nommés d'après leur fonctionnalité. Utilisez le CamelCaseEnMajuscule, puisque ce sont des constructeurs. + - Utilisez des noms cohérents pour tous les contrôleurs nommés d'après leur fonctionnalité. Utilisez le CamelCaseEnMajuscule, puisque ce sont des constructeurs. - *Pourquoi ?* : Fournit une façon cohérente d'identifier rapidement et de référencer les controlleurs. + *Pourquoi ?* : Fournit une façon cohérente d'identifier rapidement et de référencer les contrôleurs. *Pourquoi ?* : Le CamelCaseEnMajuscules est la convention pour identifier les objets qui peuvent être instanciés avec un controleur. @@ -1934,10 +1934,10 @@ Bien que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'est ut function HeroAvengersController() { } ``` -### Suffixe des Noms de Controlleurs +### Suffixe des Noms de Contrôleurs ###### [Style [Y124](#style-y124)] - - Ajoutez au nom du controlleur le suffixe ˋControllerˋ. + - Ajoutez au nom du contrôleur le suffixe ˋControllerˋ. *Pourquoi ?* : Le suffixe ˋControllerˋ est utilisé souvent et il est plus explicitement descriptif. @@ -2066,7 +2066,7 @@ Bien que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'est ut - Lorsque vous regardez un fichier vous devriez instantanément savoir ce qu'il contient ce qu'il représente. - *Pourquoi ?* : Vous passez moins de temps à fouiller et vous perdre pour cherche le code, et devenez de plus en plus efficient. Si ça implique des noms de fichier plus long, alors d'accord. Soyez descriptif avec les noms de fichier et leur contenu ne doit contenir exactement qu'un seul composant. Éviter les fichier avec plusieurs controlleurs, plusieurs services, ou un mélange. On pourrait admettre une exception à cette règle si j'ai un ensemble de fonctionnalités très petites qui sont toutes reliées entre elles, elles sont toujours facilement identifiables. + *Pourquoi ?* : Vous passez moins de temps à fouiller et vous perdre pour cherche le code, et devenez de plus en plus efficient. Si ça implique des noms de fichier plus long, alors d'accord. Soyez descriptif avec les noms de fichier et leur contenu ne doit contenir exactement qu'un seul composant. Éviter les fichier avec plusieurs contrôleurs, plusieurs services, ou un mélange. On pourrait admettre une exception à cette règle si j'ai un ensemble de fonctionnalités très petites qui sont toutes reliées entre elles, elles sont toujours facilement identifiables. ### Plat ###### [Style [Y143](#style-y143)] @@ -2089,14 +2089,14 @@ Bien que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'est ut ### Règles Générales ###### [Style [Y150](#style-y150)] - - Vous devez avoir une vue court terme et une vision à long terme. En d'autres mots, commencez petit et garder en tête là où en est votre application. Tout le code de l'appli va dans un répertoire racine nommé `app`. Tout contenu fonctionnel doit être rangé dans son propre fichier. Chaque controlleur, service, module, vue doit avoir son propre fichier. Tous les scripts provenant de fournisseurs extérieurs doivent être rangés dans un autre répertoire racine et non dans le répertoire `app`. Le code que l'on écrit pas soi-même ne doit pas se mélanger avec son appli (`bower_components`, `script`, `lib`). + - Vous devez avoir une vue court terme et une vision à long terme. En d'autres mots, commencez petit et garder en tête là où en est votre application. Tout le code de l'appli va dans un répertoire racine nommé `app`. Tout contenu fonctionnel doit être rangé dans son propre fichier. Chaque contrôleur, service, module, vue doit avoir son propre fichier. Tous les scripts provenant de fournisseurs extérieurs doivent être rangés dans un autre répertoire racine et non dans le répertoire `app`. Le code que l'on écrit pas soi-même ne doit pas se mélanger avec son appli (`bower_components`, `script`, `lib`). Note : Vous trouverez plus de détails et les justifications derrière la structure sur [ce post original sur la structure des applications](http://www.johnpapa.net/angular-app-structuring-guidelines/). ### Layout ###### [Style [Y151](#style-y151)] - - Placez les composants qui définissent le layout principal de l'application dans un répertoire nommé `layout`. Il devrait inclure une vue noyau et le controlleur devrait agir comme conteneur pour l'appli, la navigation, les menus, les zones de contenu, et les autres régions. + - Placez les composants qui définissent le layout principal de l'application dans un répertoire nommé `layout`. Il devrait inclure une vue noyau et le contrôleur devrait agir comme conteneur pour l'appli, la navigation, les menus, les zones de contenu, et les autres régions. *Pourquoi ?* : Organise tout le layout à un seul endroit réutilisé dans l'application. @@ -2154,7 +2154,7 @@ Bien que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'est ut ![Structure d'une Appli Exemple](https://raw.githubusercontent.com/johnpapa/angular-styleguide/master/assets/modularity-2.png) - Note : N'utilisez pas une structuration de répertoires-par-type. Cela requiert de se déplacer entre de multiples répertoires lorsqu'on travaille sur une fonctionnalité et cela devient rapidement difficile à manier lorsque l'application grossit à 5, 10 ou plus de 25 vues et controlleurs (et autres), ce qui complique la localisation par rapport à des répertoires-par-fonctionnalité. + Note : N'utilisez pas une structuration de répertoires-par-type. Cela requiert de se déplacer entre de multiples répertoires lorsqu'on travaille sur une fonctionnalité et cela devient rapidement difficile à manier lorsque l'application grossit à 5, 10 ou plus de 25 vues et contrôleurs (et autres), ce qui complique la localisation par rapport à des répertoires-par-fonctionnalité. ```javascript /* @@ -2777,7 +2777,7 @@ Utilisez des templates de fichier ou des fragments pour vous aider à suivre des - Dans un fichier de type JavaScript, tapez ces commandes suivies par la touche `TAB` ```javascript - ngcontroller // crée un controlleur Angular + ngcontroller // crée un contrôleur Angular ngdirective // crée une directive Angular ngfactory // crée une factory Angular ngmodule // crée un module Angular @@ -2804,7 +2804,7 @@ Utilisez des templates de fichier ou des fragments pour vous aider à suivre des - Dans un fichier de type JavaScript, tapez ces commandes suivies de la touche `TAB` : ```javascript - ng-c // crée un controlleur Angular + ng-c // crée un contrôleur Angular ng-f // crée une factory Angular ng-m // crée un module Angular ``` From 3da6ff7c33e58662703ca74e17f5d36689a83879 Mon Sep 17 00:00:00 2001 From: Xavier Haniquaut Date: Tue, 18 Aug 2015 17:20:47 +0200 Subject: [PATCH 369/567] [fr-FR] Refresh french translation : Services --- i18n/fr-FR.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/i18n/fr-FR.md b/i18n/fr-FR.md index 2baee656..16c81ac1 100644 --- a/i18n/fr-FR.md +++ b/i18n/fr-FR.md @@ -689,9 +689,9 @@ Bien que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'est ut ### Singletons ###### [Style [Y040](#style-y040)] - - Les Services sont instanciés avec le mot clé `new`, utilisez `this` pour les méthodes publiques et les variables. Puisque ces derniers sont tellement similaires aux factories, utilisez à la place une factory pour la cohérence. + - Les services sont instanciés avec le mot clé `new`, utilisez `this` pour les méthodes publiques et les variables. Puisque ces derniers sont tellement similaires aux *factories*, utilisez à la place une *factory* pour la cohérence. - Note : [Tous les serices Angular services sont des singletons](https://docs.angularjs.org/guide/services). Celà signifie qu'il n'y a qu'une seule instance d'un service donné par injecteur. + Note : [Tous les services Angular sont des singletons](https://docs.angularjs.org/guide/services). Cela signifie qu'il n'y a qu'une seule instance d'un service donné par injecteur. ```javascript // service From 69238f75aef59ec85b302c28c160409ba09bf290 Mon Sep 17 00:00:00 2001 From: Xavier Haniquaut Date: Tue, 18 Aug 2015 17:42:26 +0200 Subject: [PATCH 370/567] [fr-FR] Refresh french translation : Factories --- i18n/fr-FR.md | 62 +++++++++++++++++++++++++-------------------------- 1 file changed, 31 insertions(+), 31 deletions(-) diff --git a/i18n/fr-FR.md b/i18n/fr-FR.md index 16c81ac1..70048ea5 100644 --- a/i18n/fr-FR.md +++ b/i18n/fr-FR.md @@ -56,7 +56,7 @@ Bien que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'est ut 1. [Contribuer](#contribuer) 1. [Licence](#license) -## Responsabilité Unique +## Responsabilité unique ### Règle d'unicité ###### [Style [Y001](#style-y001)] @@ -721,32 +721,32 @@ Bien que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'est ut } ``` -**[Retour en faut de page](#table-des-matières)** +**[Retour en haut de page](#table-des-matières)** ## Factories -### Responsabilité Unique +### Responsabilité unique ###### [Style [Y050](#style-y050)] - - Les factories ne devraient avoir qu'une [unique responsabilité](http://en.wikipedia.org/wiki/Single_responsibility_principle), c'est-à-dire encapsulé par son contexte. Une fois qu'une factory commence à dépasser ce but unique, une nouvelle factory devrait être créée. + - Les *factories* ne devraient avoir qu'une [seule et unique responsabilité](http://en.wikipedia.org/wiki/Single_responsibility_principle), qui serait encapsulée par son contexte. Une fois qu'une *factory* commence à dépasser cet unique cadre, une nouvelle *factory* devrait être créée. ### Singletons ###### [Style [Y051](#style-y051)] - - Les factories sont des singletons et renvoient un objet qui contient les membres du service. + - Les *factories* sont des singletons et retournent un objet qui contient les membres du service. Note : [Tous les services Angular sont des singletons](https://docs.angularjs.org/guide/services). -### Membres Accessibles Tout en Haut +### Membres accessibles au début ###### [Style [Y052](#style-y052)] - - Exposer les membres appellables du services (son interface) en haut, utilisant une technique dérivée du Principe du Module Révélateur ou [Revealing Module Pattern](http://addyosmani.com/resources/essentialjsdesignpatterns/book/#revealingmodulepatternjavascript). + - Placez les membres appelables du services (son interface) en haut, utilisant une technique dérivée du [*Revealing Module Pattern*](http://addyosmani.com/resources/essentialjsdesignpatterns/book/#revealingmodulepatternjavascript). - *Pourquoi ?* : Placer les membres appellables tout en haut le rend facile à lire et vous aide à identifier instantanément quels membres du service peut être appellé et doit être testé unitairement (et/ou mocké). + *Pourquoi ?* : Placer les membres appelables au début facilite la lecture et vous aide à identifier instantanément quels membres du service peuvent être appelés et doivent être testés unitairement (et/ou *mockés*). - *Pourquoi ?* : Ceci est spécialement conseillé lorsque le fichier devient un peu long et celà aide à éviter le besoin de faire défiler pour voir ce qui est exposé. + *Pourquoi ?* : C'est particulièrement efficace lorsque le fichier devient long et permet d'éviter de faire défiler tout le code pour voir ce qui est exposé. - *Pourquoi ?* : Placer les fonctions au fil de l'écriture semble être facile, mais quand ces fonctions ont plus d'une ligne de code, elles peuvent réduire la lisibilité et causer plus de défilement. Définir l'interface à appeller via le service renvoyé déplace les détails d'implémentation plus bas, garde l'interface appellante tout en haut, et rend le tout plus facile à lire. + *Pourquoi ?* : Placer les fonctions au fil de l'écriture semble facile, mais quand elles font plus d'une ligne, elles peuvent vite réduire la lisibilité et causer plus de défilement. Définir l'interface à appeler via le service retourné déplace les détails d'implémentation plus bas, garde l'interface d'appel en haut, et rend le tout plus facile à lire. ```javascript /* à éviter */ @@ -790,52 +790,52 @@ Bien que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'est ut } ``` - De cette façon, les bindings sont dupliqués à travers l'objet hôte, les valeurs primitives ne peuvant se mettre à jour toutes seules grâce au principe du module révélateur. + De cette façon, les *bindings* sont répliqués à travers l'objet de capture, les valeurs primitives ne peuvent pas se mettre à jour toutes seules grâce au *revealing module pattern*. - ![Factories Utilisants "Au dessus du Pliage"](https://raw.githubusercontent.com/johnpapa/angular-styleguide/master/assets/above-the-fold-2.png) + ![Factories utilisant la syntaxe avec les membres bindables au dessus](https://raw.githubusercontent.com/johnpapa/angular-styleguide/master/assets/above-the-fold-2.png) -### Déclaration de Fonctions pour Cacher les Détails d'Implémentation +### Déclaration des fonctions pour cacher les détails d'implémentation ###### [Style [Y053](#style-y053)] - - Utilisez les déclarations de fonction pour cacher les détails d'implémentation. Gardez les membres accessibles de la factory tout en haut. Faites-les pointer vers les déclarations de fonction qui apparaissent plus loin dans le fichier. Pour plus de détails, voir [ce post](http://www.johnpapa.net/angular-function-declarations-function-expressions-and-readable-code). + - Utilisez les déclarations de fonctions pour cacher les détails d'implémentation. Gardez les membres accessibles de la *factory* en haut. Faites-les pointer vers les déclarations de fonction qui apparaissent plus loin dans le fichier. Pour plus de détails, vous pouvez lire [cet article](http://www.johnpapa.net/angular-function-declarations-function-expressions-and-readable-code). - *Pourquoi ?* : Placer les membres accessibles tout en haut permet de le rendre facile à lire et vous aide à identifier instantanément quelles fonctions de la factory vous pouvez accéder de l'extérieur. + *Pourquoi ?* : Placer les membres accessibles en haut facilite la lecture et vous aide instantanément à identifier quels membres de la *factory* peuvent être appelés depuis l'extérieur. - *Pourquoi ?* : Placer les détails d'implémentation d'une fonction plus loin dans le fichier déplace cette complexité en dehors de la vue afin de voir les choses importantes tout en haut. + *Pourquoi ?* : Placer les détails d'implémentation d'une fonction plus bas dans le fichier permet de masquer la complexité. Ainsi vous ne pouvez voir que les choses importantes en haut. - *Pourquoi ?* : Les déclarations de fonctions sont hissées de telle sorte qu'il n'y ait aucun soucis à utiliser une fonction avant qu'elle ne soit définie (comme il serait de mise avec les expressions fonctionnelles). + *Pourquoi ?* : Les déclarations de fonctions sont *hoistées* donc il n'y a pas problème à utiliser une fonction avant qu'elle ne soit définie (alors que ça serait le cas avec les expressions de fonction). - *Pourquoi ?* : Vous n'aurez plus jamais à vous en faire avec les déclarations de fonction dont le déplacement de `var a` avant `var b` pourrait casser votre code à cause d'une dépendance de `a` vers `b`. + *Pourquoi ?* : Vous ne vous préoccuperez plus des déclarations de fonctions déplaçant `var a` avant `var b` cassant ainsi votre code car `a` dépendait de `b`. - *Pourquoi ?* : L'ordre est critique avec les expressions fonctionnelles. + *Pourquoi ?* : L'ordre est critique avec les expressions de fonctions. ```javascript /** * À éviter - * L'utilisation des expressions fonctionnelles + * Utilisation des expressions de fonctions */ function dataservice($http, $location, $q, exception, logger) { var isPrimed = false; var primePromise; var getAvengers = function() { - // avec les détails d'implémentation ici + // détails d'implémentation }; var getAvengerCount = function() { - // avec les détails d'implémentation ici + // détails d'implémentation }; var getAvengersCast = function() { - // avec les détails d'implémentation ici + // détails d'implémentation }; var prime = function() { - // avec les détails d'implémentation ici + // détails d'implémentation }; var ready = function(nextPromises) { - // avec les détails d'implémentation ici + // détails d'implémentation }; var service = { @@ -852,8 +852,8 @@ Bien que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'est ut ```javascript /** * recommandé - * L'utilisation des déclararions de fonction - * et des membres accessibles tout en haut. + * Utilisation des déclarations de fonctions + * et des membres accessibles au début. */ function dataservice($http, $location, $q, exception, logger) { var isPrimed = false; @@ -871,19 +871,19 @@ Bien que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'est ut //////////// function getAvengers() { - // avec les détails d'implémentation ici + // détails d'implémentation } function getAvengerCount() { - // avec les détails d'implémentation ici + // détails d'implémentation } function getAvengersCast() { - // avec les détails d'implémentation ici + // détails d'implémentation } function prime() { - // avec les détails d'implémentation ici + // détails d'implémentation } function ready(nextPromises) { From 32950f07d4d81103c39d57aa14c056319ca2acbe Mon Sep 17 00:00:00 2001 From: Xavier Haniquaut Date: Tue, 18 Aug 2015 19:14:40 +0200 Subject: [PATCH 371/567] [fr-FR] Refresh french translation : Data services --- i18n/fr-FR.md | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/i18n/fr-FR.md b/i18n/fr-FR.md index 70048ea5..75f4fbb3 100644 --- a/i18n/fr-FR.md +++ b/i18n/fr-FR.md @@ -894,23 +894,23 @@ Bien que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'est ut **[Retour en haut de page](#table-des-matières)** -## Services de Données +## Services de données -### Séparer les Appels de Données +### Séparer les appels aux données ###### [Style [Y060](#style-y060)] - - Refactorer la logique pour faire les opérations sur les données et les interactions avec la donnée dans une factory. Rendez les services de données responsables des appels ajax, du local storage, du stockage en mémoire, ou toute autre opérations sur les données. + - *Refactorez* la logique pour faire les opérations et interactions avec les données dans une *factory*. Rendez les services de données responsables des appels *XHR*, du *local storage*, du stockage en mémoire, ou de toute autre opération sur les données. - *Pourquoi ?* : La responsabilité du contrôleur est la présentation et l'assemblage des informations pour la vue. Il ne devrait pas se soucier de la façon dont la donnée est récupérée, mais seulement de la façon de la demander. Séparer des services de données déplace la logique du 'comment récupérer une donnée' dans ce service de donnée, et laisse le contrôleur plus simple et plus focalisé sur la vue. + *Pourquoi ?* : Les responsabilités du contrôleur sont la présentation et l'assemblage des informations pour la vue. Il ne devrait pas avoir à se soucier de la façon dont les données sont récupérées mais seulement de la façon de les demander. Séparer les services de données transforme la logique du contrôleur en logique de « À quel service vais-je demander ces données ? ». Le contrôleur esr alors plus simple est plus focalisé sur sa vue. - *Pourquoi ?* : Cela le rend plus facile à tester (en mockant ou avec le vrai) les appels aux données lorsque l'on teste un contrôleur qui utilise un service de données. + *Pourquoi ?* : Cela rend plus facile à tester (*mocké* ou en utilisant le vrai) les appels aux données lorsque l'on teste un contrôleur qui utilise un service de données. - *Pourquoi ?* : L'implémentation d'un service de données peut avoir du code très spécifique pour gérer le référentiel des données. Celà peut inclure des entêtes, la façon de dialoguer avec la donnée, ou des dépendances vers d'autres services tels que $http. La séparation de la logique vers un service de données encapsule cette logique dans un unique endroit en cachant les détails d'implémentation du consommateur externe (peut-être un contrôleur), en rendant également plus simple les changements d'implémentation. + *Pourquoi ?* : L'implémentation d'un service de données peut contenir du code très spécifique pour gérer le système de données. Cela peut inclure des entêtes, la façon de dialoguer avec les données, ou d'autres services tels que `$http`. Séparer la logique vers un service de données permet d'encapsuler cette logique dans un unique endroit en cachant les détails d'implémentation des consommateurs externes (tel qu'un contrôleur), en rendant également plus simple les changements d'implémentation. ```javascript /* Recommandé */ - // une factory service de données + // Factory jouant le rôle de service de données angular .module('app.core') .factory('dataservice', dataservice); @@ -938,12 +938,12 @@ Bien que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'est ut } ``` - Note : Le service de données est appellé depuis des consommateurs, tels que des contrôleurs, en leur cachant l'implémentation, comme le montre l'éxemple ci-dessous. + Note : Le service de données est appelé par des consommateurs extérieur, tels que des contrôleurs, en leur cachant l'implémentation, comme ci-dessous. ```javascript /* Recommandé */ - // un contrôleur qui appelle la factory du service de données + // Contrôleur appelant la factory faisant le service de données angular .module('app.avengers') .controller('Avengers', Avengers); @@ -972,12 +972,12 @@ Bien que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'est ut } ``` -### Retourner une promesse depuis un appel de donnée +### Retourner une promesse suite à un appel de données ###### [Style [Y061](#style-y061)] - - Lorsqu'un service de données retourne une promesse telle que $http, retournez une promesse dans votre fonction appelée. + - Quand vous appelez un service de données tel que `$http` qui retourne une *promise*, retournez également une *promise* dans votre fonction appelante. - *Pourquoi ?* : Vous pouvez chainer les promesses entre elles et ajouter des actions après que l'appel des données soit terminé puis résoudre ou rejeter la promesse. + *Pourquoi ?* : Vous pouvez chaîner les promesses entre elles et entreprendre d'autres actions après que l'appel soit terminé, puis résoudre ou rejeter la promesse. ```javascript /* recommandé */ @@ -987,13 +987,13 @@ Bien que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'est ut function activate() { /** * Etape 1 - * Appel la fonction getAvengers pour récupérer - * les données avenger et attend la promesse + * Appelle la fonction getAvengers pour récupérer + * les données «avenger» et attend la promise. */ return getAvengers().then(function() { /** * Etape 4 - * Exécute une action à la résolution de la promesse finale + * Exécute une action à la résolution de la promise finale. */ logger.info('Activated Avengers View'); }); @@ -1003,13 +1003,13 @@ Bien que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'est ut /** * Etape 2 * Appel du service de données pour récupérer les données - * et attend la promesse + * et attend la promesse. */ return dataservice.getAvengers() .then(function(data) { /** * Etape 3 - * Défini les donnée et résoue la promesse + * Définit les données et résout la promesse. */ vm.avengers = data; return vm.avengers; From a6c021bf9c562fd92fc050ab58feca83153512bf Mon Sep 17 00:00:00 2001 From: Xavier Haniquaut Date: Tue, 18 Aug 2015 19:55:56 +0200 Subject: [PATCH 372/567] [fr-FR] Refresh french translation : Directives --- i18n/fr-FR.md | 88 +++++++++++++++++++++++++++++---------------------- 1 file changed, 50 insertions(+), 38 deletions(-) diff --git a/i18n/fr-FR.md b/i18n/fr-FR.md index 75f4fbb3..79928fcf 100644 --- a/i18n/fr-FR.md +++ b/i18n/fr-FR.md @@ -1020,16 +1020,16 @@ Bien que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'est ut **[Retour en haut de page](#table-des-matières)** ## Directives -### Limite de 1 Par Fichier +### Une directive par fichier ###### [Style [Y070](#style-y070)] - - Créer une directive par fichier. Nommer le fichier en fonction de la directive. + - Créez seulement une directive par fichier. Nommer le fichier en fonction de la directive. - *Pourquoi ?* : C'est facile de placer toutes les directives dans un fichier, mais difficile de les séparer, certains sont partagés par toute l'application, certain par modules, et certain juste par un module. + *Pourquoi ?* : Il est facile de placer toutes les directives dans un fichier, mais il l'est moins de les séparer après coup. Certaines sont partagées dans toute l'application, certaines par modules, et certaines juste par un seul module. - *Pourquoi ?* : Une directive par fichier est plus facilement maintenable. + *Pourquoi ?* : Une directive par fichier leur permet d'être plus facilement maintenables. - > Note : "**Bonne pratique** : Les directives devraient pouvoir s'auto-nettoyer. Vous pouvez utiliser `element.on('$destroy', ...)` ou `scope.$on('$destroy', ...)` pour lancer une fonction de nettoyage quand une directive est enlevée" ... - Documentation d'Angular + > Note : "**Bonne pratique** : Les directives devraient pouvoir s'auto-nettoyer. Vous pouvez utiliser `element.on('$destroy', ...)` ou bien `scope.$on('$destroy', ...)` pour lancer une fonction de nettoyage quand une directive est enlevée" ... - Documentation d'Angular ```javascript /* à éviter */ @@ -1038,25 +1038,25 @@ Bien que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'est ut angular .module('app.widgets') - /* directive order spécifique pour le module order */ + /* directive spécifique pour le module order */ .directive('orderCalendarRange', orderCalendarRange) - /* directive sales pouvant être utilisée n'importe où dans l'application sales */ + /* directive pouvant être utilisée n'importe où dans l'application sales */ .directive('salesCustomerInfo', salesCustomerInfo) - /* directive spinner pouvant être utilisée n'importe où dans l'application */ + /* directive pouvant être utilisée n'importe où dans l'application */ .directive('sharedSpinner', sharedSpinner); function orderCalendarRange() { - /* détails de l'implémentation */ + /* détails d'implémentation */ } function salesCustomerInfo() { - /* détails de l'implémentation */ + /* détails d'implémentation */ } function sharedSpinner() { - /* détails de l'implémentation */ + /* détails d'implémentation */ } ``` @@ -1065,7 +1065,7 @@ Bien que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'est ut /* calendarRange.directive.js */ /** - * @desc directive order spécifique pour le module order pour la compagnie Acme + * @desc directive spécifique pour le module order de l'entreprise Acme * @example
*/ angular @@ -1073,7 +1073,7 @@ Bien que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'est ut .directive('acmeOrderCalendarRange', orderCalendarRange); function orderCalendarRange() { - /* détails de l'implémentation */ + /* détails d'implémentation */ } ``` @@ -1082,7 +1082,7 @@ Bien que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'est ut /* customerInfo.directive.js */ /** - * @desc directive sales pouvant être utilisée n'importe où dans l'application sales pour la compagnie Acme + * @desc directive pouvant être utilisée n'importe où dans l'application sales de l'entreprise Acme * @example
*/ angular @@ -1090,7 +1090,7 @@ Bien que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'est ut .directive('acmeSalesCustomerInfo', salesCustomerInfo); function salesCustomerInfo() { - /* détails de l'implémentation */ + /* détails d'implémentation */ } ``` @@ -1099,7 +1099,7 @@ Bien que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'est ut /* spinner.directive.js */ /** - * @desc directive spinner pouvant être utilisée n'importe où dans l'application pour la compagnie Acme + * @desc directive pouvant être utilisée n'importe où dans l'application de l'entreprise Acme * @example
*/ angular @@ -1107,38 +1107,38 @@ Bien que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'est ut .directive('acmeSharedSpinner', sharedSpinner); function sharedSpinner() { - /* détails de l'implémentation */ + /* détails d'implémentation */ } ``` - Note : Il y a plusieurs options de nommage pour les directives, puisqu'elles peuvent être utilisé par des scopes plus ou moins larges. Choisissez un nom qui rend la directive et son fichier clair et distinct. Des exemples sont définis plus bas, mais regarder la section des noms pour plus de recommandations. + Note : Il y a plusieurs options de nommage pour les directives puisqu'elles peuvent être utilisées à des échelles (*scopes*) plus ou moins larges. Choisissez un nom qui rend la directive et son fichier clairs et distincts. Des exemples sont définis plus bas mais regardez la section [nommage](#nommage) pour plus de recommandations. -### Manipuler le DOM dans une Directive +### Manipuler le DOM dans une directive ###### [Style [Y072](#style-y072)] - - Quand le DOM est directement manipulé, utilisez une directive. Si une alternative peut être utilisé avec le CSS pour définir le style ou les [services d'animation](https://docs.angularjs.org/api/ngAnimate), les templates Angular , [`ngShow`](https://docs.angularjs.org/api/ng/directive/ngShow) ou [`ngHide`](https://docs.angularjs.org/api/ng/directive/ngHide), mieux vaut les utiliser à la place. Par exemple, si la directive affiche ou cache un élément, utilisez ngHide/ngShow. + - Quand vous manipulez le DOM est directement, utilisez une directive. S'il existe des alternatives, comme par exemple le CSS pour définir les styles ou les [services d'animation](https://docs.angularjs.org/api/ngAnimate), les *templates* Angular , [`ngShow`](https://docs.angularjs.org/api/ng/directive/ngShow) ou [`ngHide`](https://docs.angularjs.org/api/ng/directive/ngHide), utilisez les à la place. Par exemple si la directive affiche ou cache un élément, utilisez ngHide ou ngShow. - *Pourquoi ?* : La manipulation du DOM peut être difficile à tester, debugger, et il y a souvent une meilleure façon de faire (e.g. CSS, animations, templates) + *Pourquoi ?* : La manipulation du DOM peut être difficile à tester, déboguer, et il y a souvent une meilleure façon de faire (ex : CSS, animations, *templates*). -### Fournir un Unique Préfixe de Directive +### Utiliser un unique préfixe de directive ###### [Style [Y073](#style-y073)] - - Definissez un préfixe de directive court, unique et descriptif tel que `acmeSalesCustomerInfo` et déclaré en HTML comme `acme-sales-customer-info`. + - Définissez un unique préfixe de directive court et descriptif comme dans `acmeSalesCustomerInfo` et utilisé dans le HTML de la façon suivante : `acme-sales-customer-info`. - *Pourquoi ?* : Le préfixe court et unique identifie le contexte et l'origine de la directive. Par exemple, un préfixe `cc-` peut indiquer que la directive fait partie de l'application CodeCamper alors que `acme-` peut indiquer une directive de la companie Acme. + *Pourquoi ?* : Un préfixe court et unique identifie le contexte et l'origine de la directive. Par exemple, un préfixe comme `cc-` peut indiquer que la directive fait partie de l'application CodeCamper tandis que `acme-` peut indiquer une directive de l'entreprise Acme. - Note : Evitez `ng-` car il est réservé pour les directives Angular. Cherchez les directives largement utilisées pour éviter les conflits de nom, tel que `ion-` pour le [Framework Ionic](http://ionicframework.com/). + Note : Évitez d'utiliser le préfixe `ng-` car il est réservé pour les directives Angular. Cherchez les directives populaire pour éviter les conflits de nommage, tel que `ion-` pour les directives du framework [Ionic](http://ionicframework.com/). -### Restreindre aux Éléments et aux Attributs +### Restreindre aux éléments et aux attributs ###### [Style [Y074](#style-y074)] - - Lors de la création d'une directive qui fait du sens comme élément indépendant, permettez la restriction `E` (élément personnalisé) et éventuellement la restriction `A` (attribut personnalisé). En général, s'il devrait avoir son propre contrôle, `E` est le plus indiqué. Le conseil le plus général est de permettre `EA` mais se dirige vers une implémentation en tant qu'élément lorsqu'il est indépendant et en tant qu'attribut lorsqu'il améliore un élément DOM existant. + - Lors de la création d'une directive qui fait du sens comme élément indépendant, autorisez la restriction `E` (élément personnalisé) et éventuellement la restriction `A` (attribut personnalisé). En général, s'il devrait avoir son propre contrôle, `E` est le plus indiqué. La convention la plus utilisée est de permettre `EA` mais se dirige vers une implémentation en tant qu'élément lorsque la directive est indépendante et en tant qu'attribut lorsqu'elle augmente son propre élément de DOM. - *Pourquoi ?* : Çela a du sens. + *Pourquoi ?* : Cela a du sens. - *Pourquoi ?* : Même s'il est autorisé d'utiliser une directive en tant que classe, si la directive agit vraiement comme un élément, elle fait plus de sens en tant qu'élément ou au moins en tant qu'attribut. + *Pourquoi ?* : Même s'il est autorisé d'utiliser une directive en tant que classe, si la directive agit vraiment comme un élément, elle fait plus de sens en tant qu'élément ou au moins en tant qu'attribut. - Note : EA est la valeur par défaut avec Angular 1.3 + + Note : EA est la valeur par défaut dans Angular 1.3 + ```html @@ -1191,18 +1191,18 @@ Bien que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'est ut } ``` -### Directives et ControllerAs +### Directives et `controllerAs` ###### [Style [Y075](#style-y075)] - - Utilisez la syntaxe `controller as` avec une directive pour être cohérent avec l'utilisation de `controller as` pour l'association de la vue et du contrôleur. + - Utilisez la syntaxe avec `controllerAs` avec une directive pour être cohérent avec l'utilisation de `controllerAs` pour l'association de la vue et de son contrôleur. *Pourquoi ?* : Ça fait sens et ce n'est pas difficile. - Note : La directive ci-dessous démontre une façon parmis d'autres d'utiliser le scope à l'intérieur de la fonction link et dans un contrôleur de directive, par l'utilisation de controllerAs. J'ai in-liné le template que pour le mettre au même endroit. + Note : La directive ci-dessous montre une façon parmi d'autres d'utiliser *scope* à l'intérieur de la fonction `link` et dans un contrôleur de directive, par l'utilisation de `controllerAs`. J'ai *inliné* le template pour tout mettre au même endroit. - Note : Concernant l'injection de dépendance, voir [Identifier Manuellement les Dépendances](#manual-annotating-for-dependency-injection). + Note : Concernant l'injection de dépendances, voir [Annoter manuellement les dépendances à injecter](#annoter-manuellement-les-dépendances-à-injecter). - Note : Remarquez que le contrôleur de la directive est à l'extérieur de la closure de la directive. Cette façon de faire évite le problème des injections plus disponibles après le `return`. + Note : Remarquez que le contrôleur de la directive est à l'extérieur de la *closure* de la directive. Cette façon de faire évite le problème d'indisponibilité des injections après le `return`. ```html
@@ -1239,7 +1239,7 @@ Bien que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'est ut ExampleController.$inject = ['$scope']; function ExampleController($scope) { - // Injection du $scope seuelement pour la comparaison + // Injection de $scope seulement pour la comparaison var vm = this; vm.min = 3; @@ -1258,11 +1258,23 @@ Bien que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'est ut
min={{vm.min}}
``` + Note : Vous pouvez aussi nommer le contrôleur au moment où vous l'injectez dans la fonction de `link` et accéder aux attributs de la directive en temps que propriétés du contrôleur. + + ```javascript + // Alternative to above example + function linkFunc(scope, el, attr, vm) { + console.log('LINK: scope.min = %s *** should be undefined', scope.min); + console.log('LINK: scope.max = %s *** should be undefined', scope.max); + console.log('LINK: vm.min = %s', vm.min); + console.log('LINK: vm.max = %s', vm.max); + } + ``` + ###### [Style [Y076](#style-y076)] - - Utilisez `bindToController = true` lorsque vous utilisez la syntaxe `controller as` avec une directive quand vous voulez binder le scope externe au scope du contrôleur de la directive. + - Utilisez `bindToController = true` lorsque vous utilisez la syntaxe avec `controllerAs` avec une directive quand vous voulez *binder* le *scope* externe au *scope* du contrôleur de la directive. - *Pourquoi ?* : Cela rend plus facile de binder le scope externe au scope du contrôleur de la directive. + *Pourquoi ?* : Cela rend plus facile de *binder* le *scope* externe au *scope* du contrôleur de la directive. Note : `bindToController` a été introduit à partir de Angular 1.3.0. From 1189d5518bf7e1596be42caed545c1b173e82ed7 Mon Sep 17 00:00:00 2001 From: Xavier Haniquaut Date: Tue, 18 Aug 2015 20:24:04 +0200 Subject: [PATCH 373/567] [fr-FR] Refresh french translation : Resolving Promises for a Controller --- i18n/fr-FR.md | 31 +++++++++++++++---------------- 1 file changed, 15 insertions(+), 16 deletions(-) diff --git a/i18n/fr-FR.md b/i18n/fr-FR.md index 79928fcf..bab89f61 100644 --- a/i18n/fr-FR.md +++ b/i18n/fr-FR.md @@ -1319,18 +1319,17 @@ Bien que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'est ut **[Retour en haut de page](#table-des-matières)** -## Résolution des Promesses pour un Contrôleur - -### Promesses d'Activation du Controller +## Résolution des *promises* pour un contrôleur +### *Promises* d'activation du contrôleur ###### [Style [Y080](#style-y080)] - - Résolvez la logique de démarrage d'un contrôleur dans une fonction `activate`. + - Résolvez la logique d'initialisation d'un contrôleur dans une fonction `activate`. - *Pourquoi ?* : Placer la logique de démarrage toujours au même endroit permet de le rendre plus facile à localiser, plus cohérent à tester, et permet d'éviter la dispersion de la logique d'activation à travers le contrôleur. + *Pourquoi ?* : Placer la logique d'initialisation toujours au même endroit permet de la rendre plus facile à localiser, plus cohérente à tester, et permet d'éviter sa dispersion à travers le contrôleur. - *Pourquoi ?* : La fonction `activate` d'un contrôleur rend pratique la ré-utilisation de la logique pour un refraichissement du contrôleur ou de la vue, garde cette logique à un seul endroit, envoie l'utilisateur plus rapidement à la Vue, rend les animations faciles sur la `ng-view` ou l'`ui-view`, et c'est rendu plus vif à l'utilisateur. + *Pourquoi ?* : La fonction `activate` du contrôleur rend pratique la ré-utilisation de la logique pour un rafraîchissement du contrôleur ou de la vue, garde cette logique en un seul endroit, envoie la vue à l'utilisateur plus rapidement, rend les animations faciles sur `ng-view` ou `ui-view` et rend l'interface plus réactive pour l'utilisateur. - Note : Si vous avez besoin d'annuler sous conditions la route avant de vous mettre à utiliser le contrôleur, utilisez une [résolution de route](#style-y081) à la place. + Note : Si vous avez besoin d'annuler de façon conditionnelle la route avant d'utiliser le contrôleur, utilisez la [résolution de route](#style-y081) à la place. ```javascript /* à éviter */ @@ -1366,18 +1365,18 @@ Bien que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'est ut } ``` -### Promesses de Résolution de Route +### *Promises* de résolution de route ###### [Style [Y081](#style-y081)] - - Lorsqu'un contrôleur dépend d'une promesse qui doit être résolue avant qu'un contrôleur soit activé, résolvez ces dépendances dans le `$routeProvider`. Si vous avez besoin d'annuler une route sous certaines conditions avant que le contrôleur soit activé, utilisez un resolver de route. + - Lorsqu'un contrôleur dépend d'une *promise* qui doit être résolue avant que le contrôleur soit activé, résolvez ces dépendances dans le `$routeProvider` avant que la logique du contrôleur soit exécutée. Si vous avez besoin d'annuler une route de façon conditionnelle avant que le contrôleur soit activé, utilisez un *resolver* de route. - - Utilisez un resolver de route dès lors que vous voulez décider d'annuler la route avant même de commencer à naviguer vers la Vue. + - Utilisez un *resolver* de route quand vous voulez pouvoir décider d'annuler la route avant même de commencer à naviguer vers la vue. - *Pourquoi ?* : Un contrôleur pourrait avoir besoin de données avant qu'il se charge. Cette donnée pourrait venir d'une promesse via une factory personnalisée ou de [$http](https://docs.angularjs.org/api/ng/service/$http). Utiliser une [resolution de route](https://docs.angularjs.org/api/ngRoute/provider/$routeProvider) permet à la promesse de se résoudre avant que la logique du contrôleur s'éxécute, ainsi on peut prendre des actions basées sur cette donnée à partir de la promesse. + *Pourquoi ?* : Un contrôleur pourrait avoir besoin de données avant de se charger. Ces données pourraient provenir d'une promesse via une *factory* ou de [`$http`](https://docs.angularjs.org/api/ng/service/$http). Utiliser une [résolution de route](https://docs.angularjs.org/api/ngRoute/provider/$routeProvider) permet à la promesse de se résoudre avant que la logique du contrôleur s’exécute, alors seulement, on peut exécuter les actions basées sur les données fournies via la *promises*. - *Pourquoi ?* : Le code s'éxécute après la route et dans la fonction activate du contrôleur. La Vue commence à se charger tout de suite. Le data binding démarre quand la promesse d'activation se résoud. Une animation de "chargement" peut être affichée pendant que la vue opère la transition (via `ng-view` ou `ui-view`). + *Pourquoi ?* : Le code s’exécute après la route et dans la fonction `activate` du contrôleur. La vue commence à se charger tout de suite. Le *data-binding* démarre quand la *promise* d'activation se résout. Une animation de « chargement » peut être affichée pendant la transition (via `ng-view` ou `ui-view`). - Note : Le code s'éxécute avant la route via une promesse. Le rejet de la promesse annule le routage. Sa résolution met la nouvelle vue en attente de la résolution du routage. Une animation de "chargement" peut être affichée avant la résolution et lorsque la vue entre en transition. Si vous voulez aller à la Vue plus vite et que vous n'avez pas besoin d'un point pour décider si vous voulez atteindre la Vue, il est conseillé d'utiliser la [technique de l'activation de contrôleur](#style-y080) à la place. + Note : Le code s’exécute avant la route via une *promise*. Le rejet de la promesse annule le routage. Sa résolution met la future vue en attente de la résolution du routage. Une animation de « chargement » peut être affichée avant la résolution et lorsque la vue change d'état. Si vous voulez aller à la vue plus vite et que vous n'avez pas besoin d'une étape pour décider si vous pouvez l'atteindre, il est conseillé d'utiliser à la place la [technique de la fonction `activate` dans le contrôleur](#style-y080). ```javascript /* à éviter */ @@ -1389,7 +1388,7 @@ Bien que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'est ut var vm = this; // non-résolue vm.movies; - // résolue de façon asynchrone + // résolu de façon asynchrone movieService.getMovies().then(function(response) { vm.movies = response.movies; }); @@ -1430,7 +1429,7 @@ Bien que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'est ut } ``` - Note : L'exemple ci-dessous montre que la résolution de routage pointe vers une fonction nommée, laquelle est plus facile à débugguer et dont l'injection de dépendance est plus facile à gérer. + Note : L'exemple ci-dessous montre que la résolution du routage pointe vers une fonction nommée, laquelle est plus facile à déboguer et dont l'injection de dépendance est plus facile à gérer. ```javascript /* encore mieux */ @@ -1467,7 +1466,7 @@ Bien que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'est ut vm.movies = moviesPrepService.movies; } ``` - Note : Les dépendances dans l'exemple de code sur `movieService` ne sont pas directement compatibles avec la minification. Pour les détails sur la façon de rendre ce code compatible avec la minification, voir la section sur l'[injection de dépendance](#manual-annotating-for-dependency-injection) et sur [la minification et les annotations](#minification-and-annotation). + Note : Les dépendances sur `movieService` dans l'exemple ne sont pas directement compatibles avec le processus de minification. Pour plus de détails sur la façon de rendre ce code minifiable sans risques, voir la section sur l'[injection de dépendances](#manual-annotating-for-dependency-injection) et sur [la minification et les annotations](#minification-and-annotation). **[Retour en haut de page](#table-des-matières)** From c06bbc4063f69d2b0d6f7d08d37e982540631aba Mon Sep 17 00:00:00 2001 From: Xavier Haniquaut Date: Tue, 18 Aug 2015 20:47:24 +0200 Subject: [PATCH 374/567] [fr-FR] Refresh french translation : Manual Annotating for Dependency Injection --- i18n/fr-FR.md | 39 ++++++++++++++++++++------------------- 1 file changed, 20 insertions(+), 19 deletions(-) diff --git a/i18n/fr-FR.md b/i18n/fr-FR.md index bab89f61..2cccb733 100644 --- a/i18n/fr-FR.md +++ b/i18n/fr-FR.md @@ -1470,17 +1470,17 @@ Bien que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'est ut **[Retour en haut de page](#table-des-matières)** -## Annoter Manuellement pour l'Injection de Dépendances +## Annotation manuelle pour l'injection de dépendances -### Non Sur pour la Minification +### Risques pour la minification ###### [Style [Y090](#style-y090)] - - Eviter l'utilisation de la syntaxe raccourcie de déclaration des dépendances sans utiliser une approche sûre pour la minification. + - Évitez l'utilisation de la syntaxe raccourcie pour déclaration de dépendances. Ulilisez plutôt une approche compatible avec la minification. - *Pourquoi ?* : Les paramètres du composant (ex: contrôleur, factory, etc.) seront converties en variables mutilées. Par exemple, ˋcommonˋet ˋdataserviceˋ deviendraient ˋaˋet ˋbˋ et ne seraient pas trouvées par Angular. + *Pourquoi ?* : Les paramètres des composants (ex: contrôleur, *factory*, etc.) vont êtres convertis en variables raccourcies. Par exemple, ˋcommonˋ et ˋdataserviceˋ deviendraient ˋaˋ et ˋbˋ et ne seraient pas trouvées par Angular. ```javascript - /* à éviter - non sûr pour la minification */ + /* à éviter - non compatible avec la minification */ angular .module('app') .controller('Dashboard', Dashboard); @@ -1489,23 +1489,23 @@ Bien que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'est ut } ``` - Ce code pourrait produire des variables mutilées après minification et en cela provoquer des erreurs à l'éxécution. + Ce code pourrait produire des variables raccourcies après minification et provoquer des erreurs à l’exécution. ```javascript - /* à éviter - non sûr pour la minification */ + /* à éviter - non compatible avec la minification */ angular.module('app').controller('Dashboard', d);function d(a, b) { } ``` -### Identifier Manuellement les Dépendances +### Identification manuelle des dépendances ###### [Style [Y091](#style-y091)] - - Utilisez ˋ$injectˋpour identifier manuellement vos dépendances de composants Angular. + - Utilisez ˋ$injectˋ pour identifier manuellement les dépendances de vos composants Angular. - *Pourquoi ? * : Cette technique est la même que celle utilisée par [`ng-annotate`](https://github.com/olov/ng-annotate), que je recommande pour automatiser la création de dépendances sûres pour la minification. Si ˋng-annotateˋ détecte que l'injection a déjà été faite, celà ne la dupliquera pas. + *Pourquoi ? * : Cette technique réplique celle utilisée par [`ng-annotate`](https://github.com/olov/ng-annotate), que je recommande afin d'automatiser la création de dépendances compatible avec la minification. Si ˋng-annotateˋ détecte que l'injection a déjà été faite, cela ne la dupliquera pas. - *Pourquoi ?* : Ca préserve vos dépendances d'être vulnérable aux problèmes de minification lorsque les paramètres sont mutilés. Par exemple, ˋcommonˋet ˋdataserviceˋpourraient devenir ˋaˋ et ˋbˋ et ne pas être trouvés par Angular. + *Pourquoi ?* : Ça assure la compatibilité de vos dépendances à la minification. Par exemple, ˋcommonˋ et ˋdataserviceˋ pourraient devenir ˋaˋ et ˋbˋ et ne pas être trouvés par Angular. - *Pourquoi ?* : Eviter de créer en ligne une longue liste de dépendances peut rendre le tableau difficile à lire. De même, il peut entraîner une confusion dans la mesure où le tableau est une série de chaînes de caratères alors que le dernier élément est le nom de la fonction du composant. + *Pourquoi ?* : Pour éviter de créer *inline* une longue liste de dépendances car les longs tableaux sont difficiles à lire. De même, cela peut être gênant de voir un tableau composé d'une série de *strings* alors que son dernier élément est un appel à la fonction du composant. ```javascript /* à éviter */ @@ -1540,7 +1540,7 @@ Bien que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'est ut } ``` - Note : Lorsque votre fonction est sous une instruction de return, le $inject peut ne pas être accessible (cela pourrait arriver dans une directive). Vous pouvez vous en sortir en bougeant le contrôleur en dehors de la directive. + Note : Lorsque votre fonction se situe sous un `return`, le `$inject` peut ne pas être accessible (cela pourrait arriver dans une directive). Vous pouvez vous en sortir en sortant le contrôleur de la directive. ```javascript /* À éviter */ @@ -1550,7 +1550,7 @@ Bien que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'est ut controller: DashboardPanelController, controllerAs: 'vm' }; - return ddo + return ddo; DashboardPanelController.$inject = ['logger']; // Inatteignable function DashboardPanelController(logger) { @@ -1560,7 +1560,7 @@ Bien que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'est ut ```javascript /* recommandé */ - // A l'exterieur d'une définition de directive + // à l'exterieur d'une définition de directive function outer() { var ddo = { controller: DashboardPanelController, @@ -1568,19 +1568,20 @@ Bien que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'est ut }; return ddo; } + DashboardPanelController.$inject = ['logger']; function DashboardPanelController(logger) { } ``` -### Identifier Manuellement les Dépendances du Route Resolver +### Identification manuelle des dépendances du *route resolver* ###### [Style [Y092](#style-y092)] - - Utilisez `$inject pour identifier manuellement vos dépendances du route resolver pour les composants Angular. + - Utilisez `$inject` pour identifier manuellement vos dépendances du *route resolver* pour les composants Angular. - *Pourquoi ?* : Cette technique divise la fonction anonyme pour le route resolver, la rendant plsu facile à lire. + *Pourquoi ?* : Cette technique divise la fonction anonyme pour le *route resolver*, le rendant plus facile à lire. - *Pourquoi ?* : Une instruction `$inject` peut facilement précéder le resolver à manipuler rendant n'importe quelle dépendance sûre à la minification. + *Pourquoi ?* : Une instruction `$inject` peut facilement précéder le *resolver* à manipuler rendant n'importe quelle dépendance compatible avec la minification. ```javascript /* recommandé */ From e41164f2787a594ff9038eb7e4c894f9f4f7dfb3 Mon Sep 17 00:00:00 2001 From: Xavier Haniquaut Date: Tue, 18 Aug 2015 21:05:33 +0200 Subject: [PATCH 375/567] [fr-FR] Refresh french translation : Minification and Annotation --- i18n/fr-FR.md | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/i18n/fr-FR.md b/i18n/fr-FR.md index 2cccb733..92738bf6 100644 --- a/i18n/fr-FR.md +++ b/i18n/fr-FR.md @@ -1612,13 +1612,13 @@ Bien que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'est ut - Utilisez [ng-annotate](//github.com/olov/ng-annotate) pour [Gulp](http://gulpjs.com) ou [Grunt](http://gruntjs.com) et commentez les fonctions qui nécessitent l'injection de dépendances automatique en utilisant `/** @ngInject */`. - *Pourquoi ?* : Ca préserve votre code de n'importe quelle dépendance qui pourrait ne pas utiliser les pratiques sûres à la minification. + *Pourquoi ?* : Cela prévient votre code d'erreur provenant de dépendances n'utilisant pas les bonnes pratiques au regard de la minification. - *Pourquoi ?*: [`ng-min`](https://github.com/btford/ngmin) est déprécié. + *Pourquoi ?*: [`ng-min`](https://github.com/btford/ngmin) est obsolète. - >Je préfère Gulp car ça me paraît plus facile à écrire, lire et débugger. + >Je préfère Gulp car ça me paraît plus facile à écrire, lire et déboguer. - Le code suivant n'utilise pas de dépendances sûres à la minification. + Le code suivant n'utilise pas de dépendances compatibles avec la minification. ```javascript angular @@ -1638,7 +1638,7 @@ Bien que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'est ut } ``` - Lorsque le code ci-dessus est éxécuté par ng-annotate il produira le résultat suivant avec l'annotation ˋ$injectˋ et deviendra sûr à la minification. + Lorsque le code ci-dessus sera exécuté par `ng-annotate`, il produira le résultat suivant avec l'annotation ˋ$injectˋ et deviendra alors compatible avec la minification. ```javascript angular @@ -1660,9 +1660,9 @@ Bien que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'est ut Avengers.$inject = ['storageService', 'avengerService']; ``` - Note : Si ˋng-annotateˋ détecte que l'injection a déjà été faite (ex : ˋ@ngInjectˋ a été détécté), il ne dupliquera pas le code ˋ$injectˋ. + Note : Si ˋng-annotateˋ détecte que l'injection a déjà été faite (ex : ˋ@ngInjectˋ a été détecté), il ne dupliquera pas le code ˋ$injectˋ. - Note : Lors de l'utilisation d'un route resolver, vous pouvez préfixer la fonction de résolution avec `/* @ngInject */` et cela produira le code proprepement annoté, en gardant toute dépendance injectée sûre à la minification. + Note : Lors de l'utilisation d'un *route resolver*, vous pouvez préfixer la fonction de résolution avec `/* @ngInject */` et cela produira le code proprement annoté, en gardant toutes les dépendances injectées compatibles avec la minification. ```javascript // En utilisant les annotations @ngInject @@ -1681,17 +1681,17 @@ Bien que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'est ut } ``` - > Note : A partir d'Angular 1.3, utilisez le paramètre ˋngStrictDiˋ de la directive [`ngApp`](https://docs.angularjs.org/api/ng/directive/ngApp). Avec ce paramètre, l'injecteur sera créé en mode "strict-di" qui rendra fera échouer les invocations de fonctions de l'application qui n'utilisent pas explicitement les annotation de fonction (ceci peut ne pas être sûr à la minification). Débugger les informations qui seront logguées dans la console peut aider à débusquer le code à l'origine. + > Note : A partir d'Angular 1.3, utilisez le paramètre ˋngStrictDiˋ de la directive [`ngApp`](https://docs.angularjs.org/api/ng/directive/ngApp) pour détecter un potentiel oubli. Avec ce paramètre, l'injecteur sera créé en mode "strict-di" qui fera échouer les invocations de fonctions de l'application qui n'utiliseraient pas explicitement les annotations de fonctions (et qui rendraient l'application non-minifiable). Des infos de débogage seront alors logguées dans la console pour aider à retrouver code à l'origine de l'alerte. Je préfère utiliser `ng-strict-di` uniquement pour le débogage. `` -### Utilisation de Gulp ou Grunt pour ng-annotate +### Utilisation de Gulp ou Grunt pour `ng-annotate` ###### [Style [Y101](#style-y101)] - - Utilisez [gulp-ng-annotate](https://www.npmjs.org/package/gulp-ng-annotate) ou [grunt-ng-annotate](https://www.npmjs.org/package/grunt-ng-annotate) dans une tâche de build automatisée. Injectez `/* @ngInject */` avant toute fonction qui possède des dépendances. + - Utilisez [gulp-ng-annotate](https://www.npmjs.org/package/gulp-ng-annotate) ou [grunt-ng-annotate](https://www.npmjs.org/package/grunt-ng-annotate) dans une tâche de *build* automatisée. Injectez `/* @ngInject */` avant toute fonction qui a des dépendances. - *Pourquoi ?* : ng-annotate va intercepter la plupart des dépendances, mais parfois va nécessiter des indices grâce à l'utilisation de la syntaxe `/* @ngInject */ˋ. + *Pourquoi ?* : `ng-annotate` va intercepter la plupart des dépendances, mais parfois va nécessiter des indices grâce à l'utilisation de l'ajout de `/* @ngInject */ˋ. - Le code ci-dessous est un exemple d'une tâche gulp qui utilise ngAnnotate + Le code ci-dessous est un exemple d'une tâche gulp qui utilise `ngAnnotate` ```javascript gulp.task('js', ['jshint'], function() { From d728e01d9ee45c7bf5928641c546e68f39e9de30 Mon Sep 17 00:00:00 2001 From: Xavier Haniquaut Date: Tue, 18 Aug 2015 21:26:19 +0200 Subject: [PATCH 376/567] [fr-FR] Refresh french translation : Exception Handling --- i18n/fr-FR.md | 51 ++++++++++++++++++++++++++++++++------------------- 1 file changed, 32 insertions(+), 19 deletions(-) diff --git a/i18n/fr-FR.md b/i18n/fr-FR.md index 92738bf6..a36b6a8f 100644 --- a/i18n/fr-FR.md +++ b/i18n/fr-FR.md @@ -1719,14 +1719,14 @@ Bien que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'est ut ## Gestion des Exceptions -### decorateurs +### Décorateurs ###### [Style [Y110](#style-y110)] - - Utilisez un [decorateur](https://docs.angularjs.org/api/auto/service/$provide#decorator), au moment de la configuration en utilisant le service [`$provide`](https://docs.angularjs.org/api/auto/service/$provide), sur le service [`$exceptionHandler`](https://docs.angularjs.org/api/ng/service/$exceptionHandler) pour effecture des actions personnalisées lorsque des exceptions se produisent. + - Utilisez un [décorateur](https://docs.angularjs.org/api/auto/service/$provide#decorator), au moment de la configuration en utilisant le service [`$provide`](https://docs.angularjs.org/api/auto/service/$provide), sur le service [`$exceptionHandler`](https://docs.angularjs.org/api/ng/service/$exceptionHandler) pour effectuer des actions personnalisées lorsque des exceptions se produisent. - *Pourquoi ?* : Fournir un moyen cohérent pour gérer les exceptions non interceptées d'Angular pendant le développement ou à l'éxécution. + *Pourquoi ?* : Cela fournit un moyen cohérent pour gérer les exceptions non interceptées d'Angular pendant le développement ou à l’exécution. - Note : Une autre possibilité serait de surcharger le service au lieu d'utiliser un décorateur. C'est une bonne possibilité, mais si vou voulez garder le comportement par défaut et l'étendre, un décorateur est plus approprié. + Note : Une autre possibilité serait de surcharger le service au lieu d'utiliser un décorateur. C'est une bonne option, mais si vous voulez vous conformer au comportement standard et l'étendre, un décorateur est plus approprié. ```javascript /* recommandé */ @@ -1751,8 +1751,8 @@ Bien que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'est ut }; /** * On pourrait ajouter l'erreur à une collection d'un service, - * ajouter les erreurs au $rootScope, loguer les erreurs vers un serveur distant, - * ou loguer locallement. Ou rejetter directement. C'est entièrement votre choix. + * ajouter les erreurs au $rootScope, loguer les erreurs sur un serveur distant, + * ou les loguer localement. Ou alors les rejeter directement. C'est entièrement votre choix. * throw exception; */ toastr.error(exception.msg, errorData); @@ -1760,14 +1760,14 @@ Bien que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'est ut } ``` -### Catcher d'Exceptions +### Intercepteurs d'exceptions ###### [Style [Y111](#style-y111)] - - Créer une factory qui expose une interface pour attraper et gérer correctement les exceptions. + - Créez une *factory* qui expose une interface pour intercepter et gérer correctement les exceptions. - *Pourquoi ?* : Fournir un moyen cohérent pour gérer les exception qui peuvent être déclenchées dans votre code (par example, pendant un appel Ajax ou lors d'un échec d'une promesse). + *Pourquoi ?* : Cela fournit un moyen cohérent pour intercepter les exceptions qui peuvent être déclenchées dans votre code (par exemple, pendant une requête XHR ou lors d'un échec de *promise*). - Note : Le catcher d'axception est bon pour attraper et réagir à des exceptions spécifiques provenant d'appels dont vous savez qu'elles sont déclenchées. Par exemple, lorsque on fait un appel Ajax pour récuppérer des données d'un serveur distant et que vous voulez attraper n'importe quelles exceptions provenant de ce service uniquement et réagir seulement à celui-ci. + Note : Le intercepteur d'exceptions est bon pour intercepter et réagir à des exceptions spécifiques potentielles provenant d'appels qui pourraient en produire. Par exemple, lorsque on fait une requête XHR pour récupérer des données d'un service web distant et que vous voulez intercepter n'importe quelles exceptions provenant de ce service uniquement et réagir seulement à celles-ci. ```javascript /* recommandé */ @@ -1791,33 +1791,46 @@ Bien que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'est ut } ``` -### Erreurs de Routage +### Erreurs de routage ###### [Style [Y112](#style-y112)] - - Gérez et loguez toute erreur de routage en utilisant [`$routeChangeError`](https://docs.angularjs.org/api/ngRoute/service/$route#$routeChangeError). + - Gérez et loguez toutes les erreurs de routage en utilisant [`$routeChangeError`](https://docs.angularjs.org/api/ngRoute/service/$route#$routeChangeError). - *Pourquoi ?* : Fournir un moyen cohérent de gérer les erreurs de routage. + *Pourquoi ?* : Pour fournir un moyen cohérent de gestion des erreurs de routage. - *Pourquoi ?* : Fournir potentiellement une meilleure expérience utilisateur si une erreur de routage se produit et les rediriger vers un écran convivial avec plus de détails ou les possibilités de s'en sortir. + *Pourquoi ?* : Pour fournir potentiellement une meilleure expérience utilisateur si une erreur de routage se produit et rediriger vers un écran approprié avec plus de détails ou les possibilités pour s'en sortir. ```javascript /* recommandé */ + var handlingRouteChangeError = false; + function handleRoutingErrors() { /** - * Annulation du routage: - * Sur une erreur de routage, aller au dashboard. - * Fournir une clause de sortie s'il essaye de le faire deux fois. + * Annulation du routage : + * sur une erreur de routage, aller au dashboard. + * Fournit une clause de sortie s'il essaye de le faire deux fois. */ $rootScope.$on('$routeChangeError', function(event, current, previous, rejection) { - var destination = (current && (current.title || current.name || current.loadedTemplateUrl)) || + if (handlingRouteChangeError) { return; } + handlingRouteChangeError = true; + var destination = (current && (current.title || + current.name || current.loadedTemplateUrl)) || 'unknown target'; - var msg = 'Error routing to ' + destination + '. ' + (rejection.msg || ''); + var msg = 'Error routing to ' + destination + '. ' + + (rejection.msg || ''); + /** * Loguer éventuellement en utilisant un service personnalisé ou $log. * (N'oubliez pas d'injecter votre service personnalisé) */ logger.warning(msg, [current]); + + /** + * Lors d'une erreur de routage aller sur une autre route / état. + */ + $location.path('/'); + } ); } From 4a4f361ccc201449f774725e1e346ad9c8e076b4 Mon Sep 17 00:00:00 2001 From: Xavier Haniquaut Date: Tue, 18 Aug 2015 22:12:02 +0200 Subject: [PATCH 377/567] [fr-FR] Refresh french translation : Namming --- i18n/fr-FR.md | 86 +++++++++++++++++++++++++++++++++------------------ 1 file changed, 56 insertions(+), 30 deletions(-) diff --git a/i18n/fr-FR.md b/i18n/fr-FR.md index a36b6a8f..ae0c524f 100644 --- a/i18n/fr-FR.md +++ b/i18n/fr-FR.md @@ -1840,29 +1840,29 @@ Bien que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'est ut ## Nommage -### Règles de Nommage +### Conventions de nommage ###### [Style [Y120](#style-y120)] - - Utilisez des noms cohérents pour tous les composants en utilisant un pattern qui décrit la fonctionnalité de ce composant puis (éventuellement) son type. Le pattern que je recommande est `fonctionnalité.type.js`. Il y a 2 noms pour la plupart des resources: - * le nom du fichier (`avengers.controller.js`) - * le nom du composant déclaré à Angular (`AvengersController`) + - Utilisez des noms cohérents pour tous les composants en utilisant un motif qui décrit la fonctionnalité du composant puis (éventuellement) son type. Le motif que je recommande est `fonctionnalité.type.js`. Il y a deux noms pour la plupart des ressources : + * le nom du fichier (`avengers.controller.js`) + * le nom du composant déclaré à Angular (`AvengersController`) - *Pourquoi ?* : Les conventions de nommage donnent une façon cohérente de s'y retrouver en un clin d'oeil. La cohérence dans tout le projet est vitale. La cohérence au sein de l'équipe est importante. La cohérence dans l'entreprise apporte une efficacité redoutable. + *Pourquoi ?* : Les conventions de nommage permettent de de nommer de façon cohérente et de retrouver du contenu en un clin d'œil. La cohérence à toute l'échelle du projet est vitale. La cohérence au sein d'une équipe est importante. La cohérence dans une entreprise apporte une efficacité redoutable. - *Pourquoi ?* : Les conventions de nommage doivent simplement vous aider à naviguer dans le code plus vite et le rendre plus facile à comprendre. + *Pourquoi ?* : Les conventions de nommage doivent simplement vous aider à naviguer dans votre code plus vite et le rendre plus facile à comprendre. -### Nom des Fichiers de Fonctionnalités +### Nom des fichiers de fonctionnalités ###### [Style [Y121](#style-y121)] - - Utilisez des noms cohérents pour tous les composants qui suivent un pattern qui décrit la fonctionnalité d'un composant et (éventuellent) son type. Le pattern que je recommande est `fonctionnalité.type.js`. + - Utilisez des noms cohérents pour tous les composants qui suivent un motif qui décrit leur fonctionnalité et (éventuellement) leur type. Le motif que je recommande est `fonctionnalité.type.js`. *Pourquoi ?* : Offre une façon cohérente d'identifier rapidement les composants. - *Pourquoi ?* : Fournit un pattern matching pour automatiser des tâches. + *Pourquoi ?* : Permet de faire *matcher* par nom de fichier au sein d'un processus d'automatisation. ```javascript /** - * possibilités couramment rencontrées. + * Options courantes */ // Contrôleurs @@ -1907,7 +1907,7 @@ Bien que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'est ut avenger-profile.directive.spec.js ``` - Note : Une autre convention courante consiste à nommer les fichiers de contrôleurs sans le mot `controller` dans le nom de fichier comme `avengers.js`au lieu de `avengers.controller.js`. Toutes les autres conventions étant maintenues avec un suffixe par type. Les contrôleurs étant les les types de composant les plus courants, ça permet d'économiser la frappe au clavier tout en étant facilement identifiable. Je vous conseille de choisir une convention et de vous y tenir dans toute l'équipe. Ma préference est `avengers.controller.js`. + Note : Une autre convention courante consiste à nommer les fichiers des contrôleurs sans le mot `controller` dans le nom de fichier comme `avengers.js`au lieu de `avengers.controller.js`. Toutes les autres conventions tiennent à garder le suffixe du type. Le contrôleur étant le type de composant le plus courant, cela permet alors d'économiser à la frappe tout en restant facilement identifiable. Je vous conseille de choisir une convention et de vous y tenir dans toute l'équipe. Ma préference est `avengers.controller.js`. ```javascript /** @@ -1918,14 +1918,14 @@ Bien que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'est ut avengers.spec.js ``` -### Nommage des Fichiers de Test +### Nommage des fichiers de test ###### [Style [Y122](#style-y122)] - - Les spécifications du nommage des tests est similaire à celui du composant qu'il teste avec un suffixe `spec`. + - Le nommage des spécifications de test est similaire à celui des celui du composant qu'il teste avec le suffixe `spec`. *Pourquoi ?* : Fournit une façon cohérente d'identifier rapidement les composants. - *Pourquoi ?* : Permet le pattern matching pour [karma](http://karma-runner.github.io/) ou d'autres moteurs de tests. + *Pourquoi ?* : Permet de faire *matcher* par nom de fichier dans [karma](http://karma-runner.github.io/) ou d'autres moteurs de tests. ```javascript /** @@ -1940,11 +1940,11 @@ Bien que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'est ut ### Nommage des Contrôleurs ###### [Style [Y123](#style-y123)] - - Utilisez des noms cohérents pour tous les contrôleurs nommés d'après leur fonctionnalité. Utilisez le CamelCaseEnMajuscule, puisque ce sont des constructeurs. + - Utilisez des noms cohérents pour tous les contrôleurs nommés d'après leur fonctionnalité. Utilisez le UpperCamelCase pour les contrôleurs, car ce sont des constructeurs. *Pourquoi ?* : Fournit une façon cohérente d'identifier rapidement et de référencer les contrôleurs. - *Pourquoi ?* : Le CamelCaseEnMajuscules est la convention pour identifier les objets qui peuvent être instanciés avec un controleur. + *Pourquoi ?* : Le UpperCamelCase est la convention pour identifier les objets qui peuvent être instanciés avec un constructeur. ```javascript /** @@ -1959,12 +1959,12 @@ Bien que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'est ut function HeroAvengersController() { } ``` -### Suffixe des Noms de Contrôleurs +### Suffixe du nom des contrôleurs ###### [Style [Y124](#style-y124)] - Ajoutez au nom du contrôleur le suffixe ˋControllerˋ. - *Pourquoi ?* : Le suffixe ˋControllerˋ est utilisé souvent et il est plus explicitement descriptif. + *Pourquoi ?* : Le suffixe ˋControllerˋ est souvent utilisé et il est explicite. ```javascript /** @@ -1979,12 +1979,18 @@ Bien que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'est ut function AvengersController(){ } ``` -### Nommage des Factory +### Nommage des *factory* et des services ###### [Style [Y125](#style-y125)] - - Utilisez des noms cohérents pour toutes les foactories nommées d'après la fonctionnalitée. Utilisez le camel-case pour les services et les factories. + - Utilisez des noms cohérents pour toutes les *factories* et les services nommés d'après leur fonctionnalités. Utilisez le lowerCamelCase pour les services et les *factories*. Évitez de préfixer les *factories* et les services par `$`. N'ajoutez le suffixe `Service` à leurs noms uniquement si sa nature n'est pas claire (par exemple dans le cas des noms). - *Pourquoi ?* : Fournit une façon cohérente d'identifier rapidement et de référencer les factories. + *Pourquoi ?* : Fournit une façon cohérente d'identifier rapidement et de référencer les *factories* et les services. + + *Pourquoi ?* : Permet d'éviter les collisions avec les services et *factories* d'Angular qui ont déjà le préfixe `$`. + + *Pourquoi ?* : Les services aux noms explicites tels que `logger` n'ont pas besoin d'être préfixés. + + *Pourquoi ?* : Des alias tels que 'avengers' sont des noms et ont besoin d'un suffixe. Ce dernier doit être nommé `avengersService`. ```javascript /** @@ -1999,10 +2005,30 @@ Bien que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'est ut function logger(){ } ``` -### Nommage des Directives de Composants + ```javascript + /** + * recommended + */ + + // credit.service.js + angular + .module + .factory('creditService', creditService); + + function creditService() { } + + // credit.service.js + angular + .module + .service('customersService', customersService); + + function customersService() { } + ``` + +### Nommage des directives ###### [Style [Y126](#style-y126)] - - Utilisez des noms cohérents pour toutes les directives en utilisant le camel-case. Utilisez un préfixe court pour décrire le domaine à laquelle les directives appartiennent (exemples : préfixe de la société ou préfixe du projet). + - Utilisez des noms cohérents pour toutes les directives en utilisant le lowerCamelCase. Utilisez un préfixe court pour décrire le domaine auquel les directives appartiennent (par exemple le préfixe de la société ou du projet). *Pourquoi ?* : Fournit une façon cohérente d'identifier rapidement et de référencer les composants. @@ -2024,25 +2050,25 @@ Bien que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'est ut ### Modules ###### [Style [Y127](#style-y127)] - - Lorqu'il y a de multiples modules, le fichier du module principal est nommé ˋapp.module.jsˋ tandis que les autres modules dépendants sont nommés d'après ce qu'ils représentent. Par exemple, un module d'admin est nommé ˋadmin.module.jsˋ. Les noms des modules déclarés seraient respectivement ˋappˋ et ˋadminˋ. + - Lorqu'il y a de multiples modules, nommez le fichier du module principal ˋapp.module.jsˋ et nommez les autres modules qui en sont dépendants d'après ce qu'ils représentent. Par exemple, nommez un module d'administration ˋadmin.module.jsˋ. Les noms des modules déclarés seraient alors respectivement ˋappˋ et ˋadminˋ. - *Pourquoi ?* : Fournit de la cohérence pour les applications multi-modules, et pour les applications qui grossissent. + *Pourquoi ?* : Fournit de la cohérence pour les applications modulaires, et pour prévoir l'extension des applications. - *Pourquoi ?* : Fournit une façon aisée d'utiliser l'automatisation des tâches afin de charger toutes les définitions de modules en premier, puis ensuite tous les autres fichiers angular (pour l'assemblage). + *Pourquoi ?* : Fournit une façon aisée d'utiliser des processus d'automatisation des tâches afin de charger toutes les définitions de modules en premier, puis ensuite tous les autres fichiers Angular (pour l'assemblage). ### Configuration ###### [Style [Y128](#style-y128)] - - Séparer la configuration d'un module dans son propre fichier nommé d'après le module. Un fichier de configuration du module principal ˋappˋ est nommé ˋapp.config.jsˋ (ou simplement ˋconfig.jsˋ). Une configuration pour un module nommé ˋadmin.module.jsˋ est nommé ˋadmin.config.jsˋ. + - Séparez la configuration d'un module dans son propre fichier nommé d'après le module. Un fichier de configuration du module principal ˋappˋ est nommé ˋapp.config.jsˋ (ou simplement ˋconfig.jsˋ). Une configuration pour un module nommé ˋadmin.module.jsˋ est nommé ˋadmin.config.jsˋ. - *Pourquoi ?* : Sépare la configuration de la définition du module, du composant et du code actif. + *Pourquoi ?* : Sépare la configuration de la définition du module, des composants et du code actif. - *Pourquoi ?* : Fournit un endroit bien identifié pour mettre la configuration d'un module. + *Pourquoi ?* : Fournit un endroit bien identifié pour régler la configuration d'un module. ### Routes ###### [Style [Y129](#style-y129)] - - Séparez la configuration de la route dans son propre fichier. Un exemple pourrait être ˋapp.route.jsˋ pour le module principal et ˋadmin.route.jsˋ pour le module d'ˋadminˋ. Même pour de petites applications, il est préférable de privilégier cette séparation du reste de la configuration. + - Séparez la configuration du routage dans son propre fichier. Un exemple pourrait être ˋapp.route.jsˋ pour le module principal et ˋadmin.route.jsˋ pour le module d'administration. Même pour de petites applications, il est préférable de privilégier cette séparation du reste de la configuration. **[Retour en haut de page](#table-des-matières)** From 29444f05089c0453fcfef631a0d891adca7b6c4f Mon Sep 17 00:00:00 2001 From: Xavier Haniquaut Date: Tue, 18 Aug 2015 22:39:32 +0200 Subject: [PATCH 378/567] [fr-FR] Refresh french translation : LIFT --- i18n/fr-FR.md | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/i18n/fr-FR.md b/i18n/fr-FR.md index ae0c524f..c6dcc34b 100644 --- a/i18n/fr-FR.md +++ b/i18n/fr-FR.md @@ -2072,27 +2072,27 @@ Bien que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'est ut **[Retour en haut de page](#table-des-matières)** -## Le Principe LIFT de Structuration de l'Application +## Architecture L.I.F.T. ### LIFT ###### [Style [Y140](#style-y140)] - - Structurez votre application afin de pouvoir `L`ocaliser le code plus rapidement, `I`dentifier le code d'un seul coup, garder la structure la plus platte possible (`F`lattest), et essayez (`T`ry) de rester DRY (Don't Repeat Yourself). La structure doit suivre ces 4 règles de bases. + - Structurez votre application afin de pouvoir `L`ocaliser le code plus rapidement, `I`dentifier le code d'un seul coup, garder la structure la plus plate possible (`F`lattest), et essayez (`T`ry) de rester DRY (Don't Repeat Yourself). La structure doit suivre ces quatre règles de base. - *Pourquoi LIFT ?* : Fournit une structure cohérente qui passe bien à l'échelle, qui est modulaire, et facilite l'augmentation de l'efficacité du développeur. Une autre façon de valider la structure de votre application est de vous demander : à quelle vitesse vous pouvez ouvrir et travailler dans tous les fichiés liés à une fonctionnalité ? + *Pourquoi ?* : L.I.F.T. fournit une structure cohérente qui peut grossir facilement, qui est modulaire, et augmente facilement l'efficacité de développement. Une autre façon de valider la structure de votre application est de vous demander à quelle vitesse vous pouvez ouvrir et travailler dans tous les fichiers liés à une fonctionnalité. - Lorsque je trouve que ma structure n'est pas confortable, je reviens en arrière et je revisite les règles LIFT. + Lorsque je trouve que ma structure n'est pas confortable, je reviens en arrière et consulte à nouveau les règles L.I.F.T. - 1. `L`ocaliser le code est facile - 2. `I`dentifier le code d'un coup - 3. `F`lat (platte) structure autant que possible - 4. `T`ry (essayer) de rester DRY (Don’t Repeat Yourself, Ne Pas Se Répéter) ou T-DRY + 1. `L`ocaliser notre code est facile. + 2. `I`dentifier le code d'un coup. + 3. `F`lat structure (structure plate) autant que possible. + 4. `T`ry (Essayer) de ne pas se répéter (T-DRY). ### Localisation ###### [Style [Y141](#style-y141)] - Rendez la localisation du code intuitive, simple et rapide. - *Pourquoi ?* : Je trouve que c'est super important pour un projet. Si l'équipe ne peut pas trouver rapidement les fichiers sur lesquels elle doit travailler, ils ne vont pas être en mesure de travailler aussi efficacement que possible, et la structure devra changer. Vous ne connaissez peut-être pas le nom du fichier où la position des fichiers liés, alors les placer dans les endroits les plus intuitifs et proches les uns les autres permet de gagner un paquet de temps. Une structure de répertoire descriptive peut aider à ça. + *Pourquoi ?* : Je trouve que c'est super important pour un projet. Si l'équipe ne peut pas trouver rapidement les fichiers sur lesquels elle doit travailler, elle ne va pas être en mesure de travailler aussi efficacement que possible, et la structure doit changer. Vous ne connaissez peut-être pas le nom du fichier où la position des fichiers liés, alors les placer dans les endroits les plus intuitifs et proches les uns les autres permet de gagner beaucoup de temps. Une structure de répertoire descriptive peut aider. ``` /bower_components @@ -2115,23 +2115,23 @@ Bien que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'est ut ### Identification ###### [Style [Y142](#style-y142)] - - Lorsque vous regardez un fichier vous devriez instantanément savoir ce qu'il contient ce qu'il représente. + - Lorsque vous regardez un fichier vous devriez instantanément savoir ce qu'il contient et représente. - *Pourquoi ?* : Vous passez moins de temps à fouiller et vous perdre pour cherche le code, et devenez de plus en plus efficient. Si ça implique des noms de fichier plus long, alors d'accord. Soyez descriptif avec les noms de fichier et leur contenu ne doit contenir exactement qu'un seul composant. Éviter les fichier avec plusieurs contrôleurs, plusieurs services, ou un mélange. On pourrait admettre une exception à cette règle si j'ai un ensemble de fonctionnalités très petites qui sont toutes reliées entre elles, elles sont toujours facilement identifiables. + *Pourquoi ?* : Vous passez moins de temps à fouiller et vous perdre pour trouver du code, et devenez de plus en plus efficace. Si ça implique des noms de fichier plus long, alors d'accord. Soyez descriptif avec les noms des fichiers et leur contenu ne doit correspondre qu'à un seul composant. Évitez les fichiers avec plusieurs contrôleurs, plusieurs services, ou un mélange. On pourrait admettre une exception à cette règle si j'ai un ensemble de très petites fonctionnalités qui sont toutes reliées entre elles, elles sont toujours facilement identifiables. ### Plat ###### [Style [Y143](#style-y143)] - - Gardez une structure de répertoire à plat le plus longtemps possible. Lorsque vous avez 7 fichiers ou plus, commencez à penser à séparer. + - Gardez une structure de répertoire à plat le plus longtemps possible. Lorsque vous avez sept fichiers ou plus, commencez à penser à séparer. - *Pourquoi ?* : Personne ne souhaite rechercher dans 7 niveaux de répertoires pour trouver un fichier. Pensez aux menus des sites web… rien de plus profond que 2 niveaux ne devrait être sérieursement pris en considération. Dans une structure de répertoire, il n'y a pas de nombre d'or, mais lorsqu'un répertoire à entre 7 et 10 fichiers, il serait temps de créer des sous-répertoires. Basez cela sur votre niveau de confort. Utilisez une structure plus plate jusqu'à ce qu'il y ait un évident intérêt (pour respecter les autres principes LIFT) à créer un sous-répertoire. + *Pourquoi ?* : Personne ne souhaite rechercher dans sept niveaux de répertoires pour trouver un fichier. Pensez aux menus des sites web… Rien de plus profond que deux niveaux ne devrait être sérieusement pris en considération. Dans une structure de répertoire, il n'y a pas de nombre d'or, mais lorsqu'un répertoire à entre sept et dix fichiers, il serait temps de créer des sous-répertoires. Ajustez cela à votre de confort. Utilisez une structure plus plate jusqu'à ce qu'il y ait un intérêt évident (pour respecter les autres principes L.I.F.T.) à créer un sous-répertoire. -### T-DRY (Essayer de respecter DRY) +### T-DRY (Essayer de ne pas se répéter) ###### [Style [Y144](#style-y144)] - - Ne vous répétez pas (DRY), mais pas bêtement à tout prix ni en sacrifiant la lisibilité. + - Ne vous répétez pas (DRY), mais ne sacrifiez pas la lisibilité. - *Pourquoi ?* : Ne pas se répéter (DRY) est important, mais pas cricial si vous en êtesréduit à sacrifier les autres principes LIFT, c'est que qu'on peut appeller T-DRY (Essayer de ne pas se répéter). Je ne voudrai pas écrire session-view.html pour une vue, parce que, c'est évidemment une vue. Si ce n'est pas évident ou par convention, alors nommez-le. + *Pourquoi ?* : Ne pas se répéter (DRY) est important, mais pas critique si vous en êtes réduit à sacrifier les autres principes L.I.F.T, c'est ce qu'on sous-entend par T-DRY. Je ne veux pas écrire `session-view.html` pour une vue parce que c'est trivial. Si ce n'est pas évident ou si la convention le précise alors nommez-le. **[Retour en haut de page](#table-des-matières)** From 4eed1f671c447dfc8cb7e94b5b953135ef7f2180 Mon Sep 17 00:00:00 2001 From: Xavier Haniquaut Date: Tue, 18 Aug 2015 23:00:01 +0200 Subject: [PATCH 379/567] [fr-FR] Refresh french translation : Structure of the application --- i18n/fr-FR.md | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/i18n/fr-FR.md b/i18n/fr-FR.md index c6dcc34b..510b29fd 100644 --- a/i18n/fr-FR.md +++ b/i18n/fr-FR.md @@ -2135,34 +2135,34 @@ Bien que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'est ut **[Retour en haut de page](#table-des-matières)** -## Structure de l'Application +## Architecture de l'application -### Règles Générales +### Règles globales ###### [Style [Y150](#style-y150)] - - Vous devez avoir une vue court terme et une vision à long terme. En d'autres mots, commencez petit et garder en tête là où en est votre application. Tout le code de l'appli va dans un répertoire racine nommé `app`. Tout contenu fonctionnel doit être rangé dans son propre fichier. Chaque contrôleur, service, module, vue doit avoir son propre fichier. Tous les scripts provenant de fournisseurs extérieurs doivent être rangés dans un autre répertoire racine et non dans le répertoire `app`. Le code que l'on écrit pas soi-même ne doit pas se mélanger avec son appli (`bower_components`, `script`, `lib`). + - Vous devez avoir une vue court terme et une vision à long terme. En d'autres mots, commencez petit et gardez en tête là où veut aller votre application. Tout le code de l'application va dans un répertoire de départ nommé `app` à la racine du projet. Tout élément fonctionnel doit être rangé dans son propre et unique fichier. Chaque contrôleur, service, module, vue doit avoir son propre fichier. Tous les scripts externes doivent être rangés dans un autre répertoire à la racine du projet et non dans le répertoire `app`. Le code que l'on a pas écrit ne doit pas se mélanger avec le code de l'application (`bower_components`, `script`, `lib`). - Note : Vous trouverez plus de détails et les justifications derrière la structure sur [ce post original sur la structure des applications](http://www.johnpapa.net/angular-app-structuring-guidelines/). + Note : Vous trouverez plus de détails et de justifications concernant l'architecture sur [ce post original sur la structure des applications](http://www.johnpapa.net/angular-app-structuring-guidelines/). ### Layout ###### [Style [Y151](#style-y151)] - - Placez les composants qui définissent le layout principal de l'application dans un répertoire nommé `layout`. Il devrait inclure une vue noyau et le contrôleur devrait agir comme conteneur pour l'appli, la navigation, les menus, les zones de contenu, et les autres régions. + - Placez les composants qui définissent l'agencement visuel principal de l'application dans un répertoire nommé `layout`. Il devrait inclure une « vue-enveloppe » et le contrôleur devrait agir comme conteneur pour l'application, la navigation, les menus, les zones de contenu, et les autres régions. - *Pourquoi ?* : Organise tout le layout à un seul endroit réutilisé dans l'application. + *Pourquoi ?* : Cela organise tout l'agencement visuel à un seul endroit réutilisé dans toute l'application. -### Structure en Répertoires-par-Fonctionnalités +### Structure « répertoire-fonctionnalité » ###### [Style [Y152](#style-y152)] - - Créez des répertoires nommés d'après les fonctionnalités qu'elles représentent. Lorsqu'un répertoire grossit jusqu'à atteindre plus de 7 fichiers, commencez à penser la création d'un répertoire pour ceux-ci. Si votre seuil est différent, ajustez-le au besoin. + - Créez des répertoires nommés d'après les fonctionnalités qu'elles représentent. Lorsqu'un répertoire grossit jusqu'à atteindre plus de sept fichiers, commencez à penser la création d'un sous-répertoire pour ceux-ci. Si votre seuil est différent, ajustez au besoin. - *Pourquoi ?* : Un développeur peut localiser, identifier ce que représente chaque fichier en sune seule fois, la structure est aussi plate que possible, et il n'y a ni répétitions ni noms redondants. + *Pourquoi ?* : Un développeur peut localiser, identifier ce que représente chaque fichier en une seule fois, la structure est aussi plate que possible, et il n'y a ni répétitions ni redondance de nommage. - *Pourquoi ?* : Les règles LIFT sont toutes couvertes. + *Pourquoi ?* : Les règles L.I.F.T. sont toutes respectées. - *Pourquoi ?* : Aide à diminuer l'entropie de l'appli en organizant le contenu et en le maintenant aligné avec les principes LIFT. + *Pourquoi ?* : Aide à diminuer l'entropie de l'application en organisant le contenu et en le maintenant en accord avec les principes L.I.F.T. - *Pourquoi ?* : Lorsqu'il y a de nombreux fichiers (+ de 10) les repérer est plus facile avec une structure de répertoires cohérente et plus difficile dans une structure à plat. + *Pourquoi ?* : Lorsqu'il y a de nombreux fichiers (plus de dix), les repérer est plus facile avec une structure de répertoires cohérente que dans une structure à plat. ```javascript /** @@ -2203,15 +2203,15 @@ Bien que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'est ut session-detail.controller.js ``` - ![Structure d'une Appli Exemple](https://raw.githubusercontent.com/johnpapa/angular-styleguide/master/assets/modularity-2.png) + ![Image d'un exemple de structure d'application](https://raw.githubusercontent.com/johnpapa/angular-styleguide/master/assets/modularity-2.png) - Note : N'utilisez pas une structuration de répertoires-par-type. Cela requiert de se déplacer entre de multiples répertoires lorsqu'on travaille sur une fonctionnalité et cela devient rapidement difficile à manier lorsque l'application grossit à 5, 10 ou plus de 25 vues et contrôleurs (et autres), ce qui complique la localisation par rapport à des répertoires-par-fonctionnalité. + Note : N'utilisez pas une structuration « répertoire-type ». Cela requiert de se déplacer entre de multiples répertoires lors du travail sur une fonctionnalité et cela devient rapidement difficile à manier lorsque l'application passe de à cinq, dix ou plus de vingt-cinq vues et contrôleurs (et autres fonctionnalités), ce qui complique la localisation par rapport à une structure en « répertoire-fonctionnalité ». ```javascript /* * à éviter - * Trouver une alternative aux répertoires-par-type. - * Je vous conseille les "répertoires-par-fonctionnalité", à la place. + * Alternative aux « répertoires-type » : + * Je vous conseille les « répertoires-fonctionnalité » */ app/ From 1804ca058be10973cbff65746c97f312265f7be0 Mon Sep 17 00:00:00 2001 From: Xavier Haniquaut Date: Tue, 18 Aug 2015 23:24:39 +0200 Subject: [PATCH 380/567] [fr-FR] Refresh french translation : Modularity --- i18n/fr-FR.md | 43 ++++++++++++++++++++++--------------------- 1 file changed, 22 insertions(+), 21 deletions(-) diff --git a/i18n/fr-FR.md b/i18n/fr-FR.md index 510b29fd..4acc6a7d 100644 --- a/i18n/fr-FR.md +++ b/i18n/fr-FR.md @@ -2218,6 +2218,7 @@ Bien que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'est ut app.module.js app.config.js app.routes.js + directives.js controllers/ attendees.js session-detail.js @@ -2250,65 +2251,65 @@ Bien que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'est ut ## Modularité -### De Nombreux Petits Modules Auto-Suffisants +### Nombreux petits modules auto-suffisants ###### [Style [Y160](#style-y160)] - - Créez de petits modules qui encapsulent une responsabilité. + - Créez de petits modules qui encapsulent une seule responsabilité. - *Pourquoi ?* : Les Applications modulaires rendent faciles le branchement rapide puisqu'elles permettent aux équipes de développement de construire des sections verticales de l'application et de livrer incrémentalement. Cela signifie que nous pouvons brancher de nouvelles fonctionnalités à mesure que nous les développons. + *Pourquoi ?* : Les applications modulaires rendent facile la compossibilité rapide puisqu'elles permettent aux équipes de développement de construire verticalement des sections de l'application et de livrer incrémentalement. Cela signifie que nous pouvons brancher de nouvelles fonctionnalités au fur et à mesure de leur développement. -### Création d'un Module Applicatif +### Création d'un module applicatif ###### [Style [Y161](#style-y161)] - Créez un module racine pour l'application dont le rôle est d'assembler tous les modules et fonctionnalités de votre application. Nommez-le comme votre application. - *Pourquoi ?* : Angular encourage la modularité et la séparation des responsabilités. La création d'un module racine pour l'application dont le rôle est de lier ensemble les autres modules fournit un moyen très direct d'ajouter et de retirer des modules à votre application. + *Pourquoi ?* : Angular encourage la modularité et la séparation des responsabilités. La création d'un module racine pour l'application dont le rôle est de lier ensemble des autres modules fournit un moyen très direct d'ajouter et de retirer des modules à votre application. -### Garder le Module Applicatif Léger +### Garder le module applicatif léger ###### [Style [Y162](#style-y162)] - Ne placez dans le module applicatif que la logique d'assemblage de l'application. Laissez les fonctionnalités dans leurs propres modules. - *Pourquoi ?* : Ajouter des responsabilités supplémentaires à l'application racine pour récupérer des données, afficher des vues, ou toute autre logique non reliée à l'assemblage de l'application trouble le module applicatif rend plus difficile à réutiliser ou éteindre les ensembles de fonctionnalités. + *Pourquoi ?* : Ajouter des responsabilités supplémentaires à la racine de l'application pour récupérer des données, afficher des vues, ou toute autre logique non reliée à l'assemblage de l'application trouble le module applicatif et rend plus difficile à réutiliser ou éteindre les ensembles de fonctionnalités. *Pourquoi ?* : Le module applicatif devient une déclaration qui montre quels modules aident à constituer l'application. -### Les Macro Fonctionnalités en tant que Modules +### Les macro-fonctionnalités sont des modules ###### [Style [Y163](#style-y163)] - - Créez des modules qui représentent des macro fonctionnalités, comme le layout, les services ré-utilisables et partagés, les dashboards, et les fonctionnalités applicatives spécifiques (par exemple : clients, admin, ventes). + - Créez des modules qui représentent des macro-fonctionnalités, comme l'agencement graphique (*layout*), les services ré-utilisables et partagés, les dashboards, et les fonctionnalités applicatives spécifiques (par exemple : clients, admin, ventes). *Pourquoi ?* : Les modules auto-suffisants peuvent être ajoutés à l'application avec peu ou pas de friction. - *Pourquoi ?* : Les sprints ou itérations peuvent se focaliser sur les macro-fonctionnalités et les activer à la fin de l'itération. + *Pourquoi ?* : Les sprints ou itérations peuvent être focalisés sur les macro-fonctionnalités. Elles peuvent être activées à la fin de ceux-ci. - *Pourquoi ?* : Séparer les macros-fonctionnalités rend plus facile les tests des modules en isolation et la réutilisation du code. + *Pourquoi ?* : Séparer les macros-fonctionnalités en modules les rend plus facile à tester de façon isolée et à la réutilisation. ### Les Blocks Ré-Utilisables en tant que Modules ###### [Style [Y164](#style-y164)] - - Créez des modules qui représentent des blocs d'application ré-utilisables pour les services en commun tels que la gestion d'exceptions, les logs, les diagnostics, la sécurité et la gestion des données en locale. + - Créez des modules qui représentent des blocs ré-utilisables dans l'application pour les services en commun tels que la gestion des exceptions, les logs, les diagnostics, la sécurité et la gestion des données locale. - *Pourquoi ?* : Ces types de fonctinnalités sont requises dans de nombreuses application, donc en les gardant séparées dans leur propres modules elles peuvent être génériques par rapport aux applications et peuvent être ré-utilisées pour d'autres applications. + *Pourquoi ?* : Ces types de fonctionnalités sont requises dans de nombreuses application, donc en les gardant séparées dans leur propres modules elles peuvent être génériques et peuvent être ré-utilisées pour d'autres applications. -### Dependences Entre Modules +### Dépendances entre modules ###### [Style [Y165](#style-y165)] - Le module racine de l'application dépend des modules des fonctionnalités spécifiques et de certains modules partagés et ré-utilisables. - ![Modularity and Dependencies](https://raw.githubusercontent.com/johnpapa/angular-styleguide/master/assets/modularity-1.png) + ![Modularité et Dépendences](https://raw.githubusercontent.com/johnpapa/angular-styleguide/master/assets/modularity-1.png) - *Pourquoi?* : Le module principal de l'appli continent une déclaration rapidement identifible des fonctionnalités de l'application. + *Pourquoi?* : Le module principal de l'application continent manifeste des fonctionnalités de l'application. - *Pourquoi ?* : Chaque groupe de fonctionnalité contient une déclaration de ce dont il dépend, de ce fait il peut être tiré comme dépendance dans d'autres applications et continuer à fonctionner. + *Pourquoi ?* : Chaque groupe de fonctionnalités contient une déclaration de ce dont il dépend, de ce fait il peut être importé comme dépendance dans d'autres applications et continuer à fonctionner. - *Pourquoi ?* : Les fonctionalités propres à l'appli tels que les services de données partagées deviennent faciles à repérer et partager au sein d'un `app.core` (choisissez un nom de votre choix pour ce module. + *Pourquoi ?* : Les fonctionnalités propres à l'application telles que les services de données partagées deviennent faciles à repérer et partager au sein d'un `app.core` (choisissez un nom de votre choix pour ce module). - Note : C'est un stratégie pour la cohérence. Il y a ici beaucoup de bons choix. Choisisez-en une qui soit cohérente, suivez les règles des dépendances d'Angular, et la maintenance et la montée en charge sera facilitée. + Note : C'est un stratégie pour la cohérence. Il y a ici beaucoup de bons choix. Choisissez-en une qui soit cohérente, suivez les règles des dépendances d'Angular, et la maintenance et la montée en charge sera facilitée. - > Mes structures peuvent varier légèrement entre les projets mais elles suivent toutes ces règles pour la structure et la modularité. L'implémentation peut varier en fonction des fonctionnalités et de l'équipe. En d'autres termes, ne vous paralysez pas sur une structure exactement semblable mais soumettez votre structure aux critères de cohérence, maintenance, et efficacité. + > Mes structures peuvent varier légèrement entre les projets mais elles suivent toutes ces règles pour la structure et la modularité. L'implémentation peut varier en fonction des fonctionnalités et de l'équipe. En d'autres termes, ne vous paralysez pas sur une structure exactement semblable mais pensez votre structure en termes de cohérence, maintenabilité, et efficacité. - > Dans de petites applic, vous pouvez aussi mettre toutes vos dépendances partagées dans le module applicatif où les modules fonctionnels n'ont pas de dépendances directes. Cela pourra rendre la maintenance de cette petite application plus facile, mais rendez difficile la ré-utilisation de ces modules en dehors de cette application. + > Dans de petites applications, vous pouvez aussi mettre toutes vos dépendances partagées dans le module applicatif où les modules fonctionnels n'ont pas de dépendances directes. Cela pourra rendre la maintenance de petites applications plus facile, mais rend difficile la ré-utilisation de ces modules en dehors de celle-ci. **[Retour en haut de page](#table-des-matières)** From 945a81becbee8649ffa3df89ecea68d07a3ca64f Mon Sep 17 00:00:00 2001 From: Xavier Haniquaut Date: Tue, 18 Aug 2015 23:43:09 +0200 Subject: [PATCH 381/567] [fr-FR] Refresh french translation: Startup Logic --- i18n/fr-FR.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/i18n/fr-FR.md b/i18n/fr-FR.md index 4acc6a7d..48dfe602 100644 --- a/i18n/fr-FR.md +++ b/i18n/fr-FR.md @@ -2313,14 +2313,14 @@ Bien que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'est ut **[Retour en haut de page](#table-des-matières)** -## Logique de Démarrage +## Logique d'initialisation ### Configuration ###### [Style [Y170](#style-y170)] - - Injectez le code à l'intérieur d'une [configuration de module](https://docs.angularjs.org/guide/module#module-loading-dependencies) qui doit être configuré avant l'éxécution de l'appli angular. Parmis les candidats idéaux, on trouve les providers et les constantes. + - Injectez le code à l'intérieur d'une [configuration de module](https://docs.angularjs.org/guide/module#module-loading-dependencies) qui doit être configurée avant l’exécution de l'application Angular. Parmi les candidats idéaux, on trouve les *providers* et les constantes. - *Pourquoi ?* : Ça rend les choses plus faciles d'avoir le moins d'endroits possible pour placer la configuration. + *Pourquoi ?* : Cela rend les choses plus faciles d'avoir le moins d'endroits possibles pour la configuration. ```javascript angular @@ -2347,12 +2347,12 @@ Bien que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'est ut } ``` -### Blocs Run +### Blocs `run` ###### [Style [Y171](#style-y171)] - - Tout code qui nécessite de s'éxécuter lorsque l'application démarre devrait être déclaré dans une factory, exposé via une fonction, et injecté dans un [bloc run](https://docs.angularjs.org/guide/module#module-loading-dependencies). + - Tout code qui nécessite de s’exécuter lorsque l'application s'initialise devrait être déclaré dans une *factory*, exposé via une fonction, et injecté dans le [bloc run](https://docs.angularjs.org/guide/module#module-loading-dependencies). - *Pourquoi ?* : Le code écrit directement dans un bloc run peut être difficile à tester. Le placer dans une factory le rend plus facile à abstraire et mocker. + *Pourquoi ?* : Le code directement écrit dans un bloc `run` peut être difficile à tester. Le placer dans une *factory* le rend plus facile à abstraire et à *mocker*. ```javascript angular From 2ca250505eea09e19898d505fa918b1df211fb11 Mon Sep 17 00:00:00 2001 From: Xavier Haniquaut Date: Tue, 18 Aug 2015 23:47:09 +0200 Subject: [PATCH 382/567] [fr-FR] Refresh french translation : $ services --- i18n/fr-FR.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/i18n/fr-FR.md b/i18n/fr-FR.md index 48dfe602..d621faf0 100644 --- a/i18n/fr-FR.md +++ b/i18n/fr-FR.md @@ -2369,21 +2369,21 @@ Bien que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'est ut **[Retour en haut de page](#table-des-matières)** -## Les Services de Wrapper $ de Angular +## Les services `$` d'Angular -### $document et $window +### `$document` et `$window` ###### [Style [Y180](#style-y180)] - Utilisez [`$document`](https://docs.angularjs.org/api/ng/service/$document) et [`$window`](https://docs.angularjs.org/api/ng/service/$window) au lieu de `document` et `window`. - *Pourquoi ?* : Ces services sont wrappés par Angular et plus facilement testables qu'en utilisant document et window dans les tests. Ils vous aident à éviter d'avoir à mocker document et window vous-même. + *Pourquoi ?* : Ces services sont *wrappés* par Angular et plus facilement testables qu'en utilisant document et window dans les tests. Ils vous aident à éviter d'avoir à *mocker* `document` et `window` vous-même. ### $timeout et $interval ###### [Style [Y181](#style-y181)] - Utilisez [`$timeout`](https://docs.angularjs.org/api/ng/service/$timeout) et [`$interval`](https://docs.angularjs.org/api/ng/service/$interval) au lieu de `setTimeout` et `setInterval`. - *Pourquoi ?* : Ces services sont wrappés par Angular et plus facilement testables et gèrent le cycle de digest d'Angular conservant un data binding à jour. + *Pourquoi ?* : Ces services sont *wrappés* par Angular et plus facilement testables et gèrent le cycle de *digest* d'Angular conservant un *data-binding* synchronisé. **[Retour en haut de page](#table-des-matières)** From ee8344791e87bb7b4291b57a35483c5f8530fc03 Mon Sep 17 00:00:00 2001 From: Xavier Haniquaut Date: Wed, 19 Aug 2015 00:18:07 +0200 Subject: [PATCH 383/567] [fr-FR] Refresh french translation : Testing --- i18n/fr-FR.md | 110 +++++++++++++++++++++++++++++++++++--------------- 1 file changed, 77 insertions(+), 33 deletions(-) diff --git a/i18n/fr-FR.md b/i18n/fr-FR.md index d621faf0..14d29999 100644 --- a/i18n/fr-FR.md +++ b/i18n/fr-FR.md @@ -2387,15 +2387,15 @@ Bien que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'est ut **[Retour en haut de page](#table-des-matières)** -## Le Test -Les tests unitaires aident à maintenir un code propre, ainsi, j'ai inclu quelques unes de mes recommandations sur les fondamentaux du test unitaire avec des liens pour plus déinformation. +## Tests +Les tests unitaires aident à maintenir un code source propre, ainsi j'ai inclut quelques unes de mes recommandations sur les bases des tests unitaires avec des liens pour plus d'informations. -### Écriture des Tests avec les Stories +### Écrire les tests avec des scenarii ###### [Style [Y190](#style-y190)] - - Écrivez un ensemble de tests pour chaque story. Commencer avec un test vide et complétez-les à mesure que vous écrivez le code pour la story. + - Écrivez un ensemble de tests pour chaque scenario. Commencer avec un test vide et complétez-les à mesure que vous écrivez le code pour le scenario. - *Pourquoi ?* : Écrire les descriptions de tests aident à définir clairement ce que votre story devra faire, ne devra pas faire et comment mesurer l'avancement. + *Pourquoi ?* : Écrire les descriptions de tests aident à définir clairement ce que votre scenario devra faire, ne devra pas faire et comment mesurer la réussite. ```javascript it('should have Avengers controller', function() { @@ -2417,12 +2417,12 @@ Les tests unitaires aident à maintenir un code propre, ainsi, j'ai inclu quelqu // et ainsi de suite ``` -### Librairie de Test +### Librairie de test ###### [Style [Y191](#style-y191)] - Utilisez [Jasmine](http://jasmine.github.io/) or [Mocha](http://mochajs.org) pour les tests unitaires. - *Pourquoi ?* : Jasmine et Mocha sont toutes deux largement utilisées dans la communauté Angular. Toutes les deux stables, bien maintenues, et fournissant des fonctionnalités robustes de test. + *Pourquoi ?* : Jasmine et Mocha sont toutes deux largement utilisées dans la communauté Angular. Toutes les deux sont stables, bien maintenues, et fournissent des fonctionnalités de test robustes. Note : Lorsque vous utilisez Mocha, utilisez aussi une librairie d'assertion telle que [Chai](http://chaijs.com). Je prefère Mocha. @@ -2431,78 +2431,122 @@ Les tests unitaires aident à maintenir un code propre, ainsi, j'ai inclu quelqu - Utilisez [Karma](http://karma-runner.github.io) comme lanceur de test. - *Pourquoi ?* : Karma est facile à configurer pour lancer les tests une fois ou automatiquement lorsqu'un changement est fait dans le code. + *Pourquoi ?* : Karma est facile à configurer pour lancer les tests ponctuellement ou automatiquement lorsqu'un changement est fait dans le code. - *Pourquoi ?* : Karma s'intègre facilement dans votre processus d'Intégration Continue soit tout seul ou par Grunt ou Gulp. + *Pourquoi ?* : Karma s'intègre facilement dans votre processus d'intégration continue soit seul ou via Grunt ou Gulp. *Pourquoi ?* : Quelques EDI commencent à s'intégrer avec Karma, c'est le cas de [WebStorm](http://www.jetbrains.com/webstorm/) et [Visual Studio](http://visualstudiogallery.msdn.microsoft.com/02f47876-0e7a-4f6c-93f8-1af5d5189225). - *Pourquoi ?* : Karma fonctionne bien avec les leaders de l'automatisation de tâches tel que [Grunt](http://www.gruntjs.com) (avec [grunt-karma](https://github.com/karma-runner/grunt-karma)) ou [Gulp](http://www.gulpjs.com) (avec [gulp-karma](https://github.com/lazd/gulp-karma)). + *Pourquoi ?* : Karma fonctionne bien avec les principaux outils d'automatisation de tâches tel que [Grunt](http://www.gruntjs.com) (avec [grunt-karma](https://github.com/karma-runner/grunt-karma)) ou [Gulp](http://www.gulpjs.com). Si vous utilisez Gulp, utilisez [Karma](https://github.com/karma-runner/karma) directement plutôt que via un plugin, son API peut s'utiliser directement. -### Les Stubs et les Spy + ```javascript + /* recommended */ + + // Exemple de Gulp fonctionnant directement avec Karma + function startTests(singleRun, done) { + var child; + var excludeFiles = []; + var fork = require('child_process').fork; + var karma = require('karma').server; + var serverSpecs = config.serverIntegrationSpecs; + + if (args.startServers) { + log('Starting servers'); + var savedEnv = process.env; + savedEnv.NODE_ENV = 'dev'; + savedEnv.PORT = 8888; + child = fork(config.nodeServer); + } else { + if (serverSpecs && serverSpecs.length) { + excludeFiles = serverSpecs; + } + } + + karma.start({ + configFile: __dirname + '/karma.conf.js', + exclude: excludeFiles, + singleRun: !!singleRun + }, karmaCompleted); + + //////////////// + + function karmaCompleted(karmaResult) { + log('Karma completed'); + if (child) { + log('shutting down the child process'); + child.kill(); + } + if (karmaResult === 1) { + done('karma: tests failed with code ' + karmaResult); + } else { + done(); + } + } + } + ``` + +### `stub` et les `spy` ###### [Style [Y193](#style-y193)] - - Utilisez [Sinon](http://sinonjs.org/) pour les stubs et les spy. + - Utilisez [Sinon](http://sinonjs.org/) pour les `stub` et les `spy`. - *Pourquoi ?* : Sinon fonctionne bien avec Jasmine et Mocha et étend les fonctionnalités de stub et de spy qu'ils offrent. + *Pourquoi ?* : Sinon fonctionne bien avec Jasmine et Mocha et étend les fonctionnalités de `stub` et de `spy` qu'ils offrent. *Pourquoi ?* : Sinon rend plus facile l'alternance entre Jasmine et Mocha, si vous voulez essayer les deux. - *Pourquoi ?* : Sinon a des messages descriptifs quand les tests ne valident pas les assertions. - + *Pourquoi ?* : Sinon fournit des messages descriptifs quand les tests ne valident pas les assertions. -### Navigateur sans Interface Graphique +### Navigateur sans interface graphique ###### [Style [Y194](#style-y194)] - - Utilisez [PhantomJS](http://phantomjs.org/) pour éxécuter les tests sur un serveur. + - Utilisez [PhantomJS](http://phantomjs.org/) pour exécuter les tests sur un serveur. - *Pourquoi?* : PhantomJS est un navigateur sans interface graphique qui peut vous aider à éxécuter les tests sans avoir besoin d'un navigateur "visuel". Ainsi vous n'avez pas besoin d'installer Chrome, Safari, IE, ou d'autres navigateurs sur votre serveur. + *Pourquoi?* : PhantomJS est un navigateur sans interface graphique qui peut vous aider à exécuter les tests sans avoir besoin d'un navigateur "visuel". Ainsi vous n'avez pas besoin d'installer Chrome, Safari, IE, ou d'autres navigateurs sur votre serveur. - Note : Que cela ne vous dispense pas de tester sur tous les navigateurs dans votre environnement, d'après les clients que vous ciblez. + Note : Que cela ne vous dispense pas de tester sur tous les navigateurs dans votre environnement,en fonction des clients que vous ciblez. -### Analyse de Code +### Analyse du code ###### [Style [Y195](#style-y195)] - Exécutez JSHint sur vos tests. - *Pourquoi ?* : Les tests sont du code. JSHint peut vous aider à identifier les problèmes de qualité de code qui pourrait amener les tests à fonctionner de façon incorrecte. + *Pourquoi ?* : Les tests' c'est aussi du code. JSHint peut vous aider à identifier les problèmes de qualité de code qui pourrait amener les tests à fonctionner de façon incorrecte. -### Atténuation des Règles JSHint avec les Golbales sur les Tests +### Assouplissement des règles de JSHint avec les variables globales dans les tests ###### [Style [Y196](#style-y196)] - - Relaxez les règles sur votre code de test afin de permettre l'usage des globales telles que `describe` et `expect`. Relaxez les règles pour les expressions, de la même façon qu'avec Mocha. + - Assouplissez les règles sur votre code de test afin de permettre l'usage des variables globales courantes telles que `describe` et `expect`. Assouplissez les règles pour les expressions puisque Mocha les utilise. - *Pourquoi ?* : Vos tests sont du code et requièrent à ce titre la même attention avec les mêmes règles de qualité de code que votre code de production. Cependant, les variables globales utilisées par les frameworks de test, par exemple, peuvent être relaxées en les incluants dans les spécifications de test. + *Pourquoi ?* : Vos tests sont du code et requièrent à ce titre la même attention avec les mêmes règles de qualité de code que votre code de production. Cependant, les variables globales utilisées par les *frameworks* de test, par exemple, peuvent être négligées en les incluant dans les spécifications de test. ```javascript /* jshint -W117, -W030 */ ``` - Ou laors vous pouvez rajouter ça à votre fichier d'option JSHint. + Ou alors vous pouvez rajouter le snippet suivant à votre fichier d'options JSHint. ```javascript "jasmine": true, "mocha": true, ``` - - ![Outils de Test](https://raw.githubusercontent.com/johnpapa/angular-styleguide/master/assets/testing-tools.png) + ![Outils de test](https://raw.githubusercontent.com/johnpapa/angular-styleguide/master/assets/testing-tools.png) ### Organizing Tests ###### [Style [Y197](#style-y197)] - - Placez les fichiers des tests unitaires (specs) côte-à-côte du code client. Placez les specs qui couvrent l'intégration avec le serveur ou les celles qui testent plusieurs composants dans un répertoire `tests` séparé. + - Placez les fichiers des tests unitaires (specs) à parallèlement du code client. Placez les specs qui sont en charge de l'intégration avec le serveur ou les celles qui testent plusieurs composants dans un répertoire `tests` séparé. - *Pourquoi ?* : Les tests unitaires sont en corrélation directe avec un composant spécifique et un fichier dans le code source. + *Pourquoi ?* : Les tests unitaires sont en corrélation directe avec les composants et fichiers qu'ils testent dans le code source. - *Pourquoi ?* : Il est plus facile de les mettre à jour pluisqu'ils sont toujours les uns en face des autres. Quand vous développez, que vous fassiez du TDD, des tests en meme temps que l'implémentation ou des tests après l'implémentation, les specs sont côte-à-côte et jamais loin ni des yeux ni de l'esprit, et ainsi ils ont plus de chance d'etre maintenus ce qui permet aussi de tenir une bonne couverture de code. + *Pourquoi ?* : Il est plus facile de les mettre à jour puisqu'ils sont toujours visibles. Quand vous développez, que vous fassiez du TDD, des tests en même temps que l'implémentation ou des tests après l'implémentation, les spécifications ne sont jamais loin ni des yeux ni de l'esprit, et ainsi ils ont plus de chance d'être maintenus, ce qui permet aussi de tenir une bon *coverage*. *Pourquoi ?* : Quand vous mettez à jour le code source, il est plus facile de mettre à jour les tests en même temps. - *Pourquoi ?* : Les placer côte-à-côte les rend plus facile à trouver et facile à déplacer si vous déplacez les sources. + *Pourquoi ?* : Les placer en parallèle les rend plus facile à trouver et facile à déplacer si vous déplacez les sources. - *Pourquoi ?* : Avoir les specs proches permet au lecteur du code source d'apprendre comment le composant est supposé être utilisé et découvrir les limitations connues. + *Pourquoi ?* : Avoir les spécifications proches permet au lecteur d'apprendre comment le composant est supposé être utilisé et découvrir ses limitations connues. - *Pourquoi ?* : La séparation des specs afin qu'ils ne soient pas inclus dans le build est facile avec grunt ou gulp. + *Pourquoi ?* : Séparer les spécifications de test afin qu'ils ne soient pas inclus dans le *build* est facile avec grunt ou gulp. ``` /src/client/app/customers/customer-detail.controller.js From 3e65db42ab86da215660d6e3e670c798ec6f0d2f Mon Sep 17 00:00:00 2001 From: Xavier Haniquaut Date: Wed, 19 Aug 2015 00:25:54 +0200 Subject: [PATCH 384/567] [fr-FR] Refresh french translation : Animations --- i18n/fr-FR.md | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/i18n/fr-FR.md b/i18n/fr-FR.md index 14d29999..62417c36 100644 --- a/i18n/fr-FR.md +++ b/i18n/fr-FR.md @@ -2565,31 +2565,31 @@ Les tests unitaires aident à maintenir un code source propre, ainsi j'ai inclut ### Utilisation ###### [Style [Y210](#style-y210)] - - Utilisez de subtiles [animations avec Angular](https://docs.angularjs.org/guide/animations) pour la transition entre les états pour les vues et les éléments visuels premiers. Incluez le [module ngAnimate](https://docs.angularjs.org/api/ngAnimate). Les trois clés sont la subtilité, la fluidité, l'homogénéïté. + - Utilisez de subtiles [animations avec Angular](https://docs.angularjs.org/guide/animations) pour les transitions entre les états pour les vues et les éléments visuels de base. Incluez le [module ngAnimate](https://docs.angularjs.org/api/ngAnimate). Les trois clés sont la subtilité, la fluidité, l’homogénéité. - *Pourquoi ?* : Des animations subtiles peuvent améliorer l'Expérience Utilisateur lorsqu'elles sont utilisées de façon appropriéés. + *Pourquoi ?* : Des animations subtiles peuvent améliorer l'expérience utilisateur lorsqu'elles sont utilisées de façon appropriées. - *Pourquoi ?* : Des animations subtiles peuvent améliorer la performance perçue lorsque les vues changent. + *Pourquoi ?* : Des animations subtiles peuvent améliorer les performances perçues lorsque les vues changent. ### Moins d'une Seconde ###### [Style [Y211](#style-y211)] - - Utilisez de courtes durées pour les animations. Je commence en général par 300 milli secondes et j'ajuste jusqu'à ce que ce soit bien. + - Utilisez de courtes durées pour les animations. Je commence en général par 300ms et j'ajuste jusqu'à ce que le résultat soit celui attendu. - *Pourquoi ?* : Les animations longues peuvent avoir un effet inverse sur l'Expérience Utilisateur et la performance perçue en donnant l'apparence d'une application lente. + *Pourquoi ?* : Les animations longues peuvent avoir des effets inverses sur l'expérience utilisateur et les performances perçues en donnant l'impression d'une application lente. ### animate.css ###### [Style [Y212](#style-y212)] - - Utilisez [animate.css](http://daneden.github.io/animate.css/) pour les animations conventionnelles. + - Utilisez [animate.css](http://daneden.github.io/animate.css/) pour les animations classiques. - *Pourquoi ?* : Les animations que fournissent animate.css sont rapides, fluides et facile a ajouter à votre application. + *Pourquoi ?* : Les animations que fournit animate.css sont rapides, fluides et faciles à ajouter à votre application. - *Pourquoi ?* : Fournit de la cohérence dans vos animations. + *Pourquoi ?* : Fournit de la cohérence à vos animations. - *Pourquoi ?* : animate.css est largement utilisée et testée. + *Pourquoi ?* : animate.css est largement utilisée et testé. - Note : Voir ce [super post par Matias Niemelä sur les animations d'Angular](http://www.yearofmoo.com/2013/08/remastered-animation-in-angularjs-1-2.html) + Note : Lire ce [super post par Matias Niemelä sur les animations Angular](http://www.yearofmoo.com/2013/08/remastered-animation-in-angularjs-1-2.html) **[Retour en haut de page](#table-des-matières)** From e794f96828b5c9cc22db0f7356c40f45890e17a5 Mon Sep 17 00:00:00 2001 From: Xavier Haniquaut Date: Wed, 19 Aug 2015 00:31:00 +0200 Subject: [PATCH 385/567] [fr-FR] Refresh french translation : Comments --- i18n/fr-FR.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/i18n/fr-FR.md b/i18n/fr-FR.md index 62417c36..464b695c 100644 --- a/i18n/fr-FR.md +++ b/i18n/fr-FR.md @@ -2598,15 +2598,15 @@ Les tests unitaires aident à maintenir un code source propre, ainsi j'ai inclut ### jsDoc ###### [Style [Y220](#style-y220)] - - Si vous prévoyez de produire de la documentation de code, utilisez la syntaxe [`jsDoc`](http://usejsdoc.org/) pour documenter les noms de fonction, leur description, paramètres et valeurs de renvoi. Utilisez `@namespace` et `memberOf` pour s'adapter à la structure de votre appli. + - Si vous prévoyez de documenter votre code source, utilisez la syntaxe [`jsDoc`](http://usejsdoc.org/) pour documenter les noms des fonctions, leur descriptions, paramètres et valeurs de retour. Utilisez `@namespace` et `memberOf` pour s'adapter à l'architecture de votre application. - *Pourquoi ?* : Vous pouvez générer (et re-générer) la documentation à partir de votre code, au lieu de l'écrire de zéro. + *Pourquoi ?* : Vous pouvez générer (et re-générer) la documentation à partir de votre code, au lieu de l'écrire intégralement. - *Pourquoi ?* : Fournit de la cohérence en utilisant un outil industriel commun. + *Pourquoi ?* : Cela permet d'avoir de la cohérence grâce un outil industriel standard. ```javascript /** - * Factory de Logger + * Factory de logger * @namespace Factories */ (function() { @@ -2629,8 +2629,8 @@ Les tests unitaires aident à maintenir un code source propre, ainsi j'ai inclut /** * @name logError - * @desc Loggue les errors - * @param {String} msg Le message à logguer + * @desc Logue les erreurs + * @param {String} msg Le message à loguer * @returns {String} * @memberOf Factories.Logger */ From 961915f4226fbe05c0890b8a8b1722594563c896 Mon Sep 17 00:00:00 2001 From: Xavier Haniquaut Date: Wed, 19 Aug 2015 00:39:21 +0200 Subject: [PATCH 386/567] [fr-FR] Refresh french translation : JSHint --- i18n/fr-FR.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/i18n/fr-FR.md b/i18n/fr-FR.md index 464b695c..e3afa70e 100644 --- a/i18n/fr-FR.md +++ b/i18n/fr-FR.md @@ -2645,14 +2645,14 @@ Les tests unitaires aident à maintenir un code source propre, ainsi j'ai inclut **[Retour en haut de page](#table-des-matières)** -## JS Hint +## JSHint -### Utilisation d'un Fichier d'Options +### Utilisation d'un fichier d'options ###### [Style [Y230](#style-y230)] - - Utilisez JS Hint pour éplucher votre JavaScript et assurez-vous d'avoir personnalisé le fichier d'options JS Hint et incluez le dans le système de gestion de versions. Voir la [doc de JS Hint](http://www.jshint.com/docs/) pour les détails de chaque option. + - Utilisez JSHint pour analyser votre JavaScript et assurez-vous d'avoir personnalisé son fichier d'options et incluez le dans le système de versioning. Lire la [documentation de JSHint](http://www.jshint.com/docs/) pour avoir les détails de chaque option. - *Pourquoi ?* : Fournit une première alerte avant de committer son code dans le système de gestion de version. + *Pourquoi ?* : Cela fournit une première alerte avant de *committer* son code dans le système de versioning. *Pourquoi ?* : Fournit de la cohérence dans votre équipe. From 4f236ffaacdc951dc82033da15a39f0c7f9b5960 Mon Sep 17 00:00:00 2001 From: Xavier Haniquaut Date: Wed, 19 Aug 2015 00:42:02 +0200 Subject: [PATCH 387/567] [fr-FR] Refresh french translation : JSCS --- i18n/fr-FR.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/i18n/fr-FR.md b/i18n/fr-FR.md index e3afa70e..c5e4c38b 100644 --- a/i18n/fr-FR.md +++ b/i18n/fr-FR.md @@ -2724,11 +2724,12 @@ Les tests unitaires aident à maintenir un code source propre, ainsi j'ai inclut ## JSCS -### Use an Options File +### Utiliser un fichier de configuration ###### [Style [Y235](#style-y235)] - - Utilisez JSCS pour valider votre style de code pour votre JavaScript et pensez à personnaliser vos options pour JSCS et de l'inclure dans votre gestionnaire de versionning. Vous pouvez consulter la [documentation de JSCS](http://www.jscs.info) pour voir les détails et les options. - *Pourquoi ?* : Fournit une premiere alerte avant de commiter sur votre gestionnaire de versionning. + - Utilisez JSCS pour valider vos styles de code pour votre JavaScript et pensez à personnaliser vos options pour JSCS et de l'inclure dans votre gestionnaire de versioning. Vous pouvez consulter la [documentation de JSCS](http://www.jscs.info) pour voir les détails et les options. + + *Pourquoi ?* : Fournit une première alerte avant de *commiter* sur votre gestionnaire de versioning. *Pourquoi ?* : Permet d'assurer une cohérence au sein de votre équipe. From 1d17591f3218cd8e82a75fef2ab63e1c3314c845 Mon Sep 17 00:00:00 2001 From: Xavier Haniquaut Date: Wed, 19 Aug 2015 00:49:35 +0200 Subject: [PATCH 388/567] [fr-FR] Refresh french translation : Constants --- i18n/fr-FR.md | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/i18n/fr-FR.md b/i18n/fr-FR.md index c5e4c38b..f68a501f 100644 --- a/i18n/fr-FR.md +++ b/i18n/fr-FR.md @@ -2789,9 +2789,12 @@ Les tests unitaires aident à maintenir un code source propre, ainsi j'ai inclut "disallowSpacesInsideArrayBrackets": "all", "disallowSpacesInsideParentheses": true, - "validateJSDoc": { + "jsDoc": { + "checkAnnotations": true, "checkParamNames": true, - "requireParamTypes": true + "requireParamTypes": true, + "checkReturnTypes": true, + "checkTypes": true }, "disallowMultipleLineBreaks": true, @@ -2799,7 +2802,6 @@ Les tests unitaires aident à maintenir un code source propre, ainsi j'ai inclut "disallowCommaBeforeLineBreak": null, "disallowDanglingUnderscores": null, "disallowEmptyBlocks": null, - "disallowMultipleLineStrings": null, "disallowTrailingComma": null, "requireCommaBeforeLineBreak": null, "requireDotNotation": null, @@ -2815,9 +2817,9 @@ Les tests unitaires aident à maintenir un code source propre, ainsi j'ai inclut ### Globales des Librairies Externes ###### [Style [Y240](#style-y240)] - - Créez une Constante Angular pour les variables gobales des librairies externes. + - Créez une constante Angular pour les variables globales des librairies externes. - *Pourquoi ?* : Fournit un moyen d'injecter des librairies tierces qui seraient sinon des globales. Cela améliore la testabilité du code en vous permettant de savoir plus facilement quelles sont les dépendances de vos composants évite les abstractions qui fuient). Ça vous permet aussi de mocker ces dépendances, là où cela fait sens. + *Pourquoi ?* : Fournit un moyen d'injecter des librairies tierces qui seraient sinon des globales. Cela améliore la testabilité du code en vous permettant de savoir plus facilement quelles sont les dépendances de vos composants (et évite de faire des abstractions qui fuient). Ça vous permet aussi de *mocker* ces dépendances, là où cela fait sens. ```javascript // constants.js @@ -2835,13 +2837,13 @@ Les tests unitaires aident à maintenir un code source propre, ainsi j'ai inclut ###### [Style [Y241](#style-y241)] - - Utilisez les constantes pour les valeurs qui ne changent pas et ne viennent pas d'un autre service. Quand des contantes ne sont utilisées que par un module qui peut être ré-utilisé dans d'autres applications, placez les constantes dans un seul fichier par module nommé comme le module. Tant que c'est possible, gardez les constantes dans le module principal dans un fichier `constants.js`. + - Utilisez des constantes pour les valeurs qui ne changent pas et ne viennent pas d'un autre service. Quand des contentes ne sont pas utilisées que par un module qui peut être ré-utilisé dans d'autres applications, placez les constantes dans un seul fichier par module nommé comme le module. Tant que c'est possible, gardez les constantes dans le module principal dans un fichier `constants.js`. - *Pourquoi ?* : Une valeur qui peut changer, même rarement, devrait être récupérée d'un service afin de ne pas avoir à changer le code source. Par exemple, une URL pour un service de données pourrait être définit comme constante mais il serait mieux de lire cette valeur par appel à un web service. + *Pourquoi ?* : Une valeur qui peut changer, même rarement, devrait être récupérée d'un service afin de ne pas avoir à changer le code source. Par exemple, une URL pour un service de données pourrait être définie comme constante mais il serait mieux de lire cette valeur par appel à un web service. - *Pourquoi ?* : Les constantes peuvent être injectées dans un composant angular, y compris les providers. + *Pourquoi ?* : Les constantes peuvent être injectées dans un composant Angular, y compris les *providers*. - *Pourquoi ?* : Quand une application est divisée en modules qui peuvent être ré-utilisés dans d'autres applications, chacun de ces modules individiuel devrait pouvoir fonctioner tout seul, y compris avec les constantes dépendantes. + *Pourquoi ?* : Quand une application est divisée en modules qui peuvent être ré-utilisés dans d'autres applications, chacun de ces modules individuels devrait pouvoir fonctionner tout seul, y compris avec les constantes dépendantes. ```javascript // Constantes utilisées par toute l'appli From 5b696ad683fa04c7bdb2a3b0af1056c3c4d155ea Mon Sep 17 00:00:00 2001 From: Wolverine Date: Wed, 19 Aug 2015 10:35:12 +0800 Subject: [PATCH 389/567] Update zh-CN.md Use an absolute URL. --- i18n/zh-CN.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/i18n/zh-CN.md b/i18n/zh-CN.md index 241855c3..57da4898 100644 --- a/i18n/zh-CN.md +++ b/i18n/zh-CN.md @@ -2819,7 +2819,7 @@ Angular社区是一个热衷于分享经验的令人难以置信的社区,尽 - 你可以把它们导入到WebStorm设置中: - - 下载[WebStorm Angular file templates and snippets](assets/webstorm-angular-file-template.settings.jar?raw=true) + - 下载[WebStorm Angular file templates and snippets](https://github.com/johnpapa/angular-styleguide/blob/master/assets/webstorm-angular-file-template.settings.jar?raw=true) - 打开WebStorm点击`File`菜单 - 选择`Import Settings`菜单选项 - 选择文件点击`OK` From 41ca7aed99cc03011c40bfadab249eddf3fcc34d Mon Sep 17 00:00:00 2001 From: Xavier Haniquaut Date: Wed, 19 Aug 2015 09:37:14 +0200 Subject: [PATCH 390/567] [fr-FR] Refresh french translation : Templates / Snippets --- i18n/fr-FR.md | 106 +++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 91 insertions(+), 15 deletions(-) diff --git a/i18n/fr-FR.md b/i18n/fr-FR.md index f68a501f..dfd90db9 100644 --- a/i18n/fr-FR.md +++ b/i18n/fr-FR.md @@ -2862,44 +2862,46 @@ Les tests unitaires aident à maintenir un code source propre, ainsi j'ai inclut **[Retour en haut de page](#table-des-matières)** -## Templates de Fichiers et Fragments -Utilisez des templates de fichier ou des fragments pour vous aider à suivre des styles et des patterns cohérents. Voici des templates et/ou fragments pour quelques uns des éditeurs de texte pour le développement web et EDIs. +## Modèles de fichiers et *snippets* +Utilisez des *templates* de fichiers ou des *snippets* pour vous aider à suivre des styles et des *patterns* cohérents. Voici des *templates* et/ou *snippets* pour quelques uns des éditeurs de texte pour le développement web et EDIs. ### Sublime Text ###### [Style [Y250](#style-y250)] - - Fragments Angular qui suivent ces styles et règles. + - *Snippets* Angular conformes avec ces styles et règles. - - Téléchargez les [Fragments Angular pour Sublime](assets/sublime-angular-snippets.zip?raw=true) - - Placez-les dans votre répertoire Package + - Téléchargez les [Snippets Angular pour Sublime](assets/sublime-angular-snippets.zip?raw=true) + - Placez-les dans votre répertoire `Package` - Redémarrez Sublime - Dans un fichier de type JavaScript, tapez ces commandes suivies par la touche `TAB` ```javascript - ngcontroller // crée un contrôleur Angular - ngdirective // crée une directive Angular - ngfactory // crée une factory Angular - ngmodule // crée un module Angular + ngcontroller // creates an Angular controller + ngdirective // creates an Angular directive + ngfactory // creates an Angular factory + ngmodule // creates an Angular module + ngservice // creates an Angular service + ngfilter // creates an Angular filter ``` ### Visual Studio ###### [Style [Y251](#style-y251)] - - Les templates de fichier qui suivent ces styles et règles peuvent être trouvées sur [SideWaffle](http://www.sidewaffle.com) + - Les *templates* de fichiers qui suivent ces styles et règles peuvent être trouvées sur [SideWaffle](http://www.sidewaffle.com) - Téléchargez l'extension [SideWaffle](http://www.sidewaffle.com) pour Visual Studio (fichier vsix) - - Éxécutez le fichier vsix + - Exécutez le fichier vsix - Re-démarrez Visual Studio ### WebStorm ###### [Style [Y252](#style-y252)] - - Les fragments Angular et templates de fichiers qui suivent le style et les règles. Vous pouvez les importer dans les paramètres de WebStorm : + - Vous pouvez importer dans les paramètres de WebStormLes les *templates* de fichiers et les *snippets* Angular qui suivent ces styles et ces règles : - - Téléchargez les [templates de fichier et fragments WebStorm pour Angular](assets/webstorm-angular-file-template.settings.jar?raw=true) + - Téléchargez les [*templates* de fichiers et *snippets* WebStorm pour Angular](assets/webstorm-angular-file-template.settings.jar?raw=true) - Ouvrez WebStorm et allez dans le menu `File` - Choisissez le menu `Import Settings` - - Sélectionnez le fichier et clickez sur `OK` + - Sélectionnez le fichier et cliquez sur `OK` - Dans un fichier de type JavaScript, tapez ces commandes suivies de la touche `TAB` : ```javascript @@ -2908,7 +2910,81 @@ Utilisez des templates de fichier ou des fragments pour vous aider à suivre des ng-m // crée un module Angular ``` - **[Retour en haut de page](#table-des-matières)** +### Atom +###### [Style [Y253](#style-y253)] + + - *Snippets* Angular qui suivent ces styles et ces règles. + ``` + apm install angularjs-styleguide-snippets + ``` + or + - Ouvrez Atom puis son *package manager* (Packages -> Settings View -> Install Packages/Themes) + - Cherchez le *package* 'angularjs-styleguide-snippets' + - Cliquez sur 'Install' pour installer le *package* + + - Dans un fichier JavaScript tapez ces commandes suivies de `TAB` : + + ```javascript + ngcontroller // Crée un contrôleur Angular + ngdirective // Crée une directive Angular + ngfactory // Crée une factory Angular + ngmodule // Crée un module Angular + ngservice // Crée un service Angular + ngfilter // Crée un filter Angular + ``` + +### Brackets +###### [Style [Y254](#style-y254)] + + - *Snippets* Angular qui suivent ces styles et ces règles. + - Téléchargez les [*snippets* Angular pour Brackets](assets/brackets-angular-snippets.yaml?raw=true). + - Brackets Extension manager ( File > Extension manager ) + - Installez ['Brackets Snippets (by edc)'](https://github.com/chuyik/brackets-snippets). + - Cliquez sur l'ampoule dans la marge droite de Brackets. + - Cliquez sur `Settings` puis sur `Import` + - Choisissez le fichier et sélectionnez `skip`ou `override`. + - Cliquez sur `Start Import` + + - Dans un fichier JavaScript tapez ces commandes suivies de `TAB` : + + ```javascript + // Snippets de fichiers complets avec IIFE + ngcontroller // Crée un controller Angular + ngdirective // Crée une directive Angular + ngfactory // Crée une factory Angular + ngapp // Crée un module Angular + ngservice // Crée un service Angular + ngfilter // Crée un filter Angular + + // Snippets à chaîner + ngmodule // Crée an Angular module getter + ngstate // Crée an Angular UI Router state définition + ngconfig // Définit une fonction de configuration + ngrun // Définit une fonction run + ngroute // Définit une clause `when` pour ngRoute + ngtranslate // Utilise le service `$translate` avec sa promise + ``` + +### vim +###### [Style [Y255](#style-y255)] + + - *Snippets* pour vim qui suivent ces styles et ces règles. + + - Téléchargez les [*snippets* vim pour Angular](assets/vim-angular-snippets?raw=true) + - Réglez [neosnippet.vim](https://github.com/Shougo/neosnippet.vim) + - Copiez les *snippets* dans le répertoire approprié. + + ```javascript + ngcontroller // Crée un contrôleur Angular + ngdirective // Crée une directive Angular + ngfactory // Crée une factory Angular + ngmodule // Crée un module Angular + ngservice // Crée un service Angular + ngfilter // Crée un filter Angular + ``` + + +**[Retour en haut de page](#table-des-matières)** ## Generateur Yeoman ###### [Style [Y260](#style-y260)] From e9678ebe09c7a74da7fdde06a0c25702c0c99352 Mon Sep 17 00:00:00 2001 From: Xavier Haniquaut Date: Wed, 19 Aug 2015 09:40:47 +0200 Subject: [PATCH 391/567] [fr-FR] Refresh french translation : Yeoman --- i18n/fr-FR.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/i18n/fr-FR.md b/i18n/fr-FR.md index dfd90db9..dd76b545 100644 --- a/i18n/fr-FR.md +++ b/i18n/fr-FR.md @@ -2986,12 +2986,12 @@ Utilisez des *templates* de fichiers ou des *snippets* pour vous aider à suivre **[Retour en haut de page](#table-des-matières)** -## Generateur Yeoman +## Générateur Yeoman ###### [Style [Y260](#style-y260)] -Vous pouvez utiliser le [générateur yeoman HotTowel](http://jpapa.me/yohottowel) pour créer une appli pour démarrer avec Angular en suivant ce guide de style. +Vous pouvez utiliser le [générateur Yeoman HotTowel](http://jpapa.me/yohottowel) pour créer une application Angular qui servira de point de départ et qui suis cette charte stylistique. -1. Installer generator-hottowel +1. Installer `generator-hottowel` ``` npm install -g generator-hottowel @@ -3004,7 +3004,7 @@ Vous pouvez utiliser le [générateur yeoman HotTowel](http://jpapa.me/yohottowe cd myapp ``` -3. Éxécuter le générateur +3. Exécuter le générateur ``` yo hottowel helloWorld From 5044245aefc65070d1b4675cbf8ad787240a7a2b Mon Sep 17 00:00:00 2001 From: Xavier Haniquaut Date: Wed, 19 Aug 2015 09:51:59 +0200 Subject: [PATCH 392/567] [fr-FR] Refresh french translation : Routing --- i18n/fr-FR.md | 84 ++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 77 insertions(+), 7 deletions(-) diff --git a/i18n/fr-FR.md b/i18n/fr-FR.md index dd76b545..c81c7f1f 100644 --- a/i18n/fr-FR.md +++ b/i18n/fr-FR.md @@ -3013,25 +3013,95 @@ Vous pouvez utiliser le [générateur Yeoman HotTowel](http://jpapa.me/yohottowe **[Retour en haut de page](#table-des-matières)** ## Routage -Le routage côté client est important pour créer un flux de navigation entre les vues et la composition des vues constituées de nombreux plus petits templates et directives. +Le routage côté client est important pour créer un flux de navigation entre les vues et composer des vues constituées de nombreux *templates* et directives de plus petites tailles. ###### [Style [Y270](#style-y270)] - - Utilisez [Routeur AngularUI](http://angular-ui.github.io/ui-router/) pour faire le routage côté client. + - Utilisez le [routeur d'AngularUI](http://angular-ui.github.io/ui-router/) pour faire le routage côté client. - *Pourquoi ?* : UI Router offre toutes les fonctionnalités du routeur Angular plus quelques autres parmis lesquels les routes imbriquées et les états. + *Pourquoi ?* : `ui-router` offre toutes les fonctionnalités du routeur d'Angular et en ajoute quelques unes parmi lesquelles les routes imbriquées et les états. - *Pourquoi ?* : La syntaxe est quasiement similaire au routeur Angular et il est facile de migrer à UI Router. + *Pourquoi ?* : La syntaxe est similaire à celle du routeur Angular par défaut et il est facile de migrer vers `ui-router`. + + - Note: Vous pouvez utiliser un *provider* tel que `routerHelperProvider` montré ci-dessous pour vous aidez à configurer les états à travers les fichiers pendant la phase de `run`. + + ```javascript + // customers.routes.js + angular + .module('app.customers') + .run(appRun); + + /* @ngInject */ + function appRun(routerHelper) { + routerHelper.configureStates(getStates()); + } + + function getStates() { + return [ + { + state: 'customer', + config: { + abstract: true, + template: '', + url: '/customer' + } + } + ]; + } + ``` + + ```javascript + // routerHelperProvider.js + angular + .module('blocks.router') + .provider('routerHelper', routerHelperProvider); + + routerHelperProvider.$inject = ['$locationProvider', '$stateProvider', '$urlRouterProvider']; + /* @ngInject */ + function routerHelperProvider($locationProvider, $stateProvider, $urlRouterProvider) { + /* jshint validthis:true */ + this.$get = RouterHelper; + + $locationProvider.html5Mode(true); + + RouterHelper.$inject = ['$state']; + /* @ngInject */ + function RouterHelper($state) { + var hasOtherwise = false; + + var service = { + configureStates: configureStates, + getStates: getStates + }; + + return service; + + /////////////// + + function configureStates(states, otherwisePath) { + states.forEach(function(state) { + $stateProvider.state(state.state, state.config); + }); + if (otherwisePath && !hasOtherwise) { + hasOtherwise = true; + $urlRouterProvider.otherwise(otherwisePath); + } + } + + function getStates() { return $state.get(); } + } + } + ``` ###### [Style [Y271](#style-y271)] - Définissez les routes pour les vues d'un module à l'endroit où elles existent. Chaque module devrait contenir le routage de ses vues. - *Pourquoi ?* : Chaque module devrait avoir la cohérence de définir ses propres routes. + *Pourquoi ?* : Chaque module devrait être indépendant. - *Pourquoi ?* : Si on ajoute ou enlève un module, on souhaite que l'appli ne contienne que les routes vers des vues existantes. + *Pourquoi ?* : Si on ajoute ou enlève un module, on souhaite que l'application ne contienne que des routes qui aboutissent sur des vues existantes. - *Pourquoi ?* : Cela rend facile l'activation ou la désactivation de portions de l'application sans se préoccuper des routes orphelines. + *Pourquoi ?* : Cela rend facile l'activation ou la désactivation de portions de l'application sans se préoccuper d'avoir des routes orphelines. **[Retour en haut de page](#table-des-matières)** From 573476758972454d05bb600549e459d350ba6372 Mon Sep 17 00:00:00 2001 From: Xavier Haniquaut Date: Wed, 19 Aug 2015 09:57:40 +0200 Subject: [PATCH 393/567] [fr-FR] Refresh french translation : Task Automation --- i18n/fr-FR.md | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/i18n/fr-FR.md b/i18n/fr-FR.md index c81c7f1f..eaa4415f 100644 --- a/i18n/fr-FR.md +++ b/i18n/fr-FR.md @@ -3106,18 +3106,17 @@ Le routage côté client est important pour créer un flux de navigation entre l **[Retour en haut de page](#table-des-matières)** ## Automatisation des Tâches -Utilisez [Gulp](http://gulpjs.com) ou [Grunt](http://gruntjs.com) pour créer des tâches automatisées. Gulp favorise le code plutôt que la configuration tandis que Grunt tend vers la configuration plutôt que le code. Je préfère personnellement Gulp car il me semble plus facile à lire et écrire, mais les deux sont excellents. +Utilisez [Gulp](http://gulpjs.com) ou [Grunt](http://gruntjs.com) pour créer des tâches automatisées. Gulp favorise le code plutôt que la configuration tandis que Grunt tend vers la configuration plutôt que le code. À titre personnel je préfère Gulp car il me semble plus facile à lire et écrire, mais les deux sont excellents. -> Learn more about gulp and patterns for task automation in my [Gulp Pluralsight course(http://jpapa.me/gulpps) -> Vous pouvez en lire plus sur Gulp et ses patterns pour l'automatisation des taches dans mon cours sur [Pluralsight](http://jpapa.me/gulpps). +> Apprenez-en plus sur Gulp et les *patterns* pour l'automatisation en allant voir [mon cours sur Pluralsight](http://jpapa.me/gulpps) ###### [Style [Y400](#style-y400)] - Utilisez l'automatisation des tâches pour lister les fichiers de définition de module `*.module.js` avant tout autre fichier JavaScript de l'application. - *Pourquoi ?* : Angular a besoin que la définition des modules soit déclarée avant qu'ils puissent être utilisés. + *Pourquoi ?* : Angular a besoin que la définition des modules soit faire avant qu'ils puissent être utilisés. - *Pourquoi ?* : Nommer les modules avec un pattern spécifique tel que `*.module.js` les rends faciles à aller chercher avec une expression englobante et à les lister en premier. + *Pourquoi ?* : Nommer les modules avec un pattern spécifique tel que `*.module.js` les rends faciles à aller chercher avec une expression régulière et à les lister. ```javascript var clientApp = './src/client/app/'; From 8ddddb300d2b7b409d70c2c66c18f6cb81e5f482 Mon Sep 17 00:00:00 2001 From: Xavier Haniquaut Date: Wed, 19 Aug 2015 10:01:24 +0200 Subject: [PATCH 394/567] [fr-FR] Refresh french translation : Filters / Docs --- i18n/fr-FR.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/i18n/fr-FR.md b/i18n/fr-FR.md index eaa4415f..e66f3dd6 100644 --- a/i18n/fr-FR.md +++ b/i18n/fr-FR.md @@ -3134,14 +3134,14 @@ Utilisez [Gulp](http://gulpjs.com) ou [Grunt](http://gruntjs.com) pour créer de ###### [Style [Y420](#style-y420)] - - Évitez d'utiliser les filtres pour scanner toutes les propriété de l'arborescence d'un objet complexe. Utilisez les filtres pour sélectionner des propriétés. + - Évitez d'utiliser les filtres pour scanner toutes les propriétés de l'arborescence d'un objet complexe. Utilisez les filtres pour sélectionner des propriétés. - *Pourquoi ?*: les filtres peuvent être surutilisés et peuvent avoir des effets négatifs sur les performances s'ils ne sont pas utilisés de façon appropriée. Par exemple, quand un filtre touche un gros objet dont l'arborescence est profonde. + *Pourquoi ?*: les filtres peuvent être sur-utilisés et peuvent avoir des effets négatifs sur les performances s'ils ne sont pas utilisés de façon appropriée. Par exemple, quand un filtre touche un gros objet dont l'arborescence est profonde. **[Back to top](#table-of-contents)** -## Documentation Angular -Pour tout le reste, la référence des API, allez voir la [documentation Angular](//docs.angularjs.org/api). +## Documentation +Pour tout le reste, allez voir la [documentation de l'API d'Angular](//docs.angularjs.org/api). ## Contribuer From b974784401baf152ec5eff4b770fc2ee80eee466 Mon Sep 17 00:00:00 2001 From: Xavier Haniquaut Date: Wed, 19 Aug 2015 10:10:09 +0200 Subject: [PATCH 395/567] [fr-FR] Refresh french translation : End --- i18n/fr-FR.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/i18n/fr-FR.md b/i18n/fr-FR.md index e66f3dd6..1093d36e 100644 --- a/i18n/fr-FR.md +++ b/i18n/fr-FR.md @@ -3145,18 +3145,18 @@ Pour tout le reste, allez voir la [documentation de l'API d'Angular](//docs.angu ## Contribuer -Créez d'abord un problème pour discuter de potentiels changements ou ajouts. Si vous avez des questions sur le guide, je vous encourage à les rapporter comme problèmes dans le référentiel. Si vous trouvez une erreur de frappe, créez une pull request. L'idée est de garder le contenu à jour et d'utiliser les fonctionnalités natives de github pour aider à raporter les problèmes et les pull requests, lesquels sont recherchables via google. Pourquoi ? Parce que d'autres pourraient avoir la même question ! Vous en apprendrez plus ci-dessous pour savoir comment contribuer. +Créez d'abord une *issue* pour discuter de potentiels changements ou ajouts à faire. Si vous avez des questions sur le guide, je vous encourage à les soumettre en temps qu'*issues*. Si vous trouvez des erreurs de frappe, créez une *pull request*. L'idée est de garder le contenu à jour et d'utiliser les fonctionnalités natives de Github pour aider à retracer l'évolution de ce dernier via les *issues* et les *pull requests*, lesquels sont indexées par Google. Pourquoi ? Parce que si vous vous posez une question, il y a des chances que quelqu'un d'autre se la soit posé ! Vous en apprendrez plus ci-dessous pour savoir comment contribuer. -*En contribuant à ce référentiel, vous acceptez de rendre votre contenu accessible le sujet de la licence de ce référentiel.* +*En contribuant à ce dépôt, vous acceptez de rendre votre contenu accessible en accord avec la licence du dépôt.* ### Processus - 1. Discuter des changements dans une Issue GitHub. - 2. Ouvrir une Pull Request sur la branche develop, référencer l'Issue, et expliquer le changement et la raison pour laquelle ce changement est pertinent. - 3. La Pull Request sera évaluée et soit mergée ou abandonnée. + 1. Discuter des changements dans une *issue* GitHub. + 2. Ouvrir une *pull request* sur la branche `develop`, référencer l'*issue*, et expliquer le changement et la raison pour laquelle ce changement est pertinent. + 3. La *pull request* sera évaluée et *mergée* ou refusée. ## License -_tldr; Utilisez ce guide. Les attributions sont appréciées._ +en bref; Utilisez ce guide. Les attributions sont appréciées._ ### Copyright From 24294b5bfaaa39e185e604e80ce18bf66612a15a Mon Sep 17 00:00:00 2001 From: Xavier Haniquaut Date: Wed, 19 Aug 2015 10:14:34 +0200 Subject: [PATCH 396/567] [fr-FR] Refresh french translation : Readding translators --- i18n/fr-FR.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/i18n/fr-FR.md b/i18n/fr-FR.md index 1093d36e..3a555ca9 100644 --- a/i18n/fr-FR.md +++ b/i18n/fr-FR.md @@ -2,6 +2,8 @@ *Guide de style par subjectif pour Angular par [@john_papa](//twitter.com/john_papa)* +*Traduit par [Eric Lemerdy](https://github.com/ericlemerdy) et [Xavier Haniquaut](https://github.com/xavhan)* + Si vous cherchez un guide de style pour la syntaxe, les conventions, et la structuration d'applications Angular, alors vous êtes au bon endroit. Ces styles sont basés sur mon expérience de développement avec [Angular](//angularjs.org), mes présentations, [mes cours sur Pluralsight](http://pluralsight.com/training/Authors/Details/john-papa) et mon travail au sein de diverses équipes. Le but de ce guide de style est de proposer des conseils sur le développement d'applications Angular en exposant les conventions que j'utilise et plus important encore, pourquoi je les ai choisies. From 5fc820663746ff2ef110d0cad680eb3aa84d1cce Mon Sep 17 00:00:00 2001 From: vinicius-sabadim Date: Wed, 19 Aug 2015 15:23:55 -0300 Subject: [PATCH 397/567] Translate for the topic 'Modularity' in PT-BR --- i18n/PT-BR.md | 48 ++++++++++++++++++++++++++++++------------------ 1 file changed, 30 insertions(+), 18 deletions(-) diff --git a/i18n/PT-BR.md b/i18n/PT-BR.md index ce166365..1d8bff0b 100644 --- a/i18n/PT-BR.md +++ b/i18n/PT-BR.md @@ -2074,56 +2074,68 @@ ou *Estrutura de Pastas-por-Recurso* **[De volta ao topo](#tabela-de-conte%C3%BAdo)** ## Modularity +ou *Modularidade* ### Many Small, Self Contained Modules +ou *Muitos módulos pequenos e independentes* - - Create small modules that encapsulate one responsibility. + - Crie pequenos módulos que encapsulem uma única responsabilidade. - *Why?*: Modular applications make it easy to plug and go as they allow the development teams to build vertical slices of the applications and roll out incrementally. This means we can plug in new features as we develop them. + **Por que?**: Aplicações modulares tornam fácil o acoplamento, pois permitem que as equipes de desenvolvimento construam fatias verticais das aplicações e juntem tudo de forma incremental. Isto significa que podemos acoplar novos recursos enquanto os desenvolvemos. ### Create an App Module +ou *Crie um módulo da aplicação* - - Create an application root module whose role is pull together all of the modules and features of your application. Name this for your application. +- Crie um módulo raiz para a aplicação, cujo papel é: reunir todos os outros módulos e funcionalidades da sua aplicação. Nomeie ele de acordo com a sua aplicação. - *Why?*: Angular encourages modularity and separation patterns. Creating an application root module whose role is to tie your other modules together provides a very straightforward way to add or remove modules from your application. + **Por que?**: Angular incentiva padrões de modularidade e de separação. Criando um módulo raiz da aplicação cujo papel é o de amarrar os outros módulos juntos, fica muito simples de adicionar ou remover módulos na sua aplicação. ### Keep the App Module Thin +ou *Matenha o módulo da aplicação leve* - - Only put logic for pulling together the app in the application module. Leave features in their own modules. + - Somente coloque a lógica para reunir o aplicativo no módulo da aplicação. Deixe os recursos em seus próprios módulos. *Why?*: Adding additional roles to the application root to get remote data, display views, or other logic not related to pulling the app together muddies the app module and make both sets of features harder to reuse or turn off. + **Por que?**: Colocar funções adicionais na raiz da aplicação para obter dados remoto, modos de exibição, ou outra lógica não relacionada com o acoplamento do aplicativo, torna mais difícil reutilizar os recursos ou mesmo, desligá-los. + + **Por que?**: O módulo da aplicação torna-se um manifesto que descreve os módulos que ajudam a definir a aplicação. ### Feature Areas are Modules +ou *Áreas de recursos são módulos* - - Create modules that represent feature areas, such as layout, reusable and shared services, dashboards, and app specific features (e.g. customers, admin, sales). + - Crie módulos que representem áreas de recursos, como: layout, serviços compartilhados e reutilizados, dashboards e recursos específicos do aplicativo (por exemplo, clientes, administrativo, vendas). - *Why?*: Self contained modules can be added to the application will little or no friction. + **Por que?**: Módulos independentes podem ser adicionados na aplicação com pouco ou nenhum esforço. - *Why?*: Sprints or iterations can focus on feature areas and turn them on at the end of the sprint or iteration. + **Por que?**: Sprints ou iterações podem focar em áreas de recursos e acoplá-los na aplicação ao fim da sprint ou iteração. - *Why?*: Separating feature areas into modules makes it easier to test the modules in isolation and reuse code. + **Por que²**: Separando as áreas de recursos em módulos, fica fácil de testar os módulos em isolamento e de reutilizar o código. ### Reusable Blocks are Modules +ou *Blocos reutilizáveis são módulos* - - Create modules that represent reusable application blocks for common services such as exception handling, logging, diagnostics, security, and local data stashing. +- Crie módulos que representam blocos reutilizáveis da aplicação para serviços comuns, como: tratamento de exceção, log, diagnósticos, segurança e armazenamento local. - *Why?*: These types of features are needed in many applications, so by keeping them separated in their own modules they can be application generic and be reused across applications. + **Por que?**: Esses tipos de recursos são necessários em muitas aplicações, então mantê-los separados em seus próprios módulos os torna genéricos e assim, podem ser reutilizados em diferentes aplicações. ### Module Dependencies +ou *Dependências do módulo* + + - O módulo raiz da aplicação depende de módulos de recursos específicos do aplicativo e de qualquer módulo compartilhado ou reutilizado. - - The application root module depends on the app specific feature modules, the feature modules have no direct dependencies, the cross-application modules depend on all generic modules. + ![Moduluaridade e Dependências](https://raw.githubusercontent.com/johnpapa/angular-styleguide/master/assets/modularity-1.png) - ![Modularity and Dependencies](https://raw.githubusercontent.com/johnpapa/angularjs-styleguide/master/assets/modularity-1.png) + **Por que?**: O módulo principal do aplicativo contém um rápido manifesto para identificar os recursos da aplicação. - *Why?*: The main app module contains a quickly identifiable manifest of the application's features. + **Por que?**: Cada área de recurso contém um manifesto mostrando as suas dependências, assim, ela pode ser colocada como uma dependência em outras aplicação e ainda continuar funcionando. - *Why?*: Cross application features become easier to share. The features generally all rely on the same cross application modules, which are consolidated in a single module (`app.core` in the image). + **Por que?**: Recursos intra-aplicação como serviços compartilhados de dados, tornam-se muito mais fácil de localizar e compartilhar atráves do `app.core` (escolha o seu nome favorito para esse módulo). - *Why?*: Intra-App features such as shared data services become easy to locate and share from within `app.core` (choose your favorite name for this module). + Nota: Essa é uma estratégia para consistência. Existem muitas outras boas opções. Escolha uma que seja consistente, que siga as regras de dependência do Angular, e que seja fácil de manter e escalar. - Note: This is a strategy for consistency. There are many good options here. Choose one that is consistent, follows AngularJS's dependency rules, and is easy to maintain and scale. + > As minhas estruturas podem variar ligeiramente entre os projetos, mas todas elas seguem estas diretrizes para estrutura e modularidade. A implementação pode variar dependendo dos recursos e do time. Em outras palavras, não fique preso somente a uma estrutura mas justifique sua estrutura usando consistência, facilidade de manutenção e eficiência em mente. - > My structures vary slightly between projects but they all follow these guidelines for structure and modularity. The implementation may vary depending on the features and the team. In other words, don't get hung up on an exact like-for-like structure but do justify your structure using consistency, maintainability, and efficiency in mind. + > Em um aplicativo pequeno, você também pode considerar colocar todas as dependẽncias compartilhadas no módulo principal do aplicativo, onde os módulos de recursos não tem dependências diretas. Isso torna mais fácil de manter a aplicação, mas torna mais difícil de reutilizar os módulos fora dessa aplicação. **[De volta ao topo](#tabela-de-conte%C3%BAdo)** From 8d1ac33bc022af5cb6ae272befd1340a0675069d Mon Sep 17 00:00:00 2001 From: vinicius-sabadim Date: Wed, 19 Aug 2015 15:24:50 -0300 Subject: [PATCH 398/567] Fix typo --- i18n/PT-BR.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/i18n/PT-BR.md b/i18n/PT-BR.md index 1d8bff0b..cd92098a 100644 --- a/i18n/PT-BR.md +++ b/i18n/PT-BR.md @@ -2091,7 +2091,7 @@ ou *Crie um módulo da aplicação* **Por que?**: Angular incentiva padrões de modularidade e de separação. Criando um módulo raiz da aplicação cujo papel é o de amarrar os outros módulos juntos, fica muito simples de adicionar ou remover módulos na sua aplicação. ### Keep the App Module Thin -ou *Matenha o módulo da aplicação leve* +ou *Mantenha o módulo da aplicação leve* - Somente coloque a lógica para reunir o aplicativo no módulo da aplicação. Deixe os recursos em seus próprios módulos. From 92c7a8d5828aa991b8c3caaaa57d35fee53b671e Mon Sep 17 00:00:00 2001 From: zach_lysobey Date: Wed, 19 Aug 2015 18:12:53 -0400 Subject: [PATCH 399/567] Remove extra spaces from sublime template Sublime directive template had extra space between function namess and parens --- .../angular.directive.sublime-snippet | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/assets/sublime-angular-snippets/angular.directive.sublime-snippet b/assets/sublime-angular-snippets/angular.directive.sublime-snippet index 4c1c91bf..a4bbd6a2 100644 --- a/assets/sublime-angular-snippets/angular.directive.sublime-snippet +++ b/assets/sublime-angular-snippets/angular.directive.sublime-snippet @@ -9,7 +9,7 @@ ${2:directive}.\$inject = [${3/(\$(\w+)|\w+)/'$1'/g}]; /* @ngInject */ - function ${2:directive} (${3:dependencies}) { + function ${2:directive}(${3:dependencies}) { // Usage: // // Creates: @@ -30,7 +30,7 @@ } /* @ngInject */ - function ${4:Controller} () { + function ${4:Controller}() { } })(); From eab1808500c72664941948647ce81ba1762c8b82 Mon Sep 17 00:00:00 2001 From: Xavier Haniquaut Date: Thu, 20 Aug 2015 10:04:23 +0200 Subject: [PATCH 400/567] Fixes after @ericlemerdy comments --- i18n/fr-FR.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/i18n/fr-FR.md b/i18n/fr-FR.md index 3a555ca9..0e5eeaed 100644 --- a/i18n/fr-FR.md +++ b/i18n/fr-FR.md @@ -1,6 +1,6 @@ # Charte stylistique Angular -*Guide de style par subjectif pour Angular par [@john_papa](//twitter.com/john_papa)* +*Guide de style subjectif pour Angular par [@john_papa](//twitter.com/john_papa)* *Traduit par [Eric Lemerdy](https://github.com/ericlemerdy) et [Xavier Haniquaut](https://github.com/xavhan)* @@ -172,7 +172,7 @@ Bien que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'est ut })(); ``` - - Note : Pour des raisons de concision seulement, le reste des exemples de ce guide seront pas écrits avec la syntaxe IIFE. + - Note : Pour des raisons de concision seulement, le reste des exemples de ce guide ne seront pas écrits avec la syntaxe IIFE. - Note : Les IIFE empêchent le code de test d'atteindre des membres privés, comme les expressions régulières ou les fonctions utilitaires (*helpers*), qu'il est souvent meilleur de tester indépendamment. Cependant, vous pouvez les tester à travers les membres accessibles ou en les exposant à travers leur propre composant. Par exemple en les plaçant dans leur propre factory ou constante. From 8f72dee392129bdeb01c043fae7d295fc83e1a38 Mon Sep 17 00:00:00 2001 From: Xavier Haniquaut Date: Thu, 20 Aug 2015 10:19:06 +0200 Subject: [PATCH 401/567] Makes lines match All credits for the translators are now on the i18n/README.md Their is a lot of work in some translation to keep it updated. --- i18n/PT-BR.md | 308 ++++++++++++++++++++--------------------- i18n/README.md | 29 ++-- i18n/de-DE.md | 52 ++++--- i18n/es-ES.md | 4 - i18n/fr-FR.md | 2 - i18n/it-IT.md | 368 ++++++++++++++++++++++++------------------------- i18n/ja-JP.md | 18 ++- i18n/mk-MK.md | 318 +++++++++++++++++++++--------------------- i18n/ru-RU.md | 279 +++++++++++++++++++------------------ i18n/zh-CN.md | 288 +++++++++++++++++++------------------- 10 files changed, 818 insertions(+), 848 deletions(-) diff --git a/i18n/PT-BR.md b/i18n/PT-BR.md index cd92098a..926c9764 100644 --- a/i18n/PT-BR.md +++ b/i18n/PT-BR.md @@ -2,11 +2,9 @@ *Guia de Estilo opinativo de Angular para times. Por [@john_papa](//twitter.com/john_papa)* -*Traduzido por [Eric Douglas](https://github.com/ericdouglas), [Ciro Nunes](https://github.com/cironunes), [Jean Lucas de Carvalho](https://github.com/jlcarvalho) e [Vinicius Sabadim Fernandes](https://github.com/vinicius-sabadim)* +Se você procura por um guia de estilo opinativo para sintaxe, convenções e estruturação de aplicações AngularJS, então siga em frente! Estes estilos são baseados em minha experiência com desenvolvimento com [AngularJS](//angularjs.org), apresentações, [cursos de treinamento na Pluralsight](http://pluralsight.com/training/Authors/Details/john-papa) e trabalhando em equipe. ->The [original English version](http://jpapa.me/ngstyles) is the source of truth, as it is maintained and updated first. -Se você procura por um guia de estilo opinativo para sintaxe, convenções e estruturação de aplicações AngularJS, então siga em frente! Estes estilos são baseados em minha experiência com desenvolvimento com [AngularJS](//angularjs.org), apresentações, [cursos de treinamento na Pluralsight](http://pluralsight.com/training/Authors/Details/john-papa) e trabalhando em equipe. > Se você gostar deste guia, confira meu curso [Angular Patterns: Clean Code](http://jpapa.me/ngclean) na Pluralsight. @@ -22,11 +20,11 @@ Vários de meus estilos vieram de várias sessões de pair-programming (programa Embora este guia explique o **o quê**, **porque** e **como**, acho útil ver tudo isso em prática. Este guia é acompanhado de uma aplicação de exemplo que segue estes estilos e padrões. Você pode encontrar a [aplicação de exemplo (chamada "modular") aqui](https://github.com/johnpapa/ng-demos) na pasta `modular`. Sinta-se livre para pegá-la, cloná-la e *forká-la*. [Instruções de como rodar o aplicativo estão em seu README](https://github.com/johnpapa/ng-demos/tree/master/modular). -> **Nota de tradução**: Os títulos originais de cada seção serão mantidos, pois caso você queira buscar mais sobre estes assuntos futuramente, fazendo tal busca em inglês será obtido um resultado **imensamente** melhor. +> **Nota de tradução**: Os títulos originais de cada seção serão mantidos, pois caso você queira buscar mais sobre estes assuntos futuramente, fazendo tal busca em inglês será obtido um resultado **imensamente** melhor. > > Após o título, estará a tradução auxiliar, quando necessária, visto que alguns termos são mais facilmente entendidos quando não traduzidos, por fazerem parte do núcleo do estudo em questão. > -> Para eventuais erros de digitação e/ou tradução, favor enviar um pull-request! +> Para eventuais erros de digitação e/ou tradução, favor enviar um pull-request! ## Tabela de Conteúdo @@ -48,7 +46,7 @@ Embora este guia explique o **o quê**, **porque** e **como**, acho útil ver tu 1. [Modularity](#modularity) 1. [Angular $ Wrapper Services](#angular--wrapper-services) 1. [Testing](#testing) - 1. [Animations](#animations) + 1. [Animations](#animations) 1. [Comments](#comments) 1. [JSHint](#js-hint) 1. [Constants](#constants) @@ -72,7 +70,7 @@ ou *Responsabilidade Única* .module('app', ['ngRoute']) .controller('SomeController' , SomeController) .factory('someFactory' , someFactory); - + function SomeController() { } function someFactory() { } @@ -82,7 +80,7 @@ ou *Responsabilidade Única* ```javascript /* recomendado */ - + // app.module.js angular .module('app', ['ngRoute']); @@ -90,7 +88,7 @@ ou *Responsabilidade Única* ```javascript /* recomendado */ - + // someController.js angular .module('app') @@ -101,12 +99,12 @@ ou *Responsabilidade Única* ```javascript /* recomendado */ - + // someFactory.js angular .module('app') .factory('someFactory' , someFactory); - + function someFactory() { } ``` @@ -140,18 +138,18 @@ ou *Responsabilidade Única* function storage() { } ``` - + ```javascript /** - * recomendado + * recomendado * - * nada global é deixado para trás + * nada global é deixado para trás */ // logger.js (function() { 'use strict'; - + angular .module('app') .factory('logger', logger); @@ -171,9 +169,9 @@ ou *Responsabilidade Única* })(); ``` - - **Nota**: Apenas para agilizar, o resto dos exemplos neste guia omitirão a sintaxe IIFE. + - **Nota**: Apenas para agilizar, o resto dos exemplos neste guia omitirão a sintaxe IIFE. - - **Nota**: IIFE impede que códigos de teste alcancem membros privados como expressões regulares ou funções auxiliares que são frequentemente boas para testes unitários. Entretanto, você pode testá-las através de membros acessíveis ou expondo-os pelo próprio componente. Por exemplo, colocando funções auxiliares, expressões regulares ou constantes em sua própria *factory* ou constante. + - **Nota**: IIFE impede que códigos de teste alcancem membros privados como expressões regulares ou funções auxiliares que são frequentemente boas para testes unitários. Entretanto, você pode testá-las através de membros acessíveis ou expondo-os pelo próprio componente. Por exemplo, colocando funções auxiliares, expressões regulares ou constantes em sua própria *factory* ou constante. **[De volta ao topo](#tabela-de-conte%C3%BAdo)** @@ -185,7 +183,7 @@ ou *Evitando Colisão de Nomes* - Use uma única convenção de nomes com separadores para sub-módulos. - **Por que?** Nomes únicos ajudam a evitar colisão de nomes no módulo. Separadores ajudam a definir a hierarquia de módulos e submódulos. Por exemplo, `app` pode ser seu módulo raiz, enquanto `app.dashboard` e `app.users` podem ser módulos que são usados como dependências de `app`. + **Por que?** Nomes únicos ajudam a evitar colisão de nomes no módulo. Separadores ajudam a definir a hierarquia de módulos e submódulos. Por exemplo, `app` pode ser seu módulo raiz, enquanto `app.dashboard` e `app.users` podem ser módulos que são usados como dependências de `app`. ### Definições (*aka Setters*) @@ -194,7 +192,7 @@ ou *Evitando Colisão de Nomes* - Declare os módulos sem uma variável usando a sintaxe *setter*. **Por que?** Com 1 componente por arquivo, raramente será necessário criar uma variável para o módulo. - + ```javascript /* evite */ var app = angular.module('app', [ @@ -228,7 +226,7 @@ ou *Evitando Colisão de Nomes* /* evite */ var app = angular.module('app'); app.controller('SomeController' , SomeController); - + function SomeController() { } ``` @@ -237,24 +235,24 @@ ou *Evitando Colisão de Nomes* angular .module('app') .controller('SomeController' , SomeController); - + function SomeController() { } ``` -### *Setting* vs *Getting* +### *Setting* vs *Getting* ou *Definindo* vs *Obtendo* - Apenas *set* (configure) uma vez e *get* (receba) em todas as outras instâncias. - - **Por que?** Um módulo deve ser criado somente uma vez, então recupere-o deste ponto em diante. - + + **Por que?** Um módulo deve ser criado somente uma vez, então recupere-o deste ponto em diante. + - Use `angular.module('app', []);` para definir (*set*) um módulo. - - Use `angular.module('app');` para pegar (*get*) este módulo. + - Use `angular.module('app');` para pegar (*get*) este módulo. ### Named vs Anonymous Functions ou *Funções Nomeadas vs Funções Anônimas* - - Use funções nomeadas ao invés de passar uma função anônima como um callback. + - Use funções nomeadas ao invés de passar uma função anônima como um callback. **Por que?** Isso produz um código mais legível, é muito fácil de *debugar*, e reduz a quantidade de callbacks aninhados no código. @@ -293,7 +291,7 @@ ou *Controladores* ### controllerAs View Syntax - - Utilize a sintaxe [`controllerAs`](http://www.johnpapa.net/do-you-like-your-angular-controllers-with-or-without-sugar/) ao invés da sintaxe `clássica controller com $scope`. + - Utilize a sintaxe [`controllerAs`](http://www.johnpapa.net/do-you-like-your-angular-controllers-with-or-without-sugar/) ao invés da sintaxe `clássica controller com $scope`. **Por que?**: Controllers são construídos, "iniciados", e fornecem um nova instância única, e a sintaxe `controllerAs` é mais próxima de um construtor JavaScript do que a `sintaxe clássica do $scope`. @@ -317,11 +315,11 @@ ou *Controladores* ### controllerAs Controller Syntax - - Utilize a sintaxe `controllerAs` ao invés da sintaxe `clássica controller com $scope`. + - Utilize a sintaxe `controllerAs` ao invés da sintaxe `clássica controller com $scope`. - A sintaxe `controllerAs` usa o `this` dentro dos controllers que fica ligado ao `$scope`. - **Por que?**: O `controllerAs` é uma forma mais simples de lidar com o `$scope`. Você ainda poderá fazer o bind para a View e ainda poderá acessar os métodos do `$scope`. + **Por que?**: O `controllerAs` é uma forma mais simples de lidar com o `$scope`. Você ainda poderá fazer o bind para a View e ainda poderá acessar os métodos do `$scope`. **Por que?**: Ajuda a evitar a tentação de usar os métodos do `$scope` dentro de um controller quando seria melhor evitá-los ou movê-los para um factory. Considere utilizar o `$scope` em um factory, ou em um controller apenas quando necessário. Por exemplo, quando publicar e subscrever eventos usando [`$emit`](https://docs.angularjs.org/api/ng/type/$rootScope.Scope#$emit), [`$broadcast`](https://docs.angularjs.org/api/ng/type/$rootScope.Scope#$broadcast), ou [`$on`](https://docs.angularjs.org/api/ng/type/$rootScope.Scope#$on) considere mover estes casos para um factory e invocá-los a partir do controller. @@ -344,7 +342,7 @@ ou *Controladores* ### controllerAs with vm - Utilize uma variável de captura para o `this` quando usar a sintaxe `controllerAs`. Escolha um nome de variável consistente como `vm`, que representa o ViewModel. - + **Por que?**: A palavra-chave `this` é contextual e quando usada em uma função dentro de um controller pode mudar seu contexto. Capturando o contexto do `this` evita a ocorrência deste problema. ```javascript @@ -364,13 +362,13 @@ ou *Controladores* } ``` - Nota: Você pode evitar qualquer [jshint](http://www.jshint.com/) warnings colocando o comentário abaixo acima da linha de código. - + Nota: Você pode evitar qualquer [jshint](http://www.jshint.com/) warnings colocando o comentário abaixo acima da linha de código. + ```javascript /* jshint validthis: true */ var vm = this; ``` - + Nota: Quando watches são criados no controller utilizando o `controller as`, você pode observar o objeto `vm.*` utilizando a seguinte sintaxe. (Crie watches com cuidado pois eles deixam o ciclo de digest mais "carregado".) ```javascript @@ -383,7 +381,7 @@ ou *Controladores* ### Bindable Members Up Top - Coloque os objetos que precisam de bind no início do controller, em ordem alfabética, e não espalhados através do código do controller. - + **Por que?**: Colocar os objetos que precisam de bind no início torna mais fácil de ler e te ajuda a instantaneamente identificar quais objetos do controller podem ser utilizados na View. **Por que?**: Setar funções anônimas pode ser fácil, mas quando essas funções possuem mais de 1 linha do código elas podem dificultar a legibilidade. Definir as funções abaixo dos objetos que necessitam de bind (as funções serão elevadas pelo JavaScript Hoisting) move os detalhes de implementação para o final do controller, mantém os objetos que necessitam de bind no topo, e deixa o código mais fácil de se ler. @@ -443,8 +441,8 @@ ou *Controladores* vm.gotoSession = gotoSession; vm.refresh = function() { - /** - * linhas + /** + * linhas * de * código * afetam @@ -472,20 +470,20 @@ ou *Controladores* ### Function Declarations to Hide Implementation Details - Utilize declarações de funções para esconder detalhes de implementação. Mantenha seus objetos que necessitam de bind no topo. Quando você precisar fazer o bind de uma função no controller, aponte ela para a declaração de função que aparece no final do arquivo. Ela está ligada diretamente aos objetos que precisam de bind no início do arquivo. Para mais detalhes veja [este post](http://www.johnpapa.net/angular-function-declarations-function-expressions-and-readable-code). - + **Por que?**: Colocar os objetos que precisam de bind no início torna mais fácil de ler e te ajuda a instantaneamente identificar quais objetos do controller podem ser utilizados na View. (Mesmo do item anterior.) **Por que?**: Colocar os detalhes de implementação de uma função no final do arquivo coloca a complexidade fora do foco, logo, você pode focar nas coisas importantes no topo. **Por que?**: Declarações de funções são içadas, logo, não existe problema de se utilizar uma função antes dela ser definida (como haveria com expressões de função). - **Por que?**: Você nunca precisará se preocupar com declarações de funções quebrarem seu código por colocar `var a` antes de `var b` por que `a` depende de `b`. + **Por que?**: Você nunca precisará se preocupar com declarações de funções quebrarem seu código por colocar `var a` antes de `var b` por que `a` depende de `b`. **Por que?**: A ordenação é crítica em expressões de função. ```javascript - /** - * evite + /** + * evite * Usar expressões de funções. */ function Avengers(dataservice, logger) { @@ -560,7 +558,7 @@ ou *Controladores* vm.checkCredit = checkCredit; vm.total = 0; - function checkCredit() { + function checkCredit() { var orderTotal = vm.total; return $http.get('api/creditcheck').then(function(data) { var remaining = data.remaining; @@ -577,7 +575,7 @@ ou *Controladores* vm.checkCredit = checkCredit; vm.total = 0; - function checkCredit() { + function checkCredit() { return creditService.check(); }; } @@ -586,14 +584,14 @@ ou *Controladores* ### Keep Controllers Focused - Defina um controller para a view, e tente não reutilizar o controller para outras views. Ao invés disso, coloque as lógicas reaproveitáveis em factories e mantenha o controller simples e focado em sua view. - + **Por que?**: Reutilizar controllers em várias views é arriscado e um boa cobertura de testes end to end (e2e) é obrigatório para se garantir estabilidade em grandes aplicações. ### Assigning Controllers - - Quando um controller deve ser pareado com sua view e algum componente pode ser reutilizado por outros controllers ou views, defina controllers juntamente de suas rotas. - - Nota: Se uma View é carregada de outra forma que não seja através de uma rota, então utilize a sintaxe `ng-controller="Avengers as vm"`. + - Quando um controller deve ser pareado com sua view e algum componente pode ser reutilizado por outros controllers ou views, defina controllers juntamente de suas rotas. + + Nota: Se uma View é carregada de outra forma que não seja através de uma rota, então utilize a sintaxe `ng-controller="Avengers as vm"`. **Por que?**: Parear os controllers nas rotas permite diferentes rotas invocarem diferentes pares de controllers e views. Quando um controller é utilizado na view usando a sintaxe [`ng-controller`](https://docs.angularjs.org/api/ng/directive/ngController), esta view sempre será associada ao mesmo controller. @@ -650,8 +648,8 @@ ou *Serviços* ### Singletons - - Services são instanciados com a palavra-chave `new`, use `this` para métodos públicos e variáveis. Services são bastante similares a factories, use um factory para consistência. - + - Services são instanciados com a palavra-chave `new`, use `this` para métodos públicos e variáveis. Services são bastante similares a factories, use um factory para consistência. + Nota: [Todos services em Angular são singletons](https://docs.angularjs.org/guide/services). Isso significa que há apenas uma instância do serviço para cada injetor. ```javascript @@ -695,15 +693,15 @@ ou *Responsabilidade Única* ### Singletons - Factories são singletons e retornam um objeto que contém os membros do serviço. - + Nota: [Todos services em Angular são singletons](https://docs.angularjs.org/guide/services). ### Accessible Members Up Top ou *Membros acessíveis no topo* - - Exponha os membros que podem ser invocados no serviço (a interface) no topo, utilizando uma técnica derivada do [Revealing Module Pattern](http://addyosmani.com/resources/essentialjsdesignpatterns/book/#revealingmodulepatternjavascript). + - Exponha os membros que podem ser invocados no serviço (a interface) no topo, utilizando uma técnica derivada do [Revealing Module Pattern](http://addyosmani.com/resources/essentialjsdesignpatterns/book/#revealingmodulepatternjavascript). - **Por que?**: Colocando no topo os membros que podem ser invocados da factory, a leitura torna-se mais fácil e ajuda a identificar imediatamente quais membros da factory podem ser invocados e testados através de teste unitário (e/ou mock). + **Por que?**: Colocando no topo os membros que podem ser invocados da factory, a leitura torna-se mais fácil e ajuda a identificar imediatamente quais membros da factory podem ser invocados e testados através de teste unitário (e/ou mock). **Por que?**: É especialmente útil quando o arquivo torna-se muito longo e ajuda a evitar a necessidade de rolagem para ver o que é exposto. @@ -713,10 +711,10 @@ ou *Membros acessíveis no topo* /* evite */ function dataService() { var someValue = ''; - function save() { + function save() { /* */ }; - function validate() { + function validate() { /* */ }; @@ -741,11 +739,11 @@ ou *Membros acessíveis no topo* //////////// - function save() { + function save() { /* */ }; - function validate() { + function validate() { /* */ }; } @@ -766,9 +764,9 @@ ou *Declarações de função para esconder detalhes de implementação* **Por que?**: Function declarations (declarações de função) são içadas (hoisted) para que não hajam preocupações em utilizar uma função antes que ela seja definida (como haveria com function expressions (expressões de função)). - **Por que?**: Você nunca deve se preocupar com function declaration (declarações de função) onde `var a` está antes de `var b` vai ou não quebrar o seu código porque `a` depende de `b`. + **Por que?**: Você nunca deve se preocupar com function declaration (declarações de função) onde `var a` está antes de `var b` vai ou não quebrar o seu código porque `a` depende de `b`. - **Por que?**: A ordem é crítica com function expressions (expressões de função) + **Por que?**: A ordem é crítica com function expressions (expressões de função) ```javascript /** @@ -899,7 +897,7 @@ ou *Chamadas de dados separadas* } } ``` - + Nota: O serviço de dados (data service) é chamado pelos consumidores, como um controlador (controller), escondendo a implementação dos consumidores, como mostrado abaixo. ```javascript @@ -931,7 +929,7 @@ ou *Chamadas de dados separadas* return vm.avengers; }); } - } + } ``` ### Return a Promise from Data Calls @@ -989,7 +987,7 @@ ou *Limite 1 por arquivo* - Crie uma diretiva (directive) por arquivo. Nomeie o arquivo pela diretiva. - **Por que?**: É fácil misturar todas as diretivas em um arquivo, mas é difícil depois separá-las, já que algumas são compartilhadas entre aplicativos, outras pelos módulos (modules) e algumas somente para um módulo. + **Por que?**: É fácil misturar todas as diretivas em um arquivo, mas é difícil depois separá-las, já que algumas são compartilhadas entre aplicativos, outras pelos módulos (modules) e algumas somente para um módulo. **Por que?**: Uma diretiva (directive) por arquivo é mais fácil de dar manutenção. @@ -1047,7 +1045,7 @@ ou *Limite 1 por arquivo* /** * @desc diretiva de spinner que pode ser usada em qualquer lugar de um aplicativo de vendas em uma companhia chamada Acme * @example
- */ + */ angular .module('sales.widgets') .directive('acmeSalesCustomerInfo', salesCustomerInfo); @@ -1079,7 +1077,7 @@ ou *Limite 1 por arquivo* ### Limit DOM Manipulation ou *Limite a manipulação do DOM* - - Quando estiver manipulando o DOM diretamente, utilize uma diretiva (directive). Se formas alternativas podem ser utilizadas, como: utilizar CSS para setar estilos ou [serviços de animação (animation services)](https://docs.angularjs.org/api/ngAnimate), Angular templating, [`ngShow`](https://docs.angularjs.org/api/ng/directive/ngShow) ou [`ngHide`](https://docs.angularjs.org/api/ng/directive/ngHide), então prefira utilizá-los. Por exemplo, se uma diretiva simplesmente esconde ou mostra um elemento, use ngHide/ngShow. + - Quando estiver manipulando o DOM diretamente, utilize uma diretiva (directive). Se formas alternativas podem ser utilizadas, como: utilizar CSS para setar estilos ou [serviços de animação (animation services)](https://docs.angularjs.org/api/ngAnimate), Angular templating, [`ngShow`](https://docs.angularjs.org/api/ng/directive/ngShow) ou [`ngHide`](https://docs.angularjs.org/api/ng/directive/ngHide), então prefira utilizá-los. Por exemplo, se uma diretiva simplesmente esconde ou mostra um elemento, use ngHide/ngShow. **Por que?**: A manipulação do DOM pode ser difícil de testar, debugar, e há melhores maneiras (ex: CSS, animações (animations), templates). @@ -1088,9 +1086,9 @@ ou *Forneça um prefixo único para as diretivas* - Forneça um curto, único e descritivo prefixo para a diretiva, como `acmeSalesCustomerInfo`, que é declarado no HTML como `acme-sales-customer-info`. - **Por que?**: Um prefixo curto e único identifica o contexto e a origem da diretiva. Por exemplo, o prefixo `cc-` pode indicar que a diretiva é parte de um aplicativo da CodeCamper, enquanto a diretiva `acme-` pode indicar uma diretiva para a companhia Acme. + **Por que?**: Um prefixo curto e único identifica o contexto e a origem da diretiva. Por exemplo, o prefixo `cc-` pode indicar que a diretiva é parte de um aplicativo da CodeCamper, enquanto a diretiva `acme-` pode indicar uma diretiva para a companhia Acme. - Nota: Evite `ng-`, pois são reservadas para as diretivas do AngularJS. Pesquise largamente as diretivas utilizadas para evitar conflitos de nomes, como `ion-` que são utilizadas para o [Ionic Framework](http://ionicframework.com/). + Nota: Evite `ng-`, pois são reservadas para as diretivas do AngularJS. Pesquise largamente as diretivas utilizadas para evitar conflitos de nomes, como `ion-` que são utilizadas para o [Ionic Framework](http://ionicframework.com/). ### Restrict to Elements and Attributes ou *Restringir para elementos e atributos* @@ -1133,7 +1131,7 @@ ou *Restringir para elementos e atributos*
``` - + ```javascript /* recomendado */ angular @@ -1161,7 +1159,7 @@ ou *Diretivas e "ControladorComo"* **Por que?**: Faz sentido e não é difícil. - Nota: A diretiva (directive) abaixo demonstra algumas maneiras que você pode utilizar escopos (scopes) dentro de link e controller de uma diretiva, utilizando controllerAs. Eu coloquei o template somente para manter tudo em um mesmo local. + Nota: A diretiva (directive) abaixo demonstra algumas maneiras que você pode utilizar escopos (scopes) dentro de link e controller de uma diretiva, utilizando controllerAs. Eu coloquei o template somente para manter tudo em um mesmo local. ```html
@@ -1191,8 +1189,8 @@ ou *Diretivas e "ControladorComo"* /* jshint validthis:true */ var vm = this; - vm.min = 3; - vm.max = $scope.max; + vm.min = 3; + vm.max = $scope.max; console.log('CTRL: $scope.max = %i', $scope.max); console.log('CTRL: vm.min = %i', vm.min); console.log('CTRL: vm.max = %i', vm.max); @@ -1222,11 +1220,11 @@ ou *Resolvendo promessas para um controlador* ou *Ativação de promessas no controlador* - Resolva a lógica de inicialização no controlador (controller) em uma função `iniciar`. - + **Por que?**: Colocando a lógica de inicialização em um lugar consistente no controlador (controller), torna mais fácil de localizar, mais consistente para testar e ajuda a evitar o espalhamento da lógica de inicialização pelo controlador (controller). Nota: Se vocẽ precisa cancelar a rota condicionalmente antes de utilizar o controlador (controller), utilize uma resolução de rota (route resolve). - + ```javascript /* evite */ function Avengers(dataservice) { @@ -1331,7 +1329,7 @@ ou *Anotação Manual para Injeção de Dependência* ou *Não seguro para Minificação* - Evite usar o atalho de sintaxe de declarar dependências sem usar uma abordagem segura para minificação. - + **Por que?**: Os parâmetros do componente (por ex. controller, factory, etc) serão convertidos em variáveis encurtadas. Por exemplo, `common` e `dataservice` podem virar `a` ou `b` e não serem encontrados pelo AngularJS. ```javascript @@ -1355,30 +1353,30 @@ ou *Não seguro para Minificação* ou *Identifique Dependências Manualmente* - Use `$inject` para identificar manualmente suas dependências de componentes do AngularJS. - + **Por que?**: Esta técnica espelha a técnica usada por [`ng-annotate`](https://github.com/olov/ng-annotate), a qual eu recomendo para automatizar a criação de dependências seguras para minificação. Se `ng-annotate` detectar que a injeção já foi feita, ela não será duplicada. **Por que?**: Isto salvaguarda suas dependências de serem vulneráveis a problemas de minificação quando parâmetros podem ser encurtados. Por exemplo, `common` e `dataservice` podem se tornar `a` ou `b` e não serem encontrados pelo AngularJS. - + **Por que?**: Evite criar dependências in-line pois listas longas podem ser difíceis de ler no array. Além disso, pode ser confuso o array ser uma série de strings enquanto o último item é a função do componente. ```javascript /* evite */ angular .module('app') - .controller('Dashboard', - ['$location', '$routeParams', 'common', 'dataservice', + .controller('Dashboard', + ['$location', '$routeParams', 'common', 'dataservice', function Dashboard($location, $routeParams, common, dataservice) {} - ]); + ]); ``` ```javascript /* evite */ angular .module('app') - .controller('Dashboard', + .controller('Dashboard', ['$location', '$routeParams', 'common', 'dataservice', Dashboard]); - + function Dashboard($location, $routeParams, common, dataservice) { } ``` @@ -1390,12 +1388,12 @@ ou *Identifique Dependências Manualmente* .controller('Dashboard', Dashboard); Dashboard.$inject = ['$location', '$routeParams', 'common', 'dataservice']; - + function Dashboard($location, $routeParams, common, dataservice) { } ``` - Nota: Quando sua função estiver abaixo de um return o $inject pode ficar inacessível (isso pode acontecer em uma diretiva). Você pode resolver isso movendo o $inject para acima do return ou usando a sintaxe alternativa de injeção de array. + Nota: Quando sua função estiver abaixo de um return o $inject pode ficar inacessível (isso pode acontecer em uma diretiva). Você pode resolver isso movendo o $inject para acima do return ou usando a sintaxe alternativa de injeção de array. Nota: [`ng-annotate 0.10.0`](https://github.com/olov/ng-annotate) introduziu um comportamento em que ele move o `$inject` para onde ele possa ser acessado. @@ -1429,7 +1427,7 @@ ou *Identifique Dependências Manualmente* ou *Identifique Dependências do Resolvedor de Rotas Manualmente* - Use $inject para identificar manualmente as dependências do seu resolvedor de rotas para componentes do AngularJS. - + **Por que?**: Esta técnica separa a função anônima do resolvedor de rota, tornando-a mais fácil de ler. **Por que?**: Uma chamada a `$inject` pode facilmente preceder o resolvedor para fazer qualquer dependência segura para minificação. @@ -1462,10 +1460,10 @@ ou *Minificação e Anotação* ### ng-annotate - Use [ng-annotate](//github.com/olov/ng-annotate) para [Gulp](http://gulpjs.com) ou [Grunt](http://gruntjs.com) e comente as funções que precisam de injeção de dependência automatizada usando `/** @ngInject */` - + **Por que?**: Isso protege seu código de qualquer dependência que pode não estar usando práticas seguras para minificação. - **Por que?**: [`ng-min`](https://github.com/btford/ngmin) está deprecated. + **Por que?**: [`ng-min`](https://github.com/btford/ngmin) está deprecated. > Eu prefiro Gulp pois sinto que é mais fácil de escrever, de ler, e de debugar. @@ -1538,7 +1536,7 @@ ou *Minificação e Anotação* ### Utilize Gulp ou Grunt para o ng-annotate - Utilize [gulp-ng-annotate](https://www.npmjs.org/package/gulp-ng-annotate) ou [grunt-ng-annotate](https://www.npmjs.org/package/grunt-ng-annotate) para tarefas de build automatizadas. Injete `/* @ngInject */` antes de qualquer função que tenha dependências. - + **Por que?**: ng-annotate vai capturar todas as dependências, mas as vezes requer dicas utilizando a sintaxe `/* @ngInject */` . O código abaixo é um exemplo de uma task Gulp utilizando ngAnnotate @@ -1573,7 +1571,7 @@ ou *Tratamento de exceção* ou *decoradores* - Utilize um [decorator](https://docs.angularjs.org/api/auto/service/$provide#decorator), no seu config utilizando o serviço [`$provide`](https://docs.angularjs.org/api/auto/service/$provide), no serviço [`$exceptionHandler`](https://docs.angularjs.org/api/ng/service/$exceptionHandler) para realizar ações customizadas quando um erro ocorrer. - + **Por que?**: Fornece um caminho consistente para manipular erros não tratados pelo Angular em tempo de desenvolvimento ou execução (run-time). Nota: Outra opção é sobrescrever o serviço ao invés de utilizar um decorator. Esta é uma boa opção, mas se você quer manter o comportamento padrão e estender, o decorator é recomendado. @@ -1595,9 +1593,9 @@ ou *decoradores* function extendExceptionHandler($delegate, toastr) { return function(exception, cause) { $delegate(exception, cause); - var errorData = { - exception: exception, - cause: cause + var errorData = { + exception: exception, + cause: cause }; /** * Pode adicionar o erro para um serviço de coleções, @@ -1642,11 +1640,11 @@ ou *Coletores de exceção* ``` ### Route Errors - + - Gerencie e log todos os erros de routing utilizando o [`$routeChangeError`](https://docs.angularjs.org/api/ngRoute/service/$route#$routeChangeError). **Por que?**: Fornece uma maneira consistente de gerenciar erros relacionados a routing. - + **Por que?**: Potencialmente fornece uma melhor experiência de usuário se um erro de routing ocorrer e você redirecionar o usuário para uma tela amigável com mais detalhes ou opções de recuperação. ```javascript @@ -1686,7 +1684,7 @@ ou *Nomenclatura* **Por que?**: As convenções de nomenclatura ajudam a fornecer uma maneira consistente de encontrar algo à primeira vista. Consistência dentro do projeto é vital. Consistência dentro de um time é importante. Consistência em toda a empresa proporciona uma enorme eficiência. **Por que?**: As convenções de nomenclatura deveriam simplesmente te ajudar a encontrar trechos do seu código mais rápido e torná-lo mais fácil de se entender. - + ### Feature File Names ou *Nome para funcionalidades* @@ -1698,7 +1696,7 @@ ou *Nome para funcionalidades* ```javascript /** - * opções comuns + * opções comuns */ // Controllers @@ -1727,7 +1725,7 @@ ou *Nome para funcionalidades* // constants constants.js - + // module definition avengers.module.js @@ -1737,7 +1735,7 @@ ou *Nome para funcionalidades* // configuration avengers.config.js - + // directives avenger-profile.directive.js avenger-profile.directive.spec.js @@ -1758,7 +1756,7 @@ ou *Nome para funcionalidades* ou *Nome para aquivos de testes* - Nomeie as especificações de testes de forma similar aos componentes que elas testam, com o sufixo `spec`. - + **Por que?**: Fornece um modo consistente para identificar rapidamente os componentes. **Por que?**: Fornece padrões de correspondência para o [karma](http://karma-runner.github.io/) ou outros test runners. @@ -1777,7 +1775,7 @@ ou *Nome para aquivos de testes* ou *Nomes para controller* - Use nomes consistentes para todos os controllers nomeados após as sua funcionalidade. Use UpperCamelCase para os controllers, assim como para seus construtores. - + **Por que?**: Fornece um modo consistente para identificar e referenciar os controllers. **Por que?**: O UpperCamelCase é o modo mais comum para identificar objetos que serão instanciados através de construtores. @@ -1794,14 +1792,14 @@ ou *Nomes para controller* function HeroAvengers(){ } ``` - + ### Controller Name Suffix ou *sufixo "Controllers"* - - Complemente o nome do controller com ou sem o sufixo `Controller`. Escolha uma opção, não ambas. + - Complemente o nome do controller com ou sem o sufixo `Controller`. Escolha uma opção, não ambas. **Por que?**: O sufixo `Controller` é mais usado e mais descritivo. - + ```javascript /** * recomendado: Opção 1 @@ -1831,8 +1829,8 @@ ou *sufixo "Controllers"* ### Factory Names ou *Nomes para factory* - - Use nomes consistentes para todas as factories nomeadas após sua funcionalidade. Use a conveção camelCase para services e factories. Evite prefixos com `$`. - + - Use nomes consistentes para todas as factories nomeadas após sua funcionalidade. Use a conveção camelCase para services e factories. Evite prefixos com `$`. + **Por que?**: Fornece um modo consistente de identificar e referenciar rapidamente as factories. **Por que?**: Evite colisão de nomes com factories e services pré-programados que usam o prefixo `$`. @@ -1854,15 +1852,15 @@ ou *Nomes para factory* ou *Nomes para directive* - Use nomes consistentes para todas as directives usando a convenção camelCase. Use um prefixo curto para descrever a área a qual a directive pertence (como prefixo da compania ou do projeto). - + **Por que?**: Fornece um modo consistente de identificar e referenciar rapidamente os componentes. - + ```javascript /** * recomendado */ - // avenger.profile.directive.js + // avenger.profile.directive.js angular .module .directive('xxAvengerProfile', xxAvengerProfile); @@ -1884,7 +1882,7 @@ ou *Módulos* ### Configuration ou *Configuração* - - Separe a configuração do módulo em seu próprio arquivo, nomeado após o módulo. Um arquivo de configuração para o módulo principal `app` é nomeado `app.config.js` (ou simplesmente `config.js`). Uma configuração para o módulo `admin.module.js` é nomeada `admin.config.js`. + - Separe a configuração do módulo em seu próprio arquivo, nomeado após o módulo. Um arquivo de configuração para o módulo principal `app` é nomeado `app.config.js` (ou simplesmente `config.js`). Uma configuração para o módulo `admin.module.js` é nomeada `admin.config.js`. **Por que?**: Separa a configuração do módulo da definição, dos componentes e do código ativo. @@ -1907,7 +1905,7 @@ ou *Princípio da estrutura LIFT na aplicação* **Por que LIFT?**: Fornece uma estrutura consistente que escala bem, é modular, e torna mais fácil para aumentar a eficiência ao desenvolver, pois encontra-se o código rapidamente. Outra forma de verificar a estrutura da sua aplicação é se perguntar: Quão rápido é para você abrir e trabalhar em todos os arquivos relacionados com uma funcionalidade? Quando estou sentindo que não estou confortável com a minha estrutura, eu volto e revisito as regras do LIFT - + 1. `L`ocating (Localizar) nosso código é fácil 2. `I`dentify (Identificar) o código rapidamente 3. `F`lat (Plano) - Deixar a estrutura a mais plana que conseguirmos @@ -1999,33 +1997,33 @@ ou *Estrutura de Pastas-por-Recurso* app.module.js app.config.js app.routes.js - components/ - calendar.directive.js - calendar.directive.html - user-profile.directive.js - user-profile.directive.html + components/ + calendar.directive.js + calendar.directive.html + user-profile.directive.js + user-profile.directive.html layout/ - shell.html + shell.html shell.controller.js - topnav.html - topnav.controller.js + topnav.html + topnav.controller.js people/ attendees.html - attendees.controller.js + attendees.controller.js speakers.html speakers.controller.js speaker-detail.html speaker-detail.controller.js - services/ - data.service.js + services/ + data.service.js localstorage.service.js - logger.service.js + logger.service.js spinner.service.js sessions/ - sessions.html + sessions.html sessions.controller.js session-detail.html - session-detail.controller.js + session-detail.controller.js ``` ![Exemplo de estrutura na aplicação](https://raw.githubusercontent.com/johnpapa/angularjs-styleguide/master/assets/modularity-2.png) @@ -2033,49 +2031,49 @@ ou *Estrutura de Pastas-por-Recurso* Nota: Não estruture seu aplicativo usando pastas-por-tipo. Isto requer alternar entre várias pastas ao trabalhar em um recurso e fica difícil de manejar quando o aplicativo cresce rapidamente para 5, 10 ou 25+ views e controllers (e outros recursos), o que torna mais difícil do que pasta-por-recurso para localizar arquivos. ```javascript - /* + /* * evite * Alternativa pastas-por-tipo. * Eu recomendo "pastas-por-recurso". */ - + app/ app.module.js app.config.js app.routes.js controllers/ - attendees.js - session-detail.js - sessions.js - shell.js - speakers.js - speaker-detail.js - topnav.js - directives/ - calendar.directive.js - calendar.directive.html - user-profile.directive.js - user-profile.directive.html - services/ - dataservice.js + attendees.js + session-detail.js + sessions.js + shell.js + speakers.js + speaker-detail.js + topnav.js + directives/ + calendar.directive.js + calendar.directive.html + user-profile.directive.js + user-profile.directive.html + services/ + dataservice.js localstorage.js - logger.js + logger.js spinner.js views/ - attendees.html + attendees.html session-detail.html - sessions.html - shell.html - speakers.html + sessions.html + shell.html + speakers.html speaker-detail.html - topnav.html - ``` + topnav.html + ``` **[De volta ao topo](#tabela-de-conte%C3%BAdo)** ## Modularity ou *Modularidade* - + ### Many Small, Self Contained Modules ou *Muitos módulos pequenos e independentes* @@ -2222,7 +2220,7 @@ Testes unitários ajudam a manter o código limpo, tal como, eu inclui algumas r ### Análise de Código - - Execute JSHint no seus testes. + - Execute JSHint no seus testes. *Por que?*: Testes são códigos. JSHint ajuda a identificar problemas de qualidade de código que podem fazer com que o teste execute de maneira errada. @@ -2252,7 +2250,7 @@ Testes unitários ajudam a manter o código limpo, tal como, eu inclui algumas r ### Sub Second - - Use short durations for animations. I generally start with 300ms and adjust until appropriate. + - Use short durations for animations. I generally start with 300ms and adjust until appropriate. *Why?*: Long animations can have the reverse affect on User Experience and perceived performance by giving the appearance of a slow application. @@ -2306,7 +2304,7 @@ Testes unitários ajudam a manter o código limpo, tal como, eu inclui algumas r /** * @name logError * @desc Logs errors - * @param {String} msg Message to log + * @param {String} msg Message to log * @returns {String} * @memberOf Factories.Logger */ @@ -2405,7 +2403,7 @@ Testes unitários ajudam a manter o código limpo, tal como, eu inclui algumas r - Cria uma *Constant* no Angular para variáveis globais de bibliotecas de terceiros. - *Por que?*: Fornece uma forma de injetar bibliotecas de terceiros que de outra forma seriam globais. Isso melhora a testabilidade do código permitindo a você conhecer mais facilmente quais dependências os seus componentes têm (evita vazamento de abstrações). Também permite que você simule estas dependências, o que faz sentido. + *Por que?*: Fornece uma forma de injetar bibliotecas de terceiros que de outra forma seriam globais. Isso melhora a testabilidade do código permitindo a você conhecer mais facilmente quais dependências os seus componentes têm (evita vazamento de abstrações). Também permite que você simule estas dependências, o que faz sentido. ```javascript // constants.js @@ -2428,13 +2426,13 @@ Use file templates or snippets to help follow consistent styles and patterns. He ### Sublime Text - - Angular snippets that follow these styles and guidelines. + - Angular snippets that follow these styles and guidelines. - - Download the [Sublime Angular snippets](assets/sublime-angular-snippets.zip) + - Download the [Sublime Angular snippets](assets/sublime-angular-snippets.zip) - Place it in your Packages folder - - Restart Sublime + - Restart Sublime - In a JavaScript file type these commands followed by a `TAB` - + ```javascript ngcontroller // creates an Angular controller ngdirective // creates an Angular directive @@ -2454,7 +2452,7 @@ Use file templates or snippets to help follow consistent styles and patterns. He - Angular snippets and file templates that follow these styles and guidelines. You can import them into your WebStorm settings: - - Download the [WebStorm Angular file templates and snippets](assets/webstorm-angular-file-template.settings.jar) + - Download the [WebStorm Angular file templates and snippets](assets/webstorm-angular-file-template.settings.jar) - Open WebStorm and go to the `File` menu - Choose the `Import Settings` menu option - Select the file and click `OK` @@ -2478,7 +2476,7 @@ Open an issue first to discuss potential changes/additions. If you have question *By contributing to this repository you are agreeing to make your content available subject to the license of this repository.* ### Process - 1. Discuss the changes in an Issue. + 1. Discuss the changes in an Issue. 1. Open a Pull Request, reference the issue, and explain the change and why it adds value. 1. The Pull Request will be evaluated and either merged or declined. diff --git a/i18n/README.md b/i18n/README.md index 6a161c92..dfe00179 100644 --- a/i18n/README.md +++ b/i18n/README.md @@ -4,36 +4,37 @@ The [original English version](http://jpapa.me/ngstyles) is the source of truth, *All translations are created by and maintained by the community.* -1. [French](fr-FR.md) -2. [German](de-DE.md) -3. [Italian](it-IT.md) -4. [Japanese](ja-JP.md) -5. [Macedonian](mk-MK.md) -6. [Portuguese-Brazil](PT-BR.md) -7. [Russian](ru-RU.md) -8. [Simplified Chinese](zh-CN.md) -9. [Spanish](es-ES.md) + 1. [French](fr-FR.md) by [Eric Le Merdy](https://github.com/ericlemerdy) and [Xavier Haniquaut] (@xavhan) + 1. [German](de-DE.md) by [Michael Seeger](https://github.com/miseeger), [Sascha Hagedorn](https://github.com/saesh) and [Johannes Weber](https://github.com/johannes-weber) + 1. [Italian](it-IT.md) by [Angelo Chiello](https://github.com/angelochiello) + 1. [Japanese](ja-JP.md) by [@noritamago](https://github.com/noritamago) + 1. [Macedonian](mk-MK.md) by [Aleksandar Bogatinov](https://github.com/Bogatinov) + 1. [Portuguese-Brazil](PT-BR.md) by [Vinicius Sabadim Fernandes](https://github.com/vinicius-sabadim) + 1. [Russian](ru-RU.md) by [Vasiliy Mazhekin](https://github.com/mazhekin) + 1. [Simplified Chinese](zh-CN.md) by [Zhao Ke](https://github.com/natee) + 1. [Spanish](es-ES.md) by [Alberto Calleja](https://github.com/AlbertoImpl) and [Gilberto](https://github.com/ingilniero) + ## Contributing -Language translations are welcomed and encouraged. The success of these translations depends on the community. I highly encourage new translation contributions and help to keep them up to date. +Language translations are welcomed and encouraged. The success of these translations depends on the community. I highly encourage new translation contributions and help to keep them up to date. All translations must preserve the intention of the original document. > All contributions fall under the [MIT License of this repository](https://github.com/johnpapa/angularjs-styleguide#license). In other words, you would be providing these free to the community. -### New Translations +### New Translations 1. Fork the repository 2. Create a translation file and name it using the 118n standard format. 3. Put this file in the i18n folder 4. Translate the original English version to be current with the latest changes -3. Make a Pull Request +3. Make a Pull Request Once you do these I will merge, point the translation links to it, and enter the translation credit to you. -### Updated Translations +### Updated Translations 1. Fork the repository 2. Make the translation changes -3. Make a Pull Request +3. Make a Pull Request Once you do these I will merge, point the translation links to it, and enter the translation credit to you. diff --git a/i18n/de-DE.md b/i18n/de-DE.md index eb60d867..3af8f1b7 100644 --- a/i18n/de-DE.md +++ b/i18n/de-DE.md @@ -2,10 +2,6 @@ *Dogmatischer Angular Styleguide für Teams von John Papa [@john_papa](//twitter.com/john_papa)* -*Translated by [miseeger](https://github.com/miseeger)* - ->The [original English version](http://jpapa.me/ngstyles) is the source of truth, as it is maintained and updated first. - Sind Sie auf der Suche nach einem dogmatischen Styleguide zur Syntax, zu Konventionen und zur Struktur von Angular-Anwendungen, dann treten Sie näher. Diese Vorlagen basieren auf meinen Erfahrungen mit [Angular](//angularjs.org), Präsentationen, [Pluralsight Trainingskursen](http://pluralsight.com/training/Authors/Details/john-papa) und der Arbeit in Teams. Der Zweck dieses Styleguides ist es, eine Anleitung für die Erstellung von Angular-Anwendungen bereitzustellen, indem ich die Konventionen, die ich nutze, zeige und - wichtiger als das - beschreibe, warum ich sie wähle. @@ -121,10 +117,10 @@ Während diese Anleitung das *Was*, *Warum* und *Wie* erklärt, finde ich es ebe - Packen Sie Angular-Komponenten in eine Funktion, die sich sofort selbst ausführt (Immediately Invoked Function Expression, kurz: IIFE). - *Warum?*: Eine IIFE entfernt Variablen aus dem global scope. Dies verhindert, dass Variablen- und Funktionsdeklarationen länger als erwartet im global scope bleiben. Und es verhindert zusätzlich, Kollisionen bei Variablen zu verhindern. - - *Warum?*: Wird Ihr Code für das Deployment auf einem Produktionsserver minifiziert und in einer einzigen Datei zusammengepackt, kann es zur Kollision von Variablen (auch globalen) kommen. Eine IIFE schützt Sie hiervor, indem sie den Gültigkeitsbereich der Variablen auf die jeweilige Datei beschränkt. - + *Warum?*: Eine IIFE entfernt Variablen aus dem global scope. Dies verhindert, dass Variablen- und Funktionsdeklarationen länger als erwartet im global scope bleiben. Und es verhindert zusätzlich, Kollisionen bei Variablen zu verhindern. + + *Warum?*: Wird Ihr Code für das Deployment auf einem Produktionsserver minifiziert und in einer einzigen Datei zusammengepackt, kann es zur Kollision von Variablen (auch globalen) kommen. Eine IIFE schützt Sie hiervor, indem sie den Gültigkeitsbereich der Variablen auf die jeweilige Datei beschränkt. + ```javascript /* zu vermeiden */ // logger.js @@ -187,7 +183,7 @@ Während diese Anleitung das *Was*, *Warum* und *Wie* erklärt, finde ich es ebe - Benutzen Sie eindeutige Namenskonventionen mit Trennzeichen für Untermodule. - *Warum?*: Eindeutige Namen helfen Kollisionen bei Modulnamen zu verhindern. Trennzeichen helfen bei der Definition von Modulen und deren Untermodul-Hierarchie. Zum Beispiel kann `app` Ihr Root-Modul sein, während `app.dashboard` und `app.users` Module sein können, die von `app` als Abhängigkeiten genutzt werden. + *Warum?*: Eindeutige Namen helfen Kollisionen bei Modulnamen zu verhindern. Trennzeichen helfen bei der Definition von Modulen und deren Untermodul-Hierarchie. Zum Beispiel kann `app` Ihr Root-Modul sein, während `app.dashboard` und `app.users` Module sein können, die von `app` als Abhängigkeiten genutzt werden. ### Definitionen (auch: Setter) ###### [Style [Y021](#style-y021)] @@ -622,7 +618,7 @@ Während diese Anleitung das *Was*, *Warum* und *Wie* erklärt, finde ich es ebe - Definieren Sie einen Controller für einen View und versuchen Sie nicht, diesen Controller für weitere Views zu verwenden. Verlagern Sie stattdessen wiederzuverwendende Logik in Factories und halten Sie den Controller einfach und ausgerichtet auf seinen View. - *Warum?*: Controller in mehreren Views wiederzuverwenden ist kritisch und bedingt eine gute End-Zu-End (e2e) Testabdeckung, um die Stabilität in großen Anwendungen zu garantieren. + *Warum?*: Controller in mehreren Views wiederzuverwenden ist kritisch und bedingt eine gute End-Zu-End (e2e) Testabdeckung, um die Stabilität in großen Anwendungen zu garantieren. ### Controller zuweisen @@ -802,7 +798,7 @@ Während diese Anleitung das *Was*, *Warum* und *Wie* erklärt, finde ich es ebe *Warum?*: Das Platzieren der Implementierungsdetails einer Funktion weiter unten in der Datei, hält diese Codemenge außer Sicht und Sie sehen die wichtigen Dinge am Anfang. *Warum?*: Funktionsdeklarationen werden "nach oben gezogen" (sog. Hoisting), so dass es keine Probleme damit gibt, ob eine Funktion vor ihrer Benutzung deklariert werden sollte (wie es bei Funktionsausdrücken der Fall wäre). - + *Warum?*: Sie müssen sich niemals Sorgen darum machen, wenn Sie in Funktionsdeklarationen `var a` vor `var b` platzieren, weil `a` von `b` abhängig ist. *Warum?*: Die Reihenfolge ist kritisch in Funktionsausdrücken. @@ -974,7 +970,7 @@ Während diese Anleitung das *Was*, *Warum* und *Wie* erklärt, finde ich es ebe - Wenn Sie einen Datenservice ansprechen, der einen Promise wie `$http` zurückliefert, so liefern Sie in Ihrer aufrufenden Funktion ebenso einen Promise zurück. - *Warum?*: Sie können die Promises aneinanderhängen und weitere Aktionen ausführen, wenn der Datenabruf beendet ist und den Promise im Erfolgsfall entweder auflöst oder bei Fehlschlagen zurückweist. + *Warum?*: Sie können die Promises aneinanderhängen und weitere Aktionen ausführen, wenn der Datenabruf beendet ist und den Promise im Erfolgsfall entweder auflöst oder bei Fehlschlagen zurückweist. ```javascript /* empfohlen */ @@ -984,7 +980,7 @@ Während diese Anleitung das *Was*, *Warum* und *Wie* erklärt, finde ich es ebe function activate() { /** * Schritt 1 - * Bei der getAvengers Funktion nach den Avenger-Daten + * Bei der getAvengers Funktion nach den Avenger-Daten * fragen und auf den Promise warten */ return getAvengers().then(function() { @@ -999,7 +995,7 @@ Während diese Anleitung das *Was*, *Warum* und *Wie* erklärt, finde ich es ebe function getAvengers() { /** * Schritt 2 - * Beim Datenservice nach den Daten fragen und + * Beim Datenservice nach den Daten fragen und * auf den Promise warten */ return dataservice.getAvengers() @@ -1022,7 +1018,7 @@ Während diese Anleitung das *Was*, *Warum* und *Wie* erklärt, finde ich es ebe - Erstellen Sie eine Direktive pro Datei. Benennen Sie die Datei nach der Direktive. - *Warum?*: Es ist einfach, alle Direktiven in einer Datei zu halten, aber schwer, sie dann wieder herauszulösen sodass sie zwischen Anwendungen oder Modulen ausgetauscht werden können oder einfach nur in einem Modulzu genutzt werden. + *Warum?*: Es ist einfach, alle Direktiven in einer Datei zu halten, aber schwer, sie dann wieder herauszulösen sodass sie zwischen Anwendungen oder Modulen ausgetauscht werden können oder einfach nur in einem Modulzu genutzt werden. *Warum?*: Eine Direktive pro Datei ist einfach zu warten. @@ -1062,7 +1058,7 @@ Während diese Anleitung das *Was*, *Warum* und *Wie* erklärt, finde ich es ebe /* calendarRange.directive.js */ /** - * @desc Bestell-Direktive, die speziell für das Bestell-Modul der Firma Acme bestimmt ist. + * @desc Bestell-Direktive, die speziell für das Bestell-Modul der Firma Acme bestimmt ist. * @example
*/ angular @@ -1426,7 +1422,7 @@ Während diese Anleitung das *Was*, *Warum* und *Wie* erklärt, finde ich es ebe } ``` - Anmerkung: Das untenstehende Beispiel zeigt die Stellen, an denen die Route mit einer benannten Funktion aufgelöst wird. Das ist einfacher zu debuggen und vereinfacht auch die Handhabung von Dependency Injection. + Anmerkung: Das untenstehende Beispiel zeigt die Stellen, an denen die Route mit einer benannten Funktion aufgelöst wird. Das ist einfacher zu debuggen und vereinfacht auch die Handhabung von Dependency Injection. ```javascript /* noch besser */ @@ -1472,7 +1468,7 @@ Während diese Anleitung das *Was*, *Warum* und *Wie* erklärt, finde ich es ebe ### Unsichere Minifizierung ###### [Style [Y090](#style-y090)] - - Vermeiden Sie es, die kurze Deklarationssyntax für Abhängigkeiten ohne einen für die Minifizierung sicheren Ansatz zu verwenden. + - Vermeiden Sie es, die kurze Deklarationssyntax für Abhängigkeiten ohne einen für die Minifizierung sicheren Ansatz zu verwenden. *Warum?*: Die Parameter der Komponente (z. B. Controller, Factory, etc.) werden in abgekürzte Variablen gewandelt. So kann zum Beispiel aus `common` und `dataservice` ein `a` oder `b` werden, was von Angular nicht gefunden wird. @@ -1607,7 +1603,7 @@ Während diese Anleitung das *Was*, *Warum* und *Wie* erklärt, finde ich es ebe ### ng-annotate ###### [Style [Y100](#style-y100)] - - Benutzen Sie [ng-annotate](//github.com/olov/ng-annotate) für [Gulp](http://gulpjs.com) oder [Grunt](http://gruntjs.com) und versehen Sie die Funktionen mit den notwendigen `/** @ngInject */`-Kommentaren, die für die "automatische" Dependency Injection genutzt werden sollen. + - Benutzen Sie [ng-annotate](//github.com/olov/ng-annotate) für [Gulp](http://gulpjs.com) oder [Grunt](http://gruntjs.com) und versehen Sie die Funktionen mit den notwendigen `/** @ngInject */`-Kommentaren, die für die "automatische" Dependency Injection genutzt werden sollen. *Warum?*: Dies schützt Ihren Code vor Abhängigkeiten, die keiner minifizierungssicheren Technik entsprechen. @@ -1748,9 +1744,9 @@ Während diese Anleitung das *Was*, *Warum* und *Wie* erklärt, finde ich es ebe }; /** * Der Fehler könnte zu einer Liste im Service oder - * zum $rootScope hinzugefügt werden oder bei einem - * Remote-Webserver oder lokal protokolliert oder - * einfach wieder hart "geworfen" werden. Es obliegt + * zum $rootScope hinzugefügt werden oder bei einem + * Remote-Webserver oder lokal protokolliert oder + * einfach wieder hart "geworfen" werden. Es obliegt * ganz Ihnen. * * throw exception; @@ -1844,7 +1840,7 @@ Während diese Anleitung das *Was*, *Warum* und *Wie* erklärt, finde ich es ebe ### Richtlinien der Namensgebung ###### [Style [Y120](#style-y120)] - - Benutzen Sie stimmige Namen für alle Komponenten, einem Muster folgend, welches die Hauptfunktionen (Features) einer Komponente und dann (optional) ihren Typ beschreibt. + - Benutzen Sie stimmige Namen für alle Komponenten, einem Muster folgend, welches die Hauptfunktionen (Features) einer Komponente und dann (optional) ihren Typ beschreibt. Meine empfohlenes Muster ist `feature.typ.js`. Es gibt zwei zu vergebene Namen für die meisten Komponenten: * der Dateiname (`avengers.controller.js`) * der Name der bei Angular zu registrierenden Komponente (`AvengersController`) @@ -2054,7 +2050,7 @@ Während diese Anleitung das *Was*, *Warum* und *Wie* erklärt, finde ich es ebe ### LIFT ###### [Style [Y140](#style-y140)] - - LIFT steht für `L`ocate (auffinden), `I`dentify (identifizieren), `F`lat (flach), T`ry to stay DRY` (versuchen Sie, Ihren Code nicht zu wiederholen). Das bedeutet also, Sie sollten Ihre Anwendung so strukturieren, dass Sie Ihren Code schnell auffinden und auf einen Blick identifizieren können, für was der Code gut ist. Dabei sollten Sie die Struktur so flach wie möglich halten. Vermeiden Sie es unbedingt, Ihren Code zu wiederholen. + - LIFT steht für `L`ocate (auffinden), `I`dentify (identifizieren), `F`lat (flach), T`ry to stay DRY` (versuchen Sie, Ihren Code nicht zu wiederholen). Das bedeutet also, Sie sollten Ihre Anwendung so strukturieren, dass Sie Ihren Code schnell auffinden und auf einen Blick identifizieren können, für was der Code gut ist. Dabei sollten Sie die Struktur so flach wie möglich halten. Vermeiden Sie es unbedingt, Ihren Code zu wiederholen. *Warum LIFT?*: Bietet eine konsistente und gut skalierbare Struktur, ist modular und macht es einfacher die Effizienz eines Entwicklers zu steigern, weil er seinen Code schneller finden kann. Prüfen Sie Ihre Anwendungsstruktur, indem Sie sich fragen: Wie schnell kann ich all die Dateien, die zu einem Feature gehören öffnen und mit ihnen arbeiten?" @@ -2095,7 +2091,7 @@ Während diese Anleitung das *Was*, *Warum* und *Wie* erklärt, finde ich es ebe - Wenn Sie einen Dateinamen sehen, sollten Sie sofort wissen, was die Datei beinhaltet und für was sie steht. - *Warum?*: Sie brauchen weniger Zeit, um nach Ihrem Code zu suchen und werden so effizienter. Wenn das bedeutet, dass Sie längere Dateinamen brauchen, dann sei es so. Seien Sie beschreibend bei der Namensvergabe und sorgen Sie dafür, dass eine Datei nur eine Komponente enthält. Vermeiden Sie Dateien mir mehreren Controllern, Services oder gar mit beidem. Ich weiche von dieser Regel ab, wenn ich sehr kleine Features habe, die alle miteinander verbunden und leicht identifizierbar sind. + *Warum?*: Sie brauchen weniger Zeit, um nach Ihrem Code zu suchen und werden so effizienter. Wenn das bedeutet, dass Sie längere Dateinamen brauchen, dann sei es so. Seien Sie beschreibend bei der Namensvergabe und sorgen Sie dafür, dass eine Datei nur eine Komponente enthält. Vermeiden Sie Dateien mir mehreren Controllern, Services oder gar mit beidem. Ich weiche von dieser Regel ab, wenn ich sehr kleine Features habe, die alle miteinander verbunden und leicht identifizierbar sind. ### Flat (flache Struktur) ###### [Style [Y143](#style-y143)] @@ -2769,8 +2765,8 @@ Unit-Tests tragen dazu bei, sauberen Code zu erhalten. Daher habe ich einige mei - Benutzen Sie Konstanten für Werte, die sich nicht ändern und nicht aus einem anderen Service kommen. Wenn Konstanten nur für ein bestimmtes Modul gebraucht werden, welches zudem wiederverwendbar sein soll, dann platzieren Sie die Konstanten in einer Datei (pro Modul) und benennen Sie die Datei nach dem Modul. Bis dahin halten Sie die Konstanten im Hauptmodul in einer `constants.js`-Datei. - *Warum?*: Ein Wert, der sich ändert - wenn auch nur unregelmäßig - sollte von einem Service ermittelt werden, so dass er nicht im Quellcode geändert werden muss. Zum Beispiel könnte eine URL für einen Datenservice in einer Konstanten abgelegt werden. Besser wäre es aber, diesen Wert über einen WebService zu ermitteln. - + *Warum?*: Ein Wert, der sich ändert - wenn auch nur unregelmäßig - sollte von einem Service ermittelt werden, so dass er nicht im Quellcode geändert werden muss. Zum Beispiel könnte eine URL für einen Datenservice in einer Konstanten abgelegt werden. Besser wäre es aber, diesen Wert über einen WebService zu ermitteln. + *Warum?*: Konstanten können in jede Angular-Komponente (auch in einen Provider) eingefügt werden. *Warum?*: Ist eine Anwendung in Module unterteilt, die in anderen Anwendungen genutzt werden können, so sollte jedes alleinstehende Modul für sich selbst funktionieren, eingeschlossen seiner Konstanten. @@ -3051,7 +3047,7 @@ Nutzen Sie [Gulp](http://gulpjs.com) oder [Grunt](http://gruntjs.com), um Aufgab ```javascript var clientApp = './src/client/app/'; - // Immer zuerst die Moduldateien + // Immer zuerst die Moduldateien var files = [ clientApp + '**/*.module.js', clientApp + '**/*.js' diff --git a/i18n/es-ES.md b/i18n/es-ES.md index 2edc626b..b47fd693 100644 --- a/i18n/es-ES.md +++ b/i18n/es-ES.md @@ -2,10 +2,6 @@ *Guía de estilos colaborativa de Angular para equipos por [@john_papa](//twitter.com/john_papa)* -*Translation by [Alberto Calleja](https://github.com/AlbertoImpl) and [Gilberto](https://github.com/ingilniero)* - ->The [original English version](http://jpapa.me/ngstyles) is the source of truth, as it is maintained and updated first. - Si estás buscando una guía colaborativa sobre sintaxis, convenciones y estructura de aplicaciones con AngulRJS, este es el sitio. Estos estilos están basados en mi experiencia desarrollando con [AngularJS](//angularjs.org), persentaciones, [Cursos en Pluralsight](http://pluralsight.com/training/Authors/Details/john-papa) y trabajando en equipos. El propósito de esta guía de estilos es proporcionar una guía de cómo construir aplicaciones con Angular enseñando convenciones que uso y, lo más importante, el porqué. diff --git a/i18n/fr-FR.md b/i18n/fr-FR.md index 3a555ca9..1093d36e 100644 --- a/i18n/fr-FR.md +++ b/i18n/fr-FR.md @@ -2,8 +2,6 @@ *Guide de style par subjectif pour Angular par [@john_papa](//twitter.com/john_papa)* -*Traduit par [Eric Lemerdy](https://github.com/ericlemerdy) et [Xavier Haniquaut](https://github.com/xavhan)* - Si vous cherchez un guide de style pour la syntaxe, les conventions, et la structuration d'applications Angular, alors vous êtes au bon endroit. Ces styles sont basés sur mon expérience de développement avec [Angular](//angularjs.org), mes présentations, [mes cours sur Pluralsight](http://pluralsight.com/training/Authors/Details/john-papa) et mon travail au sein de diverses équipes. Le but de ce guide de style est de proposer des conseils sur le développement d'applications Angular en exposant les conventions que j'utilise et plus important encore, pourquoi je les ai choisies. diff --git a/i18n/it-IT.md b/i18n/it-IT.md index 0a9558c8..f2910846 100644 --- a/i18n/it-IT.md +++ b/i18n/it-IT.md @@ -2,11 +2,7 @@ *Guida stilistica dogmatica ad Angular per i team di [@john_papa](//twitter.com/john_papa)* -*Traduzione di [Angelo Chiello](https://github.com/angelochiello)* - ->The [original English version](http://jpapa.me/ngstyles) is the source of truth, as it is maintained and updated first. - -Se stai cercando una guida stilistica dogmatica per le sintassi, convenzioni e struttura di applicazioni AngularJS, allora questo fa per te. Gli stili sono basati sulla mia esperienza di sviluppo con [AngularJS](//angularjs.org), presentazioni, [corsi di formazioni di Pluralsight](http://pluralsight.com/training/Authors/Details/john-papa) e del lavoro in team. +Se stai cercando una guida stilistica dogmatica per le sintassi, convenzioni e struttura di applicazioni AngularJS, allora questo fa per te. Gli stili sono basati sulla mia esperienza di sviluppo con [AngularJS](//angularjs.org), presentazioni, [corsi di formazioni di Pluralsight](http://pluralsight.com/training/Authors/Details/john-papa) e del lavoro in team. L'obbiettivo di questa guida stilistica è di fare da vademecum alla costruzione di applicazioni con Angular mostrando le convenzioni che uso e, più importante, perché le uso. @@ -22,7 +18,7 @@ Molti dei mie stili sono frutto di parecchie sessioni di pair programming che [W ## Guarda gli stili in una App di Esempio Nonostante questa guida spieghi i *cosa*, *come* e *perché*, trovo che sia di aiuto vederle in pratica. Questa guida è accompagnata da una applicazione di esempio che segue questi stili e schemi. Puoi trovare l'[applicazione di esempio (chiamata modular) qui](https://github.com/johnpapa/ng-demos) nella cartella `modular`. Prendila, clonala o fanne un fork liberamente. [Le istruzioni su come eseguirla sono nel proprio readme](https://github.com/johnpapa/ng-demos/tree/master/modular). -##Traduzioni +##Traduzioni [Traduzioni di questa guida stilistica ad Angular](https://github.com/johnpapa/angularjs-styleguide/tree/master/i18n) sono gestite dalla comunità e possono essere trovate qui. ## Tavola dei contenuti @@ -46,7 +42,7 @@ Nonostante questa guida spieghi i *cosa*, *come* e *perché*, trovo che sia di a 1. [Logica di Startup](#logica-di-startup) 1. [Wrapper dei Servizi $ di Angular](#wrapper-dei-servizi--di-angular) 1. [Test](#test) - 1. [Animazioni](#animazioni) + 1. [Animazioni](#animazioni) 1. [Commenti](#commenti) 1. [JSHint](#jshint) 1. [JSCS](#jscs) @@ -65,7 +61,7 @@ Nonostante questa guida spieghi i *cosa*, *come* e *perché*, trovo che sia di a ### Regola dell'1 ###### [Stile [Y001](#stile-y001)] - - Definire 1 componente per file. + - Definire 1 componente per file. Il seguente esempio definisce il modulo `app` e le proprie dipendenze, definisce un controller e definisce una factory tutto nel medesimo file. @@ -75,7 +71,7 @@ Nonostante questa guida spieghi i *cosa*, *come* e *perché*, trovo che sia di a .module('app', ['ngRoute']) .controller('SomeController', SomeController) .factory('someFactory', someFactory); - + function SomeController() { } function someFactory() { } @@ -85,7 +81,7 @@ Nonostante questa guida spieghi i *cosa*, *come* e *perché*, trovo che sia di a ```javascript /* consigliato */ - + // app.module.js angular .module('app', ['ngRoute']); @@ -93,7 +89,7 @@ Nonostante questa guida spieghi i *cosa*, *come* e *perché*, trovo che sia di a ```javascript /* consigliato */ - + // someController.js angular .module('app') @@ -104,12 +100,12 @@ Nonostante questa guida spieghi i *cosa*, *come* e *perché*, trovo che sia di a ```javascript /* consigliato */ - + // someFactory.js angular .module('app') .factory('someFactory', someFactory); - + function someFactory() { } ``` @@ -119,8 +115,8 @@ Nonostante questa guida spieghi i *cosa*, *come* e *perché*, trovo che sia di a ### Closures di JavaScript ###### [Stile [Y010](#stile-y010)] - - Racchiudi i componenti di Angular in una Immediately Invoked Function Expression (IIFE) (Espressione di funzione immediatamente chiamata). - + - Racchiudi i componenti di Angular in una Immediately Invoked Function Expression (IIFE) (Espressione di funzione immediatamente chiamata). + *Perché?*: Una IIFE rimuove le variabili dallo scope globale. Questo aiuta a prevenire che variabili e dichiarazioni di funzione vivano più del previsto nello scope globale, inoltre aiuta ad evitare la collisione di variabili. *Perché?*: Quando il tuo codice è minificato e raggruppato in un file singolo per il rilascio ad un server di produzione, potresti avere collisioni di variabili e parecchie variabili globali. Una IIFE ti protegge in entrambi i casi fornendo uno scope variabile per ogni file. @@ -131,7 +127,7 @@ Nonostante questa guida spieghi i *cosa*, *come* e *perché*, trovo che sia di a .module('app') .factory('logger', logger); - // La funzione logger è aggiunta come variabile globale + // La funzione logger è aggiunta come variabile globale function logger() { } // storage.js @@ -139,22 +135,22 @@ Nonostante questa guida spieghi i *cosa*, *come* e *perché*, trovo che sia di a .module('app') .factory('storage', storage); - // La funzione storage è aggiunta come variabile globale + // La funzione storage è aggiunta come variabile globale function storage() { } ``` - + ```javascript /** - * consigliato + * consigliato * - * non ci sono più variabili globali + * non ci sono più variabili globali */ // logger.js (function() { 'use strict'; - + angular .module('app') .factory('logger', logger); @@ -174,8 +170,8 @@ Nonostante questa guida spieghi i *cosa*, *come* e *perché*, trovo che sia di a })(); ``` - - Nota: Per essere più coincisi, il resto degli esempi in questa guida potrebbe omettere l'uso della sintassi IIFE. - + - Nota: Per essere più coincisi, il resto degli esempi in questa guida potrebbe omettere l'uso della sintassi IIFE. + - Nota: Le IIFE evitano che il codice di test possa raggiungere membri privati come regular expression o funzioni di supporto le quali sono spesso oggetto di propri unit test. In ogni caso, queste possono essere testate per mezzo di membri accessibili o attraverso l'esposizione di propri componenti. Per esempio ponendo funzioni di supporto, regular expression o costanti nelle proprie factory o costanti. **[Torna all'inizio](#tavola-dei-contenuti)** @@ -185,9 +181,9 @@ Nonostante questa guida spieghi i *cosa*, *come* e *perché*, trovo che sia di a ### Evitare la collisione di nomi ###### [Stile [Y020](#stile-y020)] - - Usa una convenzione unica per i nomi con separatori per sotto moduli. + - Usa una convenzione unica per i nomi con separatori per sotto moduli. - *Perché?*: Nomi unici aiutano ad evitare la collisione di nomi dei moduli. I separatori aiutano a definire gerarchie di moduli e dei propri sotto moduli. Per esempio `app` potrebbe essere il modulo principale mentre `app.dashboard` e `app.users` potrebbero essere moduli che sono usati come dipendenze di `app`. + *Perché?*: Nomi unici aiutano ad evitare la collisione di nomi dei moduli. I separatori aiutano a definire gerarchie di moduli e dei propri sotto moduli. Per esempio `app` potrebbe essere il modulo principale mentre `app.dashboard` e `app.users` potrebbero essere moduli che sono usati come dipendenze di `app`. ### Definizioni (altrimenti noti come Setter) ###### [Stile [Y021](#stile-y021)] @@ -195,7 +191,7 @@ Nonostante questa guida spieghi i *cosa*, *come* e *perché*, trovo che sia di a - Dichiara moduli senza una variabile usando la sintassi setter. *Perché?*: con 1 componente per file, raramente c'è la necessità di introdurre una variabile per il modulo. - + ```javascript /* evitare */ var app = angular.module('app', [ @@ -230,7 +226,7 @@ Invece usa la più semplice sintassi setter. /* evitare */ var app = angular.module('app'); app.controller('SomeController', SomeController); - + function SomeController() { } ``` @@ -239,7 +235,7 @@ Invece usa la più semplice sintassi setter. angular .module('app') .controller('SomeController', SomeController); - + function SomeController() { } ``` @@ -247,7 +243,7 @@ Invece usa la più semplice sintassi setter. ###### [Stile [Y023](#stile-y023)] - Setta solo una volta e prendi (get) per tutte le altre istanze. - + *Perché?*: Un modulo dovrebbe essere creato solamente una volta, quindi recuperato da lì in avanti. ```javascript @@ -302,9 +298,9 @@ Invece usa la più semplice sintassi setter. ### Sintassi controllerAs nella View ###### [Stile [Y030](#stile-y030)] - - Usa la sintassi [`controllerAs`](http://www.johnpapa.net/do-you-like-your-angular-controllers-with-or-without-sugar/) al posto della sintassi `classico controller con $scope`. + - Usa la sintassi [`controllerAs`](http://www.johnpapa.net/do-you-like-your-angular-controllers-with-or-without-sugar/) al posto della sintassi `classico controller con $scope`. - *Perché?*: I controller sono costruiti, creati con "new" e forniti con un nuova istanza singola, inoltre la sintassi `controllerAs` è più somigliante ad un costruttore JavaScript rispetto alla `sintassi classica con $scope`. + *Perché?*: I controller sono costruiti, creati con "new" e forniti con un nuova istanza singola, inoltre la sintassi `controllerAs` è più somigliante ad un costruttore JavaScript rispetto alla `sintassi classica con $scope`. *Perché?*: Promuove l'uso del binding ad un oggetto che "usa il punto" nella View (p.e. `customer.name` invece di `name`), il quale è più contestuale, più facile da leggere ed evita qualunque questione di riferimenti che potrebbe accadere senza "uso del punto". @@ -327,13 +323,13 @@ Invece usa la più semplice sintassi setter. ### Sintassi controllerAs nel Controller ###### [Stile [Y031](#stile-y031)] - - Usa la sintassi `controllerAs` al posto della sintassi `classico controller con $scope`. + - Usa la sintassi `controllerAs` al posto della sintassi `classico controller con $scope`. - La sintassi `controllerAs` usa `this` all'interno dei controller che fanno uso di `$scope` - *Perché?*: `controllerAs` è una semplificazione sintattica per `$scope`. Puoi ancora fare il binding con la View ed accedere ai metodi di `$scope`. + *Perché?*: `controllerAs` è una semplificazione sintattica per `$scope`. Puoi ancora fare il binding con la View ed accedere ai metodi di `$scope`. - *Perché?*: Aiuta ad evitare la tentazione ad usare i metodi di `$scope` dentro un controller quando sarebbe meglio evitare o spostarli in una factory. Considera l'uso di `$scope` in una factory o, se in un controller, soltanto quando necessario. Per esempio, quando si pubblicano o sottoscrivono eventi usando [`$emit`](https://docs.angularjs.org/api/ng/type/$rootScope.Scope#$emit), [`$broadcast`](https://docs.angularjs.org/api/ng/type/$rootScope.Scope#$broadcast), o [`$on`](https://docs.angularjs.org/api/ng/type/$rootScope.Scope#$on) considera di spostare questi tipi di utilizzi in una facotry e di invocarli da un controller. + *Perché?*: Aiuta ad evitare la tentazione ad usare i metodi di `$scope` dentro un controller quando sarebbe meglio evitare o spostarli in una factory. Considera l'uso di `$scope` in una factory o, se in un controller, soltanto quando necessario. Per esempio, quando si pubblicano o sottoscrivono eventi usando [`$emit`](https://docs.angularjs.org/api/ng/type/$rootScope.Scope#$emit), [`$broadcast`](https://docs.angularjs.org/api/ng/type/$rootScope.Scope#$broadcast), o [`$on`](https://docs.angularjs.org/api/ng/type/$rootScope.Scope#$on) considera di spostare questi tipi di utilizzi in una facotry e di invocarli da un controller. ```javascript /* evitare */ @@ -355,7 +351,7 @@ Invece usa la più semplice sintassi setter. ###### [Stile [Y032](#stile-y032)] - Usa una variabile che "catturi" `this` quando si utilizza la sintassi `controllerAs`. Scegli un nome della variabile consistente come `vm`, che sta per ViewModel. - + *Perché?*: La keyword `this` è contestuale e quando usata all'interno di una funzione dentro un controller può cambiare il proprio contesto. Catturare il contesto di `this` evita di incorrere in questo problema. ```javascript @@ -381,18 +377,18 @@ Invece usa la più semplice sintassi setter. /* jshint validthis: true */ var vm = this; ``` - + Nota: Quando di creano watch in un controller usando `controller as`, puoi fare il watch del membro `vm.*` usando la seguente sintassi. (Crea watch con cautela poiché aggiungono più carico al ciclo di digest.) ```html ``` - + ```javascript function SomeController($scope, $log) { var vm = this; vm.title = 'Some Title'; - + $scope.$watch('vm.title', function(current, original) { $log.info('vm.title was %s', original); $log.info('vm.title is now %s', current); @@ -404,10 +400,10 @@ Invece usa la più semplice sintassi setter. ###### [Stile [Y033](#stile-y033)] - Poni i membri che possono fare il bind in alto nel controller, in ordine alfabetico, piuttosto che dispersi in tutto il codice del controller. - + *Perché?*: Porre i membri che posso fare il bind in alto rende semplice la lettura e aiuta l'istantanea identificazione di quali membri del controller possono essere collegati ed usati in una View. - *Perché?*: Settare funzioni anonime nella medesima linea è semplice, tuttavia quando queste funzioni sono più lunghe di 1 linea di codice possono ridurre la leggibilità. Definire le funzione al di sotto i membri che possono fare il bind (funzioni che saranno chiamate) spostano i dettagli di implementazione in basso, tengono i membri che possono fare il bind in alto e rendono il codice più facile da leggere. + *Perché?*: Settare funzioni anonime nella medesima linea è semplice, tuttavia quando queste funzioni sono più lunghe di 1 linea di codice possono ridurre la leggibilità. Definire le funzione al di sotto i membri che possono fare il bind (funzioni che saranno chiamate) spostano i dettagli di implementazione in basso, tengono i membri che possono fare il bind in alto e rendono il codice più facile da leggere. ```javascript /* evitare */ @@ -464,8 +460,8 @@ Invece usa la più semplice sintassi setter. vm.gotoSession = gotoSession; vm.refresh = function() { - /** - * linee + /** + * linee * di * codice * che peggiorano @@ -493,20 +489,20 @@ Invece usa la più semplice sintassi setter. ###### [Stile [Y034](#stile-y034)] - Usa le dichiarazioni di funzione per nascondere i dettagli di implementazione. Tieni i membri che possono fare il binding in alto. Quando necessiti di fare binding a una funzione nel controller, puntalo ad una dichiarazione di funzione che compaia dopo nel file. Questo è direttamente collegabile con la sezione Membri che possono fare il bind posti in alto. Per ulteriori dettagli guarda [questo post](http://www.johnpapa.net/angular-function-declarations-function-expressions-and-readable-code) (in inglese). - + *Perché?*: Porre i membri che possono fare il binding in alto rende semplice la lettura ed aiuta l'immediata identificazione dei membri del controller che possono fare il binding ed usati nella View. (Come sopra.) *Perché?*: Porre i dettagli di implementazione di una funzione in seguito nel file sposta la complessità fuori dalla vista così che puoi vedere le cose importanti in alto. *Perché?*: Dichiarazioni di funzioni che sono chiamate così che non c'è rischio dell'uso di una funzione prima che sia definita (come sarebbe in caso di espressioni di funzione). - *Perché?*: Non ti devi preoccupare di dichiarazioni di funzione che sposta `var a` prima di `var b` romperà il codice perché `a` dipende da `b`. + *Perché?*: Non ti devi preoccupare di dichiarazioni di funzione che sposta `var a` prima di `var b` romperà il codice perché `a` dipende da `b`. - *Perché?*: Con le espressioni di funzione l'ordine è critico. + *Perché?*: Con le espressioni di funzione l'ordine è critico. ```javascript - /** - * evitare + /** + * evitare * Uso di espressioni di funzione. */ function Avengers(avengersService, logger) { @@ -615,7 +611,7 @@ Invece usa la più semplice sintassi setter. vm.isCreditOk; vm.total = 0; - function checkCredit() { + function checkCredit() { return creditService.isOrderTotalOk(vm.total) .then(function(isOk) { vm.isCreditOk = isOk; }) .catch(showError); @@ -626,16 +622,16 @@ Invece usa la più semplice sintassi setter. ### Tenere i controller "a fuoco" ###### [Stile [Y037](#stile-y037)] - - Definisci un controller per vista e prova a non riutilizzare il controller per altre view. Piuttosto, sposta la logica riutilizzabile alle factory e mantieni il controller semplice ed a fuoco sulla propria view. - + - Definisci un controller per vista e prova a non riutilizzare il controller per altre view. Piuttosto, sposta la logica riutilizzabile alle factory e mantieni il controller semplice ed a fuoco sulla propria view. + *Perché?*: Riutilizzare i controller con diverse view è precario e sono necessari dei buoni test end-to-end (e2e) per assicurarne la stabilità in applicazioni su larga scala. ### Assegnazione dei Controller ###### [Stile [Y038](#stile-y038)] - - Quando un controller deve essere accoppiato ad una view ed un componente può essere riutilizzato da altri controller o view, definisci i controller insieme alle loro route. + - Quando un controller deve essere accoppiato ad una view ed un componente può essere riutilizzato da altri controller o view, definisci i controller insieme alle loro route. - Nota: Se una View è caricata attraverso altri mezzi che una route, allora usa la sintassi `ng-controller="AvengersController as avengers"`. + Nota: Se una View è caricata attraverso altri mezzi che una route, allora usa la sintassi `ng-controller="AvengersController as avengers"`. *Perché?*: Accoppiare il controller in una route consente a route diverse di invocare diversi accoppiamenti di controller e view. Quando i controller sono assegnati in una view usando [`ng-controller`](https://docs.angularjs.org/api/ng/directive/ngController) quella view sarà sempre associata al medesimo controller. @@ -692,8 +688,8 @@ Invece usa la più semplice sintassi setter. ### Singleton ###### [Stile [Y040](#stile-y040)] - - I Service sono istanziati con la keyword `new`, usa `this` per metodi e variabili pubbliche. Dal momento che sono molto simili alle factory, usa queste ultime per consistenza. - + - I Service sono istanziati con la keyword `new`, usa `this` per metodi e variabili pubbliche. Dal momento che sono molto simili alle factory, usa queste ultime per consistenza. + Nota: [Tutti i servizi di Angular sono singleton](https://docs.angularjs.org/guide/services). Questo significa che c'è soltanto una istanza di un dato servizio per iniettore. ```javascript @@ -728,7 +724,7 @@ Invece usa la più semplice sintassi setter. ## Factory -### Singola responsabilità +### Singola responsabilità ###### [Stile [Y050](#stile-y050)] - Le factory dovrebbero avere la [singola responsabilità](http://en.wikipedia.org/wiki/Single_responsibility_principle) che è incapsulata nel proprio contesto. Una volta che una factory eccede quello che è un singolo scopo, dovrebbe essere creata una nuova factory. @@ -737,15 +733,15 @@ Invece usa la più semplice sintassi setter. ###### [Stile [Y051](#stile-y051)] - Le factory sono singleton e ritornano un oggetto che contiene i membri del servizio. - + Nota: [Tutti i servizi di Angular sono singleton](https://docs.angularjs.org/guide/services). ### Membri accessibili in alto ###### [Stile [Y052](#stile-y052)] - - Esponi tutti i membri richiamabili del servizio (l'interfaccia) in alto, usando una tecnica derivata dal [Revealing Module Pattern](http://addyosmani.com/resources/essentialjsdesignpatterns/book/#revealingmodulepatternjavascript). + - Esponi tutti i membri richiamabili del servizio (l'interfaccia) in alto, usando una tecnica derivata dal [Revealing Module Pattern](http://addyosmani.com/resources/essentialjsdesignpatterns/book/#revealingmodulepatternjavascript). - *Perché?*: Porre i membri richiamabili in alto lo rende semplice da leggere e aiuta ad identificare istantaneamente quali membri del servizio possono essere chiamati ed essere oggetto di unit test (e/o simulati). + *Perché?*: Porre i membri richiamabili in alto lo rende semplice da leggere e aiuta ad identificare istantaneamente quali membri del servizio possono essere chiamati ed essere oggetto di unit test (e/o simulati). *Perché?*: Questo è particolarmente utile quando i file iniziano ad allungarsi così da evitare la necessità di scorrere per leggere cosa è esposto. @@ -755,10 +751,10 @@ Invece usa la più semplice sintassi setter. /* evitare */ function dataService() { var someValue = ''; - function save() { + function save() { /* */ }; - function validate() { + function validate() { /* */ }; @@ -783,11 +779,11 @@ Invece usa la più semplice sintassi setter. //////////// - function save() { + function save() { /* */ }; - function validate() { + function validate() { /* */ }; } @@ -803,15 +799,15 @@ Invece usa la più semplice sintassi setter. - Usa le dichiarazioni di funzioni per nascondere i dettagli di implementazione. Tieni i membri accessibili della factory in alto. Puntali alle dichiarazioni di funzioni che compaiono dopo nel file. Per ulteriori dettagli guarda [questo post](http://www.johnpapa.net/angular-function-declarations-function-expressions-and-readable-code) (in inglese). - *Perché?*: Porre i membri richiamabili in alto la rende semplice da leggere e aiuta ad identificare istantaneamente quali funzioni della factory possono accessibili esternamente. + *Perché?*: Porre i membri richiamabili in alto la rende semplice da leggere e aiuta ad identificare istantaneamente quali funzioni della factory possono accessibili esternamente. *Perché?*: Porre i dettagli di implementazione di una funzione dopo nel file sposta la complessità fuori dalla vista così che puoi vedere le cose importanti prima. *Perché?*: Le dichiarazioni di funzione sono richiamate così da non avere preoccupazioni circa l'uso di una funzione prima della sua definizione (come sarebbe nel caso di espressioni di funzione). - *Perché?*: Non dovrai mai preoccuparti di dichiarazioni di funzione che spostano `var a` prima di `var b` rompendo il codice perché `a` dipende da `b`. + *Perché?*: Non dovrai mai preoccuparti di dichiarazioni di funzione che spostano `var a` prima di `var b` rompendo il codice perché `a` dipende da `b`. - *Perché?*: Con le espressioni di funzione l'ordine è critico. + *Perché?*: Con le espressioni di funzione l'ordine è critico. ```javascript /** @@ -915,7 +911,7 @@ Invece usa la più semplice sintassi setter. ```javascript /* consigliato */ - // factory del servizio ai dati + // factory del servizio ai dati angular .module('app.core') .factory('dataservice', dataservice); @@ -942,7 +938,7 @@ Invece usa la più semplice sintassi setter. } } ``` - + Nota: Il servizio ai dati è chiamato dai consumatori, come un controller, nascondendo l'implementazione ai consumatori, come mostrato sotto. ```javascript @@ -974,7 +970,7 @@ Invece usa la più semplice sintassi setter. return vm.avengers; }); } - } + } ``` ### Ritornare una promessa dalle chiamate ai dati @@ -1028,12 +1024,12 @@ Invece usa la più semplice sintassi setter. ### Limita 1 per file ###### [Stile [Y070](#stile-y070)] - - Crea una directive per file. Nomina il file per la directive. + - Crea una directive per file. Nomina il file per la directive. - *Perché?*: È facile mescolare tutte le directive in un unico file ma difficoltoso da separare così che alcune siano condivise tra le applicazioni, alcune tra moduli, altre solo per un module. + *Perché?*: È facile mescolare tutte le directive in un unico file ma difficoltoso da separare così che alcune siano condivise tra le applicazioni, alcune tra moduli, altre solo per un module. *Perché?*: Una directive per file è semplice da manutenere. - + > Nota: "**Best Practice**: Le directive dovrebbero fare pulizia alla fine. Puoi usare `element.on('$destroy', ...)` oppure `scope.$on('$destroy', ...)` per lanciare una funzione di pulizia quando la directive è rimossa" ... dalla documentazione di Angular. ```javascript @@ -1090,7 +1086,7 @@ Invece usa la più semplice sintassi setter. /** * @desc directive delle vendite che può essere usato dovunque nella applicazione di vendita di una azienda di nome Acme * @example
- */ + */ angular .module('sales.widgets') .directive('acmeSalesCustomerInfo', salesCustomerInfo); @@ -1122,7 +1118,7 @@ Invece usa la più semplice sintassi setter. ### Manipolare il DOM in una Directive ###### [Stile [Y072](#stile-y072)] - - Quando devi manipolare direttamente il DOM, usa una directive. Se possono essere usate delle alternative come usare CSS per settare stili o i [servizi di animazione](https://docs.angularjs.org/api/ngAnimate), templating di Angular, [`ngShow`](https://docs.angularjs.org/api/ng/directive/ngShow) oppure [`ngHide`](https://docs.angularjs.org/api/ng/directive/ngHide), allora usa questi. Per esempio, se la directive deve semplicemente nascondere e mostrare, usa ngHide/ngShow. + - Quando devi manipolare direttamente il DOM, usa una directive. Se possono essere usate delle alternative come usare CSS per settare stili o i [servizi di animazione](https://docs.angularjs.org/api/ngAnimate), templating di Angular, [`ngShow`](https://docs.angularjs.org/api/ng/directive/ngShow) oppure [`ngHide`](https://docs.angularjs.org/api/ng/directive/ngHide), allora usa questi. Per esempio, se la directive deve semplicemente nascondere e mostrare, usa ngHide/ngShow. *Perché?*: Manipolare il DOM può essere difficoltoso da testare, debuggare e spesso ci sono modi migliori (p.e. CSS, animazioni, template) @@ -1131,9 +1127,9 @@ Invece usa la più semplice sintassi setter. - Utilizza un corto, unico e descrittivo prefisso alla directive come `acmeSalesCustomerInfo` che potrebbe essere dichiarato in HTML come `acme-sales-customer-info`. - *Perché?*: L'unico breve prefisso identifica il contesto delle directive e l'origine. Per esempio un prefisso `cc-` potrebbe indicare che la directive è parte di una app CodeCamper mentre `acme-` potrebbe indicare una direttiva per l'azienda Acme. - - Nota: Evita `ng-` poiché queste sono riservate per le directive di Angular. Cerca directive che sono largamente utilizzate per evitare il conflitto di nomi, come `ion-` per il [Framework Ionic ](http://ionicframework.com/). + *Perché?*: L'unico breve prefisso identifica il contesto delle directive e l'origine. Per esempio un prefisso `cc-` potrebbe indicare che la directive è parte di una app CodeCamper mentre `acme-` potrebbe indicare una direttiva per l'azienda Acme. + + Nota: Evita `ng-` poiché queste sono riservate per le directive di Angular. Cerca directive che sono largamente utilizzate per evitare il conflitto di nomi, come `ion-` per il [Framework Ionic ](http://ionicframework.com/). ### Restringi a Elementi and Attributi ###### [Stile [Y074](#stile-y074)] @@ -1176,7 +1172,7 @@ Invece usa la più semplice sintassi setter.
``` - + ```javascript /* consigliato */ angular @@ -1204,9 +1200,9 @@ Invece usa la più semplice sintassi setter. *Perché?*: È sensato e non è difficile. - Nota: La directive sotto dimostra alcuni dei modi in cui puoi usare lo scope all'interno di link e controller di directive usando controllerAs. Ho usato sulla stessa linea il template solo per mettere tutto in un unico posto. + Nota: La directive sotto dimostra alcuni dei modi in cui puoi usare lo scope all'interno di link e controller di directive usando controllerAs. Ho usato sulla stessa linea il template solo per mettere tutto in un unico posto. - Nota: In relazione alla dependency injection, guarda [Annotazioni manuali per la Dependency Injection](#annotazioni-manuali-per-la-dependency-injection). + Nota: In relazione alla dependency injection, guarda [Annotazioni manuali per la Dependency Injection](#annotazioni-manuali-per-la-dependency-injection). Nota: Notare che il controller della directive è al di fuori della closure della directive. Questo stile elimina problematiche dove l'iniezione viene creata come codice non raggiungibile dopo un `return`. @@ -1240,15 +1236,15 @@ Invece usa la più semplice sintassi setter. console.log('LINK: scope.vm.max = %s', scope.vm.max); } } - + ExampleController.$inject = ['$scope']; - + function ExampleController($scope) { // Iniettare $scope solo per confronto var vm = this; vm.min = 3; - + console.log('CTRL: $scope.vm.min = %s', $scope.vm.min); console.log('CTRL: $scope.vm.max = %s', $scope.vm.max); console.log('CTRL: vm.min = %s', vm.min); @@ -1264,7 +1260,7 @@ Invece usa la più semplice sintassi setter. ``` Nota: Puoi inoltre nominare il controller quando lo inietti nella link function e accedi agli attributi della directive come proprietà del controller. - + ```javascript // Alternativa all'esempio sopra riportato function linkFunc(scope, el, attr, vm) { @@ -1280,7 +1276,7 @@ Invece usa la più semplice sintassi setter. *Perché?*: Rende semplice il bind tra lo scope esterno e lo scope del controller delle directive. - Nota: `bindToController` è stato introdotto con Angular 1.3.0. + Nota: `bindToController` è stato introdotto con Angular 1.3.0. ```html
@@ -1328,13 +1324,13 @@ Invece usa la più semplice sintassi setter. ###### [Stile [Y080](#stile-y080)] - Risolvi la logica di start-up per un controller in una funzione `activate`. - + *Perché?*: Porre la logica di start-up in una posizione consistente nel controller la rende semplice da localizzare, più consistente da testare e aiuta a prevenire la diffusione della logica di attivazione su tutto il controller. *Perché?*: La funzione `activate` del controller rende il riuso della logica adatto in caso di un refresh del controller/view, tiene la logica assieme, porta l'utente alla view più rapidamente, rende le animazini più facili su `ng-view` o `ui-view`e da la sensazione all'utente di istantaneità. - + Nota: Se hai necessità di annullare condizionalmente il route prima di iniziare ad usare il controller, usa piuttosto una [risoluzione nella route](#stile-y081). - + ```javascript /* evitare */ function Avengers(dataservice) { @@ -1432,7 +1428,7 @@ Invece usa la più semplice sintassi setter. vm.movies = moviesPrepService.movies; } ``` - + Nota: L'esempio sotto mostra il punto di risoluzione della route in una funzione con il nome per cui è più semplice da fare il debug e più semplice da gestire nella iniezione delle dependenze. ```javascript @@ -1480,7 +1476,7 @@ Invece usa la più semplice sintassi setter. ###### [Stile [Y090](#stile-y090)] - Evita di usare abbreviazioni sintattiche per la dichiarazione di dipendenze senza usare un approccio a prova di minificazione. - + *Perché?*: I parametri dei componenti (p.e. controller, factory, etc.) saranno convertiti in variabili dal nome ridotto. Per esempio, `common` e `dataservice` potrebbero diventare `a` o `b` e non essere piò ritrovate da Angular. ```javascript @@ -1504,30 +1500,30 @@ Invece usa la più semplice sintassi setter. ###### [Stile [Y091](#stile-y091)] - Usa `$inject` per identificare manualmente le tue dipendenze per i componenti di Angular. - + *Perché?*: Questa tecnica rispecchia la tecnica usata da [`ng-annotate`](https://github.com/olov/ng-annotate), che raccomando per l'automazione della creazione della minificazione sicura delle dipendenze. Se `ng-annotate` rileva che una iniezione è stata fatta, non la duplicherà. *Perché?*: Questo salvaguarda le tue dipendenze dall'essere vulnerabili alla questione della minificazione quando i parametri possono essere passati con nomi ridotti. Per esempio, `common` e `dataservice` possono diventare `a` o `b` e non essere più trovati da Angular. - *Perché?*: Evita la creazione di dipendenze sulla stessa linea dal momento che lunghe liste possono essere difficili da leggere nell'array. Inoltre può essere fuorviante che l'array è una serie di stringhe mentre l'ultimo elemento è la funzione del componente. + *Perché?*: Evita la creazione di dipendenze sulla stessa linea dal momento che lunghe liste possono essere difficili da leggere nell'array. Inoltre può essere fuorviante che l'array è una serie di stringhe mentre l'ultimo elemento è la funzione del componente. ```javascript /* evitare */ angular .module('app') - .controller('Dashboard', - ['$location', '$routeParams', 'common', 'dataservice', + .controller('Dashboard', + ['$location', '$routeParams', 'common', 'dataservice', function Dashboard($location, $routeParams, common, dataservice) {} - ]); + ]); ``` ```javascript /* evitare */ angular .module('app') - .controller('Dashboard', + .controller('Dashboard', ['$location', '$routeParams', 'common', 'dataservice', Dashboard]); - + function Dashboard($location, $routeParams, common, dataservice) { } ``` @@ -1539,7 +1535,7 @@ Invece usa la più semplice sintassi setter. .controller('Dashboard', Dashboard); Dashboard.$inject = ['$location', '$routeParams', 'common', 'dataservice']; - + function Dashboard($location, $routeParams, common, dataservice) { } ``` @@ -1582,7 +1578,7 @@ Invece usa la più semplice sintassi setter. ###### [Stile [Y092](#stile-y092)] - Usa `$inject` per identificare manualmente le tue dipendenze di resolver della route per i componenti di Angular. - + *Perché?*: Questa tecnica evade le funzioni anonime per il resolver della route, rendendolo più semplice da leggere. *Perché?*: Una dichiarazione `$inject` può facilmente precedere il resolver per gestire la produzione di dipendenze che siano a prova di minificazione. @@ -1615,10 +1611,10 @@ Invece usa la più semplice sintassi setter. ###### [Stile [Y100](#stile-y100)] - Usa [ng-annotate](//github.com/olov/ng-annotate) per [Gulp](http://gulpjs.com) o [Grunt](http://gruntjs.com) e commenta le funzioni che necessitano di automatizzare la dependency injection usando `/** @ngInject */` - + *Perché?*: Questo salvaguarda il tuo codice da ogni dipendenza che non segua le pratiche a prova di minificazione - *Perché?*: [`ng-min`](https://github.com/btford/ngmin) è deprecato. + *Perché?*: [`ng-min`](https://github.com/btford/ngmin) è deprecato. >Preferisco Gulp poiché lo ritengo più semplice da scrivere, leggere e fare il debug. @@ -1692,7 +1688,7 @@ Invece usa la più semplice sintassi setter. ###### [Stile [Y101](#stile-y101)] - Usa [gulp-ng-annotate](https://www.npmjs.org/package/gulp-ng-annotate) o [grunt-ng-annotate](https://www.npmjs.org/package/grunt-ng-annotate) in un task di automatizzazione delle build. Inietta `/* @ngInject */` prima di qualunque funzione che abbia delle dipendenze. - + *Perché?*: ng-annotate carpirà la maggior parte delle dipendenze ma talvolta necessita dell'uso del suggerimento sintattico `/* @ngInject */`. Il seguente codice è un esempio di un task di gulp che utilizza ngAnnotate. @@ -1700,7 +1696,7 @@ Invece usa la più semplice sintassi setter. ```javascript gulp.task('js', ['jshint'], function() { var source = pkg.paths.js; - + return gulp.src(source) .pipe(sourcemaps.init()) .pipe(concat('all.min.js', {newLine: ';'})) @@ -1727,7 +1723,7 @@ Invece usa la più semplice sintassi setter. ###### [Stile [Y110](#stile-y110)] - Usa un [decorator](https://docs.angularjs.org/api/auto/service/$provide#decorator), al momento del config usando il servizio [`$provide`](https://docs.angularjs.org/api/auto/service/$provide), sul servizio [`$exceptionHandler`](https://docs.angularjs.org/api/ng/service/$exceptionHandler) per eseguire azioni ad hoc quando l'eccezione occorre. - + *Perché?*: Fornisce un modo consistente per la gestione delle eccezioni non trattate da Angular sia durante lo sviluppo che a runtime. Nota: Un'altra opzione è di fare l'override del servizio invece che usare un decorator. Questa è una buona opzione ma se vuoi tenere il comportamento di default ed estenderlo un decorator è consigliato. @@ -1749,9 +1745,9 @@ Invece usa la più semplice sintassi setter. function extendExceptionHandler($delegate, toastr) { return function(exception, cause) { $delegate(exception, cause); - var errorData = { - exception: exception, - cause: cause + var errorData = { + exception: exception, + cause: cause }; /** * Potresti aggiungere l'errore ad una collezione del servizio, @@ -1807,7 +1803,7 @@ Invece usa la più semplice sintassi setter. ```javascript /* consigliato */ var handlingRouteChangeError = false; - + function handleRoutingErrors() { /** * Annullamento del route: @@ -1829,7 +1825,7 @@ Invece usa la più semplice sintassi setter. * (Non dimenticare di iniettare il servizio ad hoc) */ logger.warning(msg, [current]); - + /** * Su un errore di routing, vai ad un'altra route/stato. */ @@ -1849,10 +1845,10 @@ Invece usa la più semplice sintassi setter. - Usa nomi consistenti per tutti i componenti seguendo uno schema che descriva le funzionalità dei componenti e poi (a scelta) il suo tipo. Lo schema che consiglio è `feature.type.js`. Ci sono 2 nomi per la maggior parte dei componenti: * il nome del file (`avengers.controller.js`) * il nome del componente registrato con Angular (`AvengersController`) - + *Perché?*: Convezioni sui nomi aiutano a fornire un modo consistente per trovate i contenuti a colpo d'occhio. Essere consistenti in un progetto è vitale. Essere consistenti in un team è importante. Essere consistenti nell'insieme di un'azienda è tremendamente efficiente. - *Perché?*: Le convezioni sulla nomenclatura dovrebbe semplicemente aiutare a trovare il tuo codice più rapidamente e renderlo più semplice da comprendere. + *Perché?*: Le convezioni sulla nomenclatura dovrebbe semplicemente aiutare a trovare il tuo codice più rapidamente e renderlo più semplice da comprendere. ### Nomi dei file per funzionalità ###### [Stile [Y121](#stile-y121)] @@ -1865,7 +1861,7 @@ Invece usa la più semplice sintassi setter. ```javascript /** - * opzioni comuni + * opzioni comuni */ // Controllers @@ -1894,7 +1890,7 @@ Invece usa la più semplice sintassi setter. // constants constants.js - + // module definition avengers.module.js @@ -1904,7 +1900,7 @@ Invece usa la più semplice sintassi setter. // configuration avengers.config.js - + // directives avenger-profile.directive.js avenger-profile.directive.spec.js @@ -1924,7 +1920,7 @@ Invece usa la più semplice sintassi setter. ### Nomi dei file di test ###### [Stile [Y122](#stile-y122)] - - Nomina le specifiche dei test in modo similare al componente che testano aggiundendo il suffisso `spec`. + - Nomina le specifiche dei test in modo similare al componente che testano aggiundendo il suffisso `spec`. *Perché?*: Fornisce un modo consistente per identificare facilmente i componenti. @@ -1961,7 +1957,7 @@ Invece usa la più semplice sintassi setter. function HeroAvengers(){ } ``` - + ### Suffisso nel nome di un controller ###### [Stile [Y124](#stile-y124)] @@ -1988,11 +1984,11 @@ Invece usa la più semplice sintassi setter. - Usa una nomenclatura consistente per tutte le factory e i service dando i nomi a seguito delle loro funzionalità. Usa il camel-case per service e factory. Evita di pre-nominare factory e service con `$`. Aggiungi il suffisso `Service` a service e factory soltanto quando non è chiaro cosa siano (p. es. quando si tratta di nomi). *Perché?*: Fornisce un modo consistente per identificare facilmente e referenziare le factory. - + *Perché?*: Evita collisione di nomi con factory e servizi di Angular esistenti che usano il prefisso `$`. - + *Perché?*: Service con nomi evidenti quali `logger` on richiedono il suffisso. - + *Perché?*: Nomi di service quali `avengers` sono nomi, richiedono in suffisso e dovrebbero essere nominati `avengersService`. ```javascript @@ -2027,7 +2023,7 @@ Invece usa la più semplice sintassi setter. function customersService() { } ``` - + ### Nomi dei componenti directive ###### [Stile [Y126](#stile-y126)] @@ -2040,7 +2036,7 @@ Invece usa la più semplice sintassi setter. * consigliato */ - // avenger-profile.directive.js + // avenger-profile.directive.js angular .module .directive('xxAvengerProfile', xxAvengerProfile); @@ -2079,12 +2075,12 @@ Invece usa la più semplice sintassi setter. ### LIFT ###### [Stile [Y140](#stile-y140)] - - Struttura la tua app tale da poter `L`ocate (localizzare) il codice facilmente, `I`dentify (identificare) il codice a colpo d'occhio, tenere la struttura più `F`lattest (piatta) che puoi, e `T`ry (provare) a rimanere DRY (Don't Repeat Yourself - Non ripetersi). La struttura dovrebbe seguire queste 4 linee guida basilari. + - Struttura la tua app tale da poter `L`ocate (localizzare) il codice facilmente, `I`dentify (identificare) il codice a colpo d'occhio, tenere la struttura più `F`lattest (piatta) che puoi, e `T`ry (provare) a rimanere DRY (Don't Repeat Yourself - Non ripetersi). La struttura dovrebbe seguire queste 4 linee guida basilari. *Perché LIFT?*: Fornisce una struttura consistente che scala bene, è modulare e rende più semplice aumentare l'efficienza dello sviluppatore nel trovare facilmente il codice. Un altro modo per verificare la struttura della tua app è chiederti: Quanto rapidamente puoi aprire e lavorare ad una funzionalità in tutti i file che sono collegati? Quando ritengo che la mia struttura non sia confortevole, torno indietro a rivedere le linee guida LIFT - + 1. `L`ocalizzare il nostro codice con facilità 2. `I`dentificare il codice a colpo d'occhio 3. `F`lat (pitta) struttura quanto più possibile @@ -2135,7 +2131,7 @@ Invece usa la più semplice sintassi setter. - Si DRY, ma non diventare pazzo e sacrificare la leggibilità. - *Perché?*: Non ripetersi è importante ma non è cruciale se sacrifica altri principi LIFT, per questo il principio è Try (provare) DRY. Non voglio digitare session-view.html perché è ovvio essere una view. Se non è ovvio o se per convenzione allora nominala così. + *Perché?*: Non ripetersi è importante ma non è cruciale se sacrifica altri principi LIFT, per questo il principio è Try (provare) DRY. Non voglio digitare session-view.html perché è ovvio essere una view. Se non è ovvio o se per convenzione allora nominala così. **[Torna all'inizio](#tavola-dei-contenuti)** @@ -2151,7 +2147,7 @@ Invece usa la più semplice sintassi setter. ### Layout ###### [Stile [Y151](#stile-y151)] - - Metti i componenti che definiscono il layout globale dell'applicazione in una cartella con il nome `layout`. Questi possono includere un shell view e controller che agiscono come contenitori per l'app, navigazione, menù, aree per i contenuti ed altre regioni. + - Metti i componenti che definiscono il layout globale dell'applicazione in una cartella con il nome `layout`. Questi possono includere un shell view e controller che agiscono come contenitori per l'app, navigazione, menù, aree per i contenuti ed altre regioni. *Perché?*: Organizza tutto il layout in una sola posizione riutilizzabile lungo tutta l'applicazione. @@ -2177,33 +2173,33 @@ Invece usa la più semplice sintassi setter. app.module.js app.config.js app.routes.js - components/ - calendar.directive.js - calendar.directive.html - user-profile.directive.js - user-profile.directive.html + components/ + calendar.directive.js + calendar.directive.html + user-profile.directive.js + user-profile.directive.html layout/ - shell.html + shell.html shell.controller.js - topnav.html - topnav.controller.js + topnav.html + topnav.controller.js people/ attendees.html - attendees.controller.js + attendees.controller.js speakers.html speakers.controller.js speaker-detail.html speaker-detail.controller.js - services/ - data.service.js + services/ + data.service.js localstorage.service.js - logger.service.js + logger.service.js spinner.service.js sessions/ - sessions.html + sessions.html sessions.controller.js session-detail.html - session-detail.controller.js + session-detail.controller.js ``` ![Struttura dell'App di Esempio](https://raw.githubusercontent.com/johnpapa/angularjs-styleguide/master/assets/modularity-2.png) @@ -2211,44 +2207,44 @@ Invece usa la più semplice sintassi setter. Nota: Non usare una strutturazione del tipo cartella-per-tipo per la tua app. Questo richiede spostarsi tra molte cartelle quando si lavora su una funzionalità e diventa rapidamente scomodo quando l'app cresce di 5, 10 o più di 25 tra view e controller (ed altre funzionalità), per cui è più difficile rispetto alla localizzazione basata su cartella-per-funzionalità. ```javascript - /* + /* * evitare * Alternativa cartella-per-tipo * Consiglio invece "cartella-per-funzionalità". */ - + app/ app.module.js app.config.js app.routes.js directives.js controllers/ - attendees.js - session-detail.js - sessions.js - shell.js - speakers.js - speaker-detail.js - topnav.js - directives/ - calendar.directive.js - calendar.directive.html - user-profile.directive.js - user-profile.directive.html - services/ - dataservice.js + attendees.js + session-detail.js + sessions.js + shell.js + speakers.js + speaker-detail.js + topnav.js + directives/ + calendar.directive.js + calendar.directive.html + user-profile.directive.js + user-profile.directive.html + services/ + dataservice.js localstorage.js - logger.js + logger.js spinner.js views/ - attendees.html + attendees.html session-detail.html - sessions.html - shell.html - speakers.html + sessions.html + shell.html + speakers.html speaker-detail.html - topnav.html - ``` + topnav.html + ``` **[Torna all'inizio](#tavola-dei-contenuti)** @@ -2274,7 +2270,7 @@ Invece usa la più semplice sintassi setter. - Nel modulo principale metti solo la logica che serva da collante per l'app. Lascia le funzionalità ognuna al proprio modulo. *Perché?*: L'aggiunta di ruoli addizionali al modulo principale per il recupero dei dati, il mostrare viste o altra logica non correlata al tenere insieme l'applicazione sporca il modulo principale e rende entrambi gli insiemi di funzionalità più complessi da riusare o rimuovere. - + *Perché?*: Il modulo app diventa un manifesto che descrive quali moduli aiutano a definire l'applicazione. ### Aree di funzionalità sono Moduli @@ -2286,7 +2282,7 @@ Invece usa la più semplice sintassi setter. *Perché?*: Sprint o iterazioni possono focalizzarsi sulle aree di funzionalità e renderle disponibili alla fine dello sprint o dell'iterazione. - *Perché?*: Separare aree di funzioni in moduli rende più semplice testare i moduli in isolamento e il riutilizzo del codice. + *Perché?*: Separare aree di funzioni in moduli rende più semplice testare i moduli in isolamento e il riutilizzo del codice. ### Blocchi riutilizzabili sono Moduli ###### [Stile [Y164](#stile-y164)] @@ -2302,7 +2298,7 @@ Invece usa la più semplice sintassi setter. ![Modularità e Dipendenze](https://raw.githubusercontent.com/johnpapa/angularjs-styleguide/master/assets/modularity-1.png) - *Perché?*: Il modulo principale dell'app contiene un manifesto che sia facilmente identificabile con le funzionalità dell'applicazione. + *Perché?*: Il modulo principale dell'app contiene un manifesto che sia facilmente identificabile con le funzionalità dell'applicazione. *Perché?*: Ogni area di funzionalità contiene un manifesto di ciò da cui dipende, in modo tale da poter essere usato come dipendenza in altre applicazioni e continuare a funzionare. @@ -2310,8 +2306,8 @@ Invece usa la più semplice sintassi setter. Nota: Questa è una strategia per la consistenza. Ci sono diverse buone opzioni in questo caso. Scegline una che sia consistente, segua le regole delle dipendenze di Angular e sia facile da manutenere e scalare. - > La mia struttura varia leggermente tra progetti ma tutti seguono queste linee guida per la strutturazione e modularità. L'implementazione può variare in relazione alle funzionalità ed al team. In altre parole, non ti bloccare su una struttura che sia esattamente uguale ma giustifica la tua struttura tenendo a mente l'uso di consistenza, manutenibilità ed efficienza. - + > La mia struttura varia leggermente tra progetti ma tutti seguono queste linee guida per la strutturazione e modularità. L'implementazione può variare in relazione alle funzionalità ed al team. In altre parole, non ti bloccare su una struttura che sia esattamente uguale ma giustifica la tua struttura tenendo a mente l'uso di consistenza, manutenibilità ed efficienza. + > In una applicazione piccola, si può considerare di mettere tutte le dipendenze condivise nel modulo dell'app dove i moduli delle funzionalità non hanno dipendenze dirette. Ciò rende semplice mantenere l'applicazione più piccola ma rende più difficile riutilizzare i moduli fuori dell'applicazione stessa. **[Torna all'inizio](#tavola-dei-contenuti)** @@ -2330,7 +2326,7 @@ Invece usa la più semplice sintassi setter. .module('app') .config(configure); - configure.$inject = + configure.$inject = ['routerHelperProvider', 'exceptionHandlerProvider', 'toastr']; function configure (routerHelperProvider, exceptionHandlerProvider, toastr) { @@ -2502,18 +2498,18 @@ Gli unit test aiutano a mantenere il codice più chiaro, perciò ho incluso alcu - Usa [PhantomJS](http://phantomjs.org/) per eseguire i test su un server. - *Perché?*: PhantomJS è un headless browser (browser senza interfaccia grafica) che aiuta l'esecuzione di test senza la necessità di un browser "visuale". Quindi non devi installare Chrome, Safari, IE o altri browser sul server. + *Perché?*: PhantomJS è un headless browser (browser senza interfaccia grafica) che aiuta l'esecuzione di test senza la necessità di un browser "visuale". Quindi non devi installare Chrome, Safari, IE o altri browser sul server. Nota: Dovresti in ogni caso testare tutti i browser nel tuo ambiente, come appropriato per il pubblico che ne è il target. ### Analisi del codice ###### [Stile [Y195](#stile-y195)] - - Esegui JSHint sui tuoi test. + - Esegui JSHint sui tuoi test. *Perché?*: I test sono codice. JSHint può aiutare ad identificare problemi di qualità del codice che causano l’improprio funzionamento del test. -### Alleviare le regole sulle variabili globali di JSHint per i test +### Alleviare le regole sulle variabili globali di JSHint per i test ###### [Stile [Y196](#stile-y196)] - Rilassa le regole sul codice dei test per consentire variabili globali comuni quali `describe` ed `expect`. @@ -2524,12 +2520,12 @@ Gli unit test aiutano a mantenere il codice più chiaro, perciò ho incluso alcu /* jshint -W117, -W030 */ ``` Oppure puoi aggiungere le righe che seguono al tuo file JSHint Options. - + ```javascript "jasmine": true, "mocha": true, ``` - + ![Strumenti per i test](https://raw.githubusercontent.com/johnpapa/angularjs-styleguide/master/assets/testing-tools.png) ### Organizzazione dei test @@ -2537,14 +2533,14 @@ Gli unit test aiutano a mantenere il codice più chiaro, perciò ho incluso alcu - Posiziona i file degli unit test (spec) vicino al codice del client. Posiziona le specifiche che coprono l'integrazione con il server o che testano più componenti in una cartella separata `tests`. - *Perché?*: Gli unit test hanno una correlazione diretta con un componente specifico e file nei sogenti. + *Perché?*: Gli unit test hanno una correlazione diretta con un componente specifico e file nei sogenti. *Perché?*: È più semplice da tenere aggiornati dal momento che sono sempre a vista. Quando scrivi codice, sia che tu faccia TDD o fai i test durante o dopo lo sviluppo, le scpecifiche sono sempre di fianco e mai fuori dalla vista o dai pensieri, quindi è più probabile che siano aggiornati e ciò consente inoltre a mantenere una migliore copertura del codice. *Perché?*: Quando aggiorni i sorgenti, è più semplice andare ad aggiornare anche i test. *Perché?*: Posizionarli vicino rende semplice trovarli e spostarli con i sorgenti qualora ciò accada. - + *Perché?*: Avere le specifiche vicino rende più facile al lettore del codice sorgente imparare come il componente dovrebbe essere usato e scoprire le sue limitazioni. *Perché?*: Separare le specifiche così da non essere nella build di distribuzione è semplice con grunt o gulp. @@ -2575,7 +2571,7 @@ Gli unit test aiutano a mantenere il codice più chiaro, perciò ho incluso alcu ### Sotto il secondo ###### [Stile [Y211](#stile-y211)] - - Usa animazioni che abbiano una durata breve. Generalmente parto con 300 ms e aggiusto finché non è appropriato. + - Usa animazioni che abbiano una durata breve. Generalmente parto con 300 ms e aggiusto finché non è appropriato. *Perché?*: Animazioni lunghe possono avere l'effetto contrario sull'esperienza dell'utente e di percezzione delle prestazioni che danno il senso di una applicazione lenta. @@ -2607,7 +2603,7 @@ Gli unit test aiutano a mantenere il codice più chiaro, perciò ho incluso alcu ```javascript /** - * Factory di Log + * Factory di Log * @namespace Factories */ (function() { @@ -2832,7 +2828,7 @@ Gli unit test aiutano a mantenere il codice più chiaro, perciò ho incluso alcu .constant('moment', moment); })(); ``` - + ###### [Stile [Y241](#stile-y241)] - Usa constanti per i valori che non cambiano e che non provengono da un altro servizio. Quando le costanti sono utilizzate solo per un modulo che potrebbe essere riutilizzato in più applicazioni, metti le costanti in un file per modulo e nominalo come il modulo. Fintanto che tale necesstià non si presenti, tieni le constanti nel modulo principale in un file `constants.js`. @@ -2866,13 +2862,13 @@ Usa file template o snippet che ti aiutino a seguire stili e schemi consistentem ### Sublime Text ###### [Stile [Y250](#stile-y250)] - - Snippet Angular che seguono questi stili e linee guida. + - Snippet Angular che seguono questi stili e linee guida. - - Scarica gli [snippet di Angular per Sublime](assets/sublime-angular-snippets.zip?raw=true) + - Scarica gli [snippet di Angular per Sublime](assets/sublime-angular-snippets.zip?raw=true) - Mettili nella tua cartella Packages - - Riavvia Sublime + - Riavvia Sublime - In un file JavaScript digita questi comandi seguiti da `TAB` - + ```javascript ngcontroller // crea un controller Angular ngdirective // crea una directive Angular @@ -2896,7 +2892,7 @@ Usa file template o snippet che ti aiutino a seguire stili e schemi consistentem - Snippet Angular e file di template che seguono queste linee guida. Le puoi importare dentro i tuoi settaggi di WebStorm: - - Scarica i [file dei template e gli snippet di Angular per WebStorm](assets/webstorm-angular-file-template.settings.jar?raw=true) + - Scarica i [file dei template e gli snippet di Angular per WebStorm](assets/webstorm-angular-file-template.settings.jar?raw=true) - Apri WebStorm e vai al menù `File` - Scegli la voce di menù `Import Settings` - Seleziona il file e clicca `OK` @@ -2907,7 +2903,7 @@ Usa file template o snippet che ti aiutino a seguire stili e schemi consistentem ng-f // crea una factory Angular ng-m // crea un modulo Angular ``` - + ### Atom ###### [Stile [Y253](#stile-y253)] @@ -2919,7 +2915,7 @@ Usa file template o snippet che ti aiutino a seguire stili e schemi consistentem - Apri Atom, poi apri il Package Manager (Packages -> Settings View -> Install Packages/Themes) - Cerca il pacchetto 'angularjs-styleguide-snippets' - Clicca 'Install' per installare il pacchetto - + - In un file di JavaScript digita i seguenti comandi seguiti da un `TAB` ```javascript @@ -3018,7 +3014,7 @@ Il routing del lato client è importante al fine di creare in flusso di navigazi *Perché?*: UI Router offre tutte le funzionalità del router di Angular più alcune funzionalità aggiuntive che includono route nidificate e stati. *Perché?*: la sintassi è piuttosto simile a quella del router di Angular ed è facile migrare a UI Router. - + - Nota: Puoi usare un provider quale `routerHelperProvider` mostrato sotto per aiutarti a configurare gli stati tra i file durante la fase di esecuzione. ```javascript @@ -3147,7 +3143,7 @@ Apri prima una "issue" per discutere potenziali cambiamenti/aggiunte. Se hai dom ### Processo - 1. Discuti i cambiamenti in un issue di GitHub. + 1. Discuti i cambiamenti in un issue di GitHub. 2. Apri una Pull Request, fai riferimento all issue e specifica i cambiamenti e perché questi aggiungono valore. 3. La Pull Request sarà vagliata e quindi fatto un merge o declinata. diff --git a/i18n/ja-JP.md b/i18n/ja-JP.md index 29218653..064fbd51 100644 --- a/i18n/ja-JP.md +++ b/i18n/ja-JP.md @@ -2,16 +2,14 @@ *[@john_papa](//twitter.com/john_papa)によるチームのための頑固なAngularスタイルガイド* -*Translation by [@noritamago](https://github.com/noritamago)* - ->The [original English version](http://jpapa.me/ngstyles) is the source of truth, as it is maintained and updated first. - もしあなたがAngularのシンタックス、規約、そしてアプリケーション構成のための頑固なスタイルガイドを探しているなら、どうぞいらっしゃい!本スタイルは、[Angular](//angularjs.org)を用いた私の開発経験やプレゼンテーション、[Pluralsight training courses](http://pluralsight.com/training/Authors/Details/john-papa) 、そしてチームでの作業に基づいたものです。 このスタイルガイドの目的は、私が実践している規約だけでなく、私がそれを行う理由を示すことによって、Angularアプリケーションを構築する手引きとなることです。 >もしあなたがこのガイドを気に入ったのなら、Pluralsightにある [Angular Patterns: Clean Code](http://jpapa.me/ngclean) の私のコースもチェックして下さい。 +[![Angular Patterns: Clean Code](https://raw.githubusercontent.com/johnpapa/angular-styleguide/master/assets/ng-clean-code-banner.png)](http://jpapa.me/ngclean) + ## Community Awesomeness and Credit あなたは決して1人でありません!Angularのコミュニティは、自身の経験を共有することに情熱的な素晴らしい集団です。実際、友人でありAngularのエキスパートでもある Todd Motto と私は、共同で多くのスタイルや規約をまとめました。一部意見が分かれましたが、概ね合意できるものでした。彼のアプローチと本スタイルとの比較のため、是非 [Todd's guidelines](https://github.com/toddmotto/angularjs-styleguide) をチェックすることをお勧めします。 @@ -1483,9 +1481,9 @@ function Dashboard(common, dataservice) { } ``` - + このコードはMinifyされたときにマングルされた変数が生成され実行エラーになるかもしれません。 - + ```javascript /* avoid - not minification-safe*/ angular.module('app').controller('Dashboard', d);function d(a, b) { } @@ -1999,7 +1997,7 @@ ### Directive Component Names ###### [Style [Y126](#style-y126)] - - 全てのディレクトリにキャメルケースで一貫性を取れた名前を用いて下さい。そのディレクティブが属する範囲を表す短いプリフィックス(例としては会社やプロジェクトのプリフィックス)を用いて下さい。 + - 全てのディレクトリにキャメルケースで一貫性を取れた名前を用いて下さい。そのディレクティブが属する範囲を表す短いプリフィックス(例としては会社やプロジェクトのプリフィックス)を用いて下さい。 *なぜ ?*: 参照するべきコンポーネントと素早く特定する一貫性の取れた方法を与えます。 @@ -2404,7 +2402,7 @@ *なぜ ?*: Karmaは一度だけ実行するか、コードが変更されたときに自動的に実行するかを簡単に設定することができます。 - *なぜ ?*: Karmaは自前のテストランナーもしくはGruntやGulpを用いた継続的なインテグレーションのプロセスに容易に接続することができます。 + *なぜ ?*: Karmaは自前のテストランナーもしくはGruntやGulpを用いた継続的なインテグレーションのプロセスに容易に接続することができます。 *なぜ ?*: [WebStorm](http://www.jetbrains.com/webstorm/) や [Visual Studio](http://visualstudiogallery.msdn.microsoft.com/02f47876-0e7a-4f6c-93f8-1af5d5189225)などのいくつかのIDEはKarmaを統合し始めています。 @@ -2910,7 +2908,7 @@ ## Yeoman Generator ###### [Style [Y260](#style-y260)] -このスタイルガイドに沿ったAngularのアプリケーションを作る良いスタートポイントとして、[HotTowel yeoman generator](http://jpapa.me/yohottowel)を使うことができます。 +このスタイルガイドに沿ったAngularのアプリケーションを作る良いスタートポイントとして、[HotTowel yeoman generator](http://jpapa.me/yohottowel)を使うことができます。 1. generator-hottowelをインストール @@ -3082,7 +3080,7 @@ _tldr; Use this guide. Attributions are appreciated._ ### Copyright Copyright (c) 2014-2015 [John Papa](http://johnpapa.net) - + ### (The MIT License) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the diff --git a/i18n/mk-MK.md b/i18n/mk-MK.md index 872cf239..076188ce 100644 --- a/i18n/mk-MK.md +++ b/i18n/mk-MK.md @@ -2,18 +2,13 @@ *Своеволен Angular водич на кодирање за тимови од [@john_papa](//twitter.com/john_papa)* -*Преведено од [Александар Богатинов](https://github.com/Bogatinov)* - ->[Оригиналната Англиска верзија](http://jpapa.me/ngstyles) е изворот на вистината, одржувана и ажурирана прва. - -Доколку барате своеволен стил на кодирање за синтакса, конвенции и структурирање на Angular апликации, тогаш сте на правилното место. -Овие стилови се базирани на моето искуство во развој на [Angular](//angular.org), презентации, [Pluralsight тренинг курсеви](http://pluralsight.com/training/Authors/Details/john-papa) и работа во тимови. +Доколку барате своеволен стил на кодирање за синтакса, конвенции и структурирање на Angular апликации, тогаш сте на правилното место. Овие стилови се базирани на моето искуство во развој на [Angular](//angular.org), презентации, [Pluralsight тренинг курсеви](http://pluralsight.com/training/Authors/Details/john-papa) и работа во тимови. Целта на овој водич на кодирање е да овозможи насока во развој на Angular апликации преку конвенциите што јас ги користам, и уште поважно, зошто ги користам. >Ако ви се допаѓа овој водич, тогаш проверете ми го курсот [Angular Patterns: Clean Code](http://jpapa.me/ngclean) на Pluralsight кој е придружник на овој водич. -[![Angular Шаблон: Чист Код](https://raw.githubusercontent.com/johnpapa/angular-styleguide/master/assets/ng-clean-code-banner.png)](http://jpapa.me/ngclean) + [![Angular Шаблон: Чист Код](https://raw.githubusercontent.com/johnpapa/angular-styleguide/master/assets/ng-clean-code-banner.png)](http://jpapa.me/ngclean) ## Величествена заедница и заслуга Никогаш не работи во вакуум. Јас сметам дека Angular заедницата е неверојатна група кои се страсни за споделување искуство. Како резултат, јас и мојот пријател кој е Angular експерт, Todd Motto соработувавме со многу стилови и конвенции. Се согласуваме на повеќето, додека на останатите се разликуваме. Ве охрабрувам да ги погледнете на [Todd's guidelines](https://github.com/toddmotto/angular-styleguide) со цел да добиете осет за неговиот пристап и како се споредува. @@ -23,8 +18,7 @@ ## Погледнете ги водичите во пробната апликација Иако овој водич ги објаснува "што", "зошто" и "како", јас сметам дека е полезно да ги запазиме во практика. Овој водич е придружен од пробна апликација која ги следи овие стилови и модели. Можете да ја најдете [пробната апликација (наречена modular) тука](https://github.com/johnpapa/ng-demos) во папката 'modular'. Не се колебајте да ја земете, да ја клонирате и форкувате. [Инструкции за да ја започнете се во своете readme](https://github.com/johnpapa/ng-demos/tree/master/modular) - -##Преводи +##Преводи [Преводи од овој Angular водич на кодирање](https://github.com/johnpapa/angular-styleguide/tree/master/i18n) се одржувани од заедницата и можете да ги најдете тука. ## Table of contents @@ -48,7 +42,7 @@ 1. [Startup Logic](#startup-logic) 1. [Angular $ Wrapper Services](#angular--wrapper-services) 1. [Testing](#testing) - 1. [Animations](#animations) + 1. [Animations](#animations) 1. [Comments](#comments) 1. [JSHint](#js-hint) 1. [JSCS](#jscs) @@ -67,9 +61,9 @@ ### Правило од 1 ###### [Style [Y001](#style-y001)] - - Дефинирај 1 компонента во датотека. + - Дефинирај 1 компонента во датотека. - Следниот пример го дефинира `app` модулот и неговите зависности, дефинира контролер, и дефинира фабрика, сé во една датотека + Следниот пример го дефинира `app` модулот и неговите зависности, дефинира контролер, и дефинира фабрика, сé во една датотека ```javascript /* избегнувајте */ @@ -77,17 +71,17 @@ .module('app', ['ngRoute']) .controller('someController', someController) .factory('someFactory', someFactory); - + function SomeController() { } function someFactory() { } ``` - + Истите компоненти сега се разделени во свои датотеки. ```javascript /* препорачано */ - + // app.module.js angular .module('app', ['ngRoute']); @@ -95,7 +89,7 @@ ```javascript /* препорачано */ - + // someController.js angular .module('app') @@ -106,12 +100,12 @@ ```javascript /* препорачано */ - + // someFactory.js angular .module('app') .factory('someFactory', someFactory); - + function someFactory() { } ``` @@ -120,8 +114,8 @@ ## IIFE ### JavaScript Closures ###### [Style [Y010](#style-y010)] - - Вгнездете ги Angular компоненти во Immediately Invoked Function Expression (IIFE). - + - Вгнездете ги Angular компоненти во Immediately Invoked Function Expression (IIFE). + *Зошто?*: IIFE не ги покажува променливите на глобално ниво. Ова помага при спречување да променливите и декларациите на функциите да живеат подолго од очекуваното на глобалното ниво, што исто така помага во избегнување на судири на променливи со исто име. *Зошто?*: Кога вашиот код е минифициран и поставен во една датотека за да биде ажуриран на продукцискиот сервер тогаш може да се појават судири на локални и глобални променливи. IIFE ве заштитува од двата случаи овозможувајќи ниво на променливи во една датотека. @@ -133,7 +127,7 @@ .module('app') .factory('logger', logger); - // logger функцијата е додадена како глобална променлива + // logger функцијата е додадена како глобална променлива function logger() { } // storage.js @@ -145,10 +139,10 @@ function storage() { } ``` - + ```javascript /** - * препорачано + * препорачано * * нема заборавени глобални променливи */ @@ -156,7 +150,7 @@ // logger.js (function() { 'use strict'; - + angular .module('app') .factory('logger', logger); @@ -176,8 +170,8 @@ })(); ``` - - Забелешка: Со цел да се скрати кодот, остатокот од примерите во овој водич нема да го прикажат IIFE - + - Забелешка: Со цел да се скрати кодот, остатокот од примерите во овој водич нема да го прикажат IIFE + - Забелешка: IIFE's го спречува кодот за тестирање од пристап до приватните членови како регуларни изрази или помошни функции кои потребни се да бидат директно тестирани во изолација. Сепак можете да ги тестирате овие преку членови кои можат да се пристапат или да ги изложите преку своја компонента. На пример, со поставување тие помошни функции, регуларни изрази или константи во своја фабрика или константа. **[Назад кон содржината](#table-of-contents)** @@ -186,16 +180,16 @@ ### Избегнувајте судири во именување ###### [Style [Y020](#style-Y020)] - - Користите уникатни шаблони на именување со разделувачи за под-модулите. + - Користите уникатни шаблони на именување со разделувачи за под-модулите. *Зошто?*: Со уникатни имиња избегнувате судири на модули со исто име. Разделувачи ги одредуваат модулите и нивната хиерархија на подмодули. На пример `app` е главниот модул додека `app.dashboard` и `app.users` се модули кои можно е да се зависни од `app`. ### Дефинирање (познати како Setters) ###### [Style [Y021](#style-Y021)] - - Декларирај модули без променлива користејќи ја setter синтаксата. + - Декларирај модули без променлива користејќи ја setter синтаксата. *Зошто?*: Со 1 компонента во датотека, реткост е да поставиш нова променлива во модулот. - + ```javascript /* избегнувајте*/ var app = angular.module('app', [ @@ -229,7 +223,7 @@ /* избегнувајте */ var app = angular.module('app'); app.controller('SomeController', SomeController); - + function SomeController() { } ``` @@ -238,22 +232,22 @@ angular .module('app') .controller('SomeController', SomeController); - + function SomeController() { } ``` ### Setting vs Getting ###### [Style [Y023](#style-Y023)] - Само еднаш создади и земај го за сите други инстанци. - + *Зошто?*: Модул треба еднаш да биде создаден, и од тој момент да биде само превземен. - + - Употреби `angular.module('app', []);` за да создадеш модул. - - Употреби `angular.module('app');` за да го превземеш тој модул. + - Употреби `angular.module('app');` за да го превземеш тој модул. ### Именувани vs Анонимни функции ###### [Style [Y024](#style-Y024)] - - Употреби именувани функции наместо да проследиш анонимни функции како повратни повици (callback). + - Употреби именувани функции наместо да проследиш анонимни функции како повратни повици (callback). *Зошто?*: Ова создава читлив код, кој е полесен за дебагирање и го намалува бројот на вгнездени повратни повици. @@ -315,11 +309,11 @@ ### controllerAs синтакса во контролери ###### [Style [Y031](#style-Y031)] - - Употреби `controllerAs` наместо `класичен контролер со $scope` синтакса. + - Употреби `controllerAs` наместо `класичен контролер со $scope` синтакса. - `controllerAs` синтакса користи `this` во контролерите што се поврзува со `$scope` - *Зошто?*: `controllerAs` е синтаксички поубав од `$scope`. Вие сеуште може да се поврзете со Прегледот и да ги пристапите `$scope` методите. + *Зошто?*: `controllerAs` е синтаксички поубав од `$scope`. Вие сеуште може да се поврзете со Прегледот и да ги пристапите `$scope` методите. *Зошто?*: Ви помага да избегнете употреба на `$scope` методи во контролерот кога е подобро да ги избегнете или преместите во фабрика. `$scope` може да употребите во фабрика или во контролер само кога ви е потребен. На пример, кога објавувате/пријавувате настани со употреба на [`$emit`](https://docs.angular.org/api/ng/type/$rootScope.Scope#$emit), [`$broadcast`](https://docs.angular.org/api/ng/type/$rootScope.Scope#$broadcast), или [`$on`](https://docs.angular.org/api/ng/type/$rootScope.Scope#$on) подобро е да ги преместите во фабрика и да ја повикате неа во контролерот. @@ -342,7 +336,7 @@ ### controllerAs со vm ###### [Style [Y032](#style-Y032)] - Употребете нова променлива за `this` кога употребувате `controllerAs` синтакса. Одлучете се за постојано име на променлива како на пример `vm`, што е кратеница за ViewModel. - + *Зошто?*: `this` зборот е контекстуален и може да ја промени својата состојба кога се употребува во функција која е во контролерот. Со употреба на нова променлива за `this`, се избегнува овој проблем. ```javascript @@ -366,7 +360,7 @@ ```javascript /* jshint validthis: true */ var vm = this; - ``` + ``` Забелешка: Кога создавате watches во контролерот кога ја користите `controller as` синтаксата, тогаш можете да го надгледувате `vm.*` членот со следната синтакса. (Создавање watches претпазливо бидејќи можат да додадат товар на digest циклусот.) @@ -380,10 +374,10 @@ ### Поврзување на членовите на почеток ###### [Style [Y033](#style-Y033)] - Постави ги членовите кои ќе се поврзат според алфабетски редослед. Наместо да бидат поставени низ кодот во контролерот. - - *Зошто?*: Поставување на поврзувањата на почетокот го прави кодот полесен за читање и помага за да го најдеш кој член од контролерот е поврзан и употребуван во Прегледот. - *Зошто?*: Поставување на анонимни функции во ист ред е лесно, но доколку тие функции се подолги од 1 линија код тогаш може да ја намалат читливоста. Со дефинирање на функциите под поврзаните членови (функциите ќе бидат земени) горе и нивните имплементациите доле го прави кодот полесен за читање. + *Зошто?*: Поставување на поврзувањата на почетокот го прави кодот полесен за читање и помага за да го најдеш кој член од контролерот е поврзан и употребуван во Прегледот. + + *Зошто?*: Поставување на анонимни функции во ист ред е лесно, но доколку тие функции се подолги од 1 линија код тогаш може да ја намалат читливоста. Со дефинирање на функциите под поврзаните членови (функциите ќе бидат земени) горе и нивните имплементациите доле го прави кодот полесен за читање. ```javascript /* избегнувајте*/ @@ -440,8 +434,8 @@ vm.gotoSession = gotoSession; vm.refresh = function() { - /** - * линии + /** + * линии * на * код * нарушуваат @@ -468,19 +462,19 @@ ### Декларација на функции за да ја скрие имплементацијата ###### [Style [Y034](#style-Y034)] - Употребу декларации на функции за да ги скриеш нивните имплементации. Нека членовите за поврзување останат горе. Кога треба да поврзеш функција во контролерот, посочи ја кон декларацијата на таа функција која се појавува подоле во датотеката. Ова е директно поврзано со секцијата Поврзување на членови на почеток. За повеќе детали, проверете го [овој пост](http://www.johnpapa.net/angular-function-declarations-function-expressions-and-readable-code). - + *Зошто?*: Поставување членови за поврзување на почеток го прави кодот полесен за читање и лесно да забележиме кој член од контролерот може да биде повзан и искористен во Прегледот. (Исто како погоре.) *Зошто?*: Поставување на имплементацијата на функцијата подоле во датотеката ја поместува комплексноста надвор од преглед со цел да ги забележиме поважните работи на почетокот. *Зошто?*: Декларации на функции се превземени со цел да не се грижиме дали функцијата е декларирана пред да е дефинирана. (како што е со изрази на функции). - *Зошто?*: Нема потреба да се грижиме дали нашиот код ќе се скрши доколку ги приместиме `var a` пред `var b` доколку `a` зависи од `b`. + *Зошто?*: Нема потреба да се грижиме дали нашиот код ќе се скрши доколку ги приместиме `var a` пред `var b` доколку `a` зависи од `b`. *Зошто?*: Редоследот е значаен со функциски изрази. ```javascript - /** + /** * избегнувајте * употреба на функциски изрази */ @@ -573,7 +567,7 @@ .catch(function(error) { // Интерпретирајте ја грешката // Спремете се со истекување на време? пробување пак? друг сервис? - // Повторно одбиете за корисникот да ја забележи соодветната порака + // Повторно одбиете за корисникот да ја забележи соодветната порака }); }; } @@ -587,7 +581,7 @@ vm.isCreditOk; vm.total = 0; - function checkCredit() { + function checkCredit() { return creditService.isOrderTotalOk(vm.total) .then(function(isOk) { vm.isCreditOk = isOk; }) .catch(showServiceError); @@ -598,15 +592,15 @@ ### Контролерите треба да бидат фокусирани ###### [Style [Y037](#style-Y037)] - - Дефинирајте контролер за преглед, и пробајте да не го искористите истиот за други прегледи. Наместо тоа, преместете ја повторно употребливата логика во фабрики и поставете го тој контролер фокусиран за својот преглед. - + - Дефинирајте контролер за преглед, и пробајте да не го искористите истиот за други прегледи. Наместо тоа, преместете ја повторно употребливата логика во фабрики и поставете го тој контролер фокусиран за својот преглед. + *Why?*: Повторно искористување на контролери со повеќе прегледи е лесно кршливо и тешко за одржување стабилност низ повеќе апликации во е2е тестирање. ### Назначување Контролери ###### [Style [Y038](#style-Y038)] - - Кога контролерот е во пар со прегледот и кога било кој од нив треба да биде повторно искористен од други контролери или прегледи тогаш дефинирај ги контролерите со нивните рута. - - Забелешка: Доколку Прегледот е вчитан преку други начини наместо рути, тогаш искористете ја `ng-controller="Avengers as vm"` синтаксата. + - Кога контролерот е во пар со прегледот и кога било кој од нив треба да биде повторно искористен од други контролери или прегледи тогаш дефинирај ги контролерите со нивните рута. + + Забелешка: Доколку Прегледот е вчитан преку други начини наместо рути, тогаш искористете ја `ng-controller="Avengers as vm"` синтаксата. *Зошто?*: Преку поставување на контролерот во пар во рутата се овозможува други рути да започнат други парови од контролери и прегледи. Кога контролерите се назначени со прегледот со [`ng-controller`](https://docs.angular.org/api/ng/directive/ngController), тогаш тој преглед е секогаш поврзан со истиот контролер. @@ -662,8 +656,8 @@ ### Singletons ###### [Style [Y040](#style-Y040)] - - Сервиси се инстанцирани со `new` зборот, и се употребуваат со `this` за јавни методи и променливи. Бидејќи се слични со фабрики, користете фабрика за конзистентност. - + - Сервиси се инстанцирани со `new` зборот, и се употребуваат со `this` за јавни методи и променливи. Бидејќи се слични со фабрики, користете фабрика за конзистентност. + Забелешка: [Сите Angular сервиси се singletons](https://docs.angular.org/guide/services). Тоа значи дека има само една инстанца од сервис за injector. ```javascript @@ -705,14 +699,14 @@ ### Singletons ###### [Style [Y051](#style-Y051)] - Фабрики се singletons и враќаат објект што ги содржини членовите од тој сервис. - + Забелешка: [Сите Angular сервиси се singletons](https://docs.angular.org/guide/services). ### Членовите за пристап на почеток ###### [Style [Y052](#style-Y052)] - - Изложи ги членовите на сервисот кои треба да се повикаат (неговиот интерфејс) на почетокот, користејќи ја техниката [Revealing Module Pattern](http://addyosmani.com/resources/essentialjsdesignpatterns/book/#revealingmodulepatternjavascript). + - Изложи ги членовите на сервисот кои треба да се повикаат (неговиот интерфејс) на почетокот, користејќи ја техниката [Revealing Module Pattern](http://addyosmani.com/resources/essentialjsdesignpatterns/book/#revealingmodulepatternjavascript). - *Зошто?*: Поставување на повикувачките членови на почетокот го прави кодот полесен за читање и помага при лесно забележување на кои членови можат да се повикаат и мораат да бидат тестирани (и/или излажани при тестирање). + *Зошто?*: Поставување на повикувачките членови на почетокот го прави кодот полесен за читање и помага при лесно забележување на кои членови можат да се повикаат и мораат да бидат тестирани (и/или излажани при тестирање). *Зошто?*: Ова е посебно значајно кога датотеката станува подолга и ја намалува потребата од scrolling за да забележиме што е изложено. @@ -722,10 +716,10 @@ /* избегнувајте */ function dataService() { var someValue = ''; - function save() { + function save() { /* */ }; - function validate() { + function validate() { /* */ }; @@ -750,16 +744,16 @@ //////////// - function save() { + function save() { /* */ }; - function validate() { + function validate() { /* */ }; } ``` - + На овој начин поврзувањата се пресликуваат низ објектот, примитивните вредности не можат да се ажурираат самостојно со употреба на Revealing шаблонот на модули. ![Фабрики искористуваат "Above the Fold"](https://raw.githubusercontent.com/johnpapa/angular-styleguide/master/assets/above-the-fold-2.png) @@ -774,9 +768,9 @@ *Зошто?*: Декларации на функции се поврзани така што нема потреба од грижа доколку се користи функцијата пред да биде дефинирана (како што е примерот со функциски изрази). - *Зошто?*: Никогаш нема да има потреба од грижа со декларации на функции и дали поместување на `var a` пред `var b` ќе го скрши кодот доколку `a` зависи од `b`. + *Зошто?*: Никогаш нема да има потреба од грижа со декларации на функции и дали поместување на `var a` пред `var b` ќе го скрши кодот доколку `a` зависи од `b`. - *Зошто?*: Редоследот е значаен за функциски изрази. + *Зошто?*: Редоследот е значаен за функциски изрази. ```javascript /** @@ -905,7 +899,7 @@ } } ``` - + Забелешка: Податочниот сервис е повикан од потрошувачите како контролери, криејќи ја имплементацијата од нив, како што е покажано подоле. ```javascript @@ -937,7 +931,7 @@ return vm.avengers; }); } - } + } ``` ### Вратете Promise од податочни повици @@ -989,9 +983,9 @@ ## Directives ### Ограничувајте се на 1 на датотека ###### [Style [Y070](#style-Y070)] - - Создадете една директива по датотека. Именувајте ја според директивата. + - Создадете една директива по датотека. Именувајте ја според директивата. - *Зошто?*: Полесно е да ги споите повеќе директиви во една датотека, но потешко да ги разделите тие со цел да бидат споделени низ апликации, модули или само еден модул. + *Зошто?*: Полесно е да ги споите повеќе директиви во една датотека, но потешко да ги разделите тие со цел да бидат споделени низ апликации, модули или само еден модул. *Зошто?*: Една директива по датотека е полесна за одржување. @@ -1049,7 +1043,7 @@ /** * @desc sales директива која може да се користи низ апликацијата во компанијата Acme * @пример
- */ + */ angular .module('sales.widgets') .directive('acmeSalesCustomerInfo', salesCustomerInfo); @@ -1080,7 +1074,7 @@ ### Манипулирајте DOM во директивата ###### [Style [Y072](#style-Y072)] - - Кога манипулирате директно со DOM, употребете директива. Ако можат да се употребат други начини, како CSS за стилови или [анимациски сервиси](https://docs.angular.org/api/ngAnimate), Angular темплејти, [`ngShow`](https://docs.angular.org/api/ng/directive/ngShow) или [`ngHide`](https://docs.angular.org/api/ng/directive/ngHide), тогаш употребете ги тие. На пример, ако директивата само се појавува/исчезнува, тогаш употребете ngHide/ngShow. + - Кога манипулирате директно со DOM, употребете директива. Ако можат да се употребат други начини, како CSS за стилови или [анимациски сервиси](https://docs.angular.org/api/ngAnimate), Angular темплејти, [`ngShow`](https://docs.angular.org/api/ng/directive/ngShow) или [`ngHide`](https://docs.angular.org/api/ng/directive/ngHide), тогаш употребете ги тие. На пример, ако директивата само се појавува/исчезнува, тогаш употребете ngHide/ngShow. *Зошто?*: Манипулација на DOM е тешка да се тестира, дебагира и притоа постојат подобри начини. (на пример CSS, анимации, темплејти) @@ -1088,9 +1082,9 @@ ###### [Style [Y073](#style-Y073)] - Обезбедете краток, уникатен и описен префикс на директивата како `acmeSalesCustomerInfo` што е декларирана во HTML како `acme-sales-customer-info`. - *Зошто?*: Уникатниот краток префикс ја идентификува смислата на директивата и нејзиното потекло. На пример, префиксот `cc-` може да укажува дека директивата дел од CodeCamper апликацијата додека `acme-` може да укажува дека директивата е за компанијата Acme. + *Зошто?*: Уникатниот краток префикс ја идентификува смислата на директивата и нејзиното потекло. На пример, префиксот `cc-` може да укажува дека директивата дел од CodeCamper апликацијата додека `acme-` може да укажува дека директивата е за компанијата Acme. - Забелешка: Избегнувајте `ng-` бидејќи тие се резервирани за директивите на Angular. Проучете најчесто употребувани директиви со цел да избегнувате судири со имињата, како `ion-` за [Ionic Framework](http://ionicframework.com/). + Забелешка: Избегнувајте `ng-` бидејќи тие се резервирани за директивите на Angular. Проучете најчесто употребувани директиви со цел да избегнувате судири со имињата, како `ion-` за [Ionic Framework](http://ionicframework.com/). ### Ограничете се на Елементи и Атрибути ###### [Style [Y074](#style-Y074)] @@ -1132,7 +1126,7 @@
``` - + ```javascript /* препорачано */ angular @@ -1202,8 +1196,8 @@ // Внесување $scope за споредба var vm = this; - vm.min = 3; - + vm.min = 3; + console.log('CTRL: $scope.vm.min = %s', $scope.vm.min); console.log('CTRL: $scope.vm.max = %s', $scope.vm.max); console.log('CTRL: vm.min = %s', vm.min); @@ -1219,7 +1213,7 @@ ``` Забелешка: Можете исто така да го именувате Контролерот кога ќе го вметнете во link функција и пристапите до атрибутите на директивата како својства на контролерот. - + ```javascript // Алтернатива за примерот горе function linkFunc(scope, el, attr, vm) { @@ -1229,7 +1223,7 @@ console.log('LINK: vm.max = %s', vm.max); } ``` - + ###### [Style [Y076](#style-y076)] @@ -1237,7 +1231,7 @@ *Зошто?*: Полесно е да се поврзе надворешниот scope со тој на контролерот во директивата. - Забелешка: `bindToController` беше воведен во Angular 1.3.0. + Забелешка: `bindToController` беше воведен во Angular 1.3.0. ```html
@@ -1285,13 +1279,13 @@ ### Активација на Promises во контролерот ###### [Style [Y080](#style-Y080)] - Решете се со логиката за започнување на контролерот во `activate` функцијата. - + *Зошто?*: Поставување на почетна логика во согласно место во контролерот е полесно за лоцирање, полесно за тестирање и го оневозможува распределувањето на почетната логика низ целиот контролер. *Зошто?*: Функцијата `activate` во контролерот е погодна за повторно да се искористи логиката за освежување на контролер/Преглед, ја држи логиката на едно место, побрзо го прикажува Прегледот, ги олеснува анимациите на `ng-view` или `ui-view` и е елегантно за корисникот. Забелешка: Доколку условно требате да го прекинете решавањето на патеката пред да го користите контролерот, тогаш разгледајте го [route resolve](#style-y081). - + ```javascript /* избегнувајте */ function Avengers(dataservice) { @@ -1436,7 +1430,7 @@ ### Опасно за минифкација ###### [Style [Y090](#style-Y090)] - Избегнувајте употреба на кратенки за декларација на зависности без употреба на безбеден пристап за минификација. - + *Зошто?*: Параметрите на компонентата (e.g. контролер, фабрика, итн) ќе бидат претворени во исчезнати променливи. На пример, `common` и `dataservice` може да постанат `a` или `b` и да не бидат најдени од Angular. ```javascript @@ -1459,7 +1453,7 @@ ### Рачна идентификација на зависности ###### [Style [Y091](#style-Y091)] - Употребете `$inject` за рачна идентификација на вашиоте зависности во Angular компонентите. - + *Зошто?*: Оваа техника се користи во [`ng-annotate`](https://github.com/olov/ng-annotate), што ја препорачувам за автоматизација на создавање на безбедни зависности при минификација. Доколку `ng-annotate` забележи зависност доколку постои, нема да ја повтори. *Зошто?*: Ова ги заштитува вашите зависности од можноста да бидат изгубени при минификација. На пример, `common` и `dataservice` можат да постанат `a` or `b` и да не можат да бидат најдени од Angular. @@ -1470,19 +1464,19 @@ /* избегнувајте */ angular .module('app') - .controller('Dashboard', - ['$location', '$routeParams', 'common', 'dataservice', + .controller('Dashboard', + ['$location', '$routeParams', 'common', 'dataservice', function Dashboard($location, $routeParams, common, dataservice) {} - ]); + ]); ``` ```javascript /* избегнувајте */ angular .module('app') - .controller('Dashboard', + .controller('Dashboard', ['$location', '$routeParams', 'common', 'dataservice', Dashboard]); - + function Dashboard($location, $routeParams, common, dataservice) { } ``` @@ -1494,7 +1488,7 @@ .controller('Dashboard', Dashboard); Dashboard.$inject = ['$location', '$routeParams', 'common', 'dataservice']; - + function Dashboard($location, $routeParams, common, dataservice) { } ``` @@ -1536,7 +1530,7 @@ ### Рачна идентификација на зависностите преку решавање на патеки ###### [Style [Y092](#style-Y092)] - Употребете `$inject` за рачна идентификација на зависностите преку решавање на патеки во Angular компоненти. - + *Зошто?*: Оваа техника ги разделува анонимните функции за решавање на патеката, кое е полесно за читање. *Зошто?*: `$inject` линијата може лесно да го претходи решавачот, подобрувајќи ја безбедноста при минификација. @@ -1568,10 +1562,10 @@ ### ng-annotate ###### [Style [Y100](#style-Y100)] - Употребете [ng-annotate](//github.com/olov/ng-annotate) за [Gulp](http://gulpjs.com) или [Grunt](http://gruntjs.com) и поставете го коментарот `/** @ngInject */` над функциите кои им се потребни автоматизиран dependency injection. - + *Зошто?*: Го заштитува вашиот код од загуба на зависности при минификација. - *Зошто?*: Употреба на [`ng-min`](https://github.com/btford/ngmin) е застарено. + *Зошто?*: Употреба на [`ng-min`](https://github.com/btford/ngmin) е застарено. >Јас преферирам Gulp бидејќи сметам е полесен за пишување, читање и дебагирање. @@ -1644,7 +1638,7 @@ ### Употребете Gulp или Grunt за ng-annotate ###### [Style [Y101](#style-Y101)] - Употребете [gulp-ng-annotate](https://www.npmjs.org/package/gulp-ng-annotate) или [grunt-ng-annotate](https://www.npmjs.org/package/grunt-ng-annotate) во автоматизиран build task. Внесете `/* @ngInject */` пред функцијата која има зависности. - + *Зошто?*: ng-annotate ќе ги фати повеќето зависности, но понекогаш потребни се навестувања во својата `/* @ngInject */` синтакса. Следниот код е припер за gulp задача која употребува ngAnnotate @@ -1677,7 +1671,7 @@ ### Декоратори ###### [Style [Y110](#style-Y110)] - Употребете [decorator](https://docs.angular.org/api/auto/service/$provide#decorator), при конфигурација со употреба на [`$provide`](https://docs.angular.org/api/auto/service/$provide) сервис, на [`$exceptionHandler`](https://docs.angular.org/api/ng/service/$exceptionHandler) сервисот за да извршите лични акции кога ќе се случи исклучок. - + *Зошто?*: Овозможува постојан начин да се справи со исклучоци кои Angular не може да ги фати во development-time или run-time. Забелешка: Друга опција е да се прескокне сервисот наместо да се користи декоратор. Ова е добра опција, но доколку сакате да го задржите стандардното однесување и проширите, тогаш препорачливо е да користите декоратор. @@ -1699,9 +1693,9 @@ function extendExceptionHandler($delegate, toastr) { return function(exception, cause) { $delegate(exception, cause); - var errorData = { - exception: exception, - cause: cause + var errorData = { + exception: exception, + cause: cause }; /** * Може да ја додадете грешката на колекцијата на сервиси, @@ -1795,10 +1789,10 @@ - Употребете самостојни имиња за сите компоненти следејќи го шаблонот кој ја опишува функцијата и после (опционално) неговиот тип. Мојот препорачан шаблон е `feature.type.js`. Постојат две имиња за повеќето датотеки: * името на датотеката (`avengers.controller.js`) * регистрираната компонента во Angular (`AvengersController`) - + *Зошто?*: Конвенциите при именување им помага на тимот за конзистентен начин да ги најдат компонентите при прв поглед. Конзистентност во проект е значајно. Конзистентност во тимот е важно. Конзистентност низ компанијата обезбедува огромна ефикасност. - *Зошто?*: Конвенцијата при именување треба едностанво да ви помогне побрзо да го најдете кодот и полесно да го разберете. + *Зошто?*: Конвенцијата при именување треба едностанво да ви помогне побрзо да го најдете кодот и полесно да го разберете. ### Имиња на датотеки по функција ###### [Style [Y121](#style-Y121)] @@ -1839,7 +1833,7 @@ // Константи constants.js - + // Дефиниција на модули avengers.module.js @@ -1849,7 +1843,7 @@ // Конфигурација avengers.config.js - + // Директиви avenger-profile.directive.js avenger-profile.directive.spec.js @@ -1868,7 +1862,7 @@ ### Имиња на датотеки за тестови ###### [Style [Y122](#style-Y122)] - - Имињата на тестовите се слични со компонентата што ја тестираат со додавање на суфикс `spec`. + - Имињата на тестовите се слични со компонентата што ја тестираат со додавање на суфикс `spec`. *Зошто?*: Обезбедува конзистентен начин за лесно препознавање компоненти. @@ -1904,7 +1898,7 @@ function HeroAvengersController(){ } ``` - + ### Суфикс на името на контролерот ###### [Style [Y124](#style-Y124)] - Додадете суфикс `Controller` на името на Контролерот. @@ -1956,7 +1950,7 @@ * препорачано */ - // avenger-profile.directive.js + // avenger-profile.directive.js angular .module .directive('xxAvengerProfile', xxAvengerProfile); @@ -1969,7 +1963,7 @@ ### Модули ###### [Style [Y127](#style-Y127)] - Кога постојат повеќе модули, името на главниот модул е `app.module.js` додека другите зависни модули се именувани според тоа што претставуваат. На пример, админ модул е именувам `admin.module.js`. Соодветните регистрирани имиња на модули би биле `app` и `admin`. - + *Зошто?*: Обезбедува конзистентност за повеќе модуларни апликации како и проширување до огромни апликации. *Зошто?*: Обезбедува лесен начин да се автоматизираат задачите за создавање на дефинициите на модулите, па потоа сите останати angular датотеки (пакување на датотеки). @@ -1991,12 +1985,12 @@ ## Application Structure LIFT Principle ### LIFT ###### [Style [Y140](#style-Y140)] - - Поставете ја пликацијата така што `L` (брзо лоцирање на кодот), `I` (идентификација на кодот со поглед), `F` (најрамна структура што можете) и `T` (обидете се да останете DRY). Структурата треба да ги задоволува овие 4 основни водичи. + - Поставете ја пликацијата така што `L` (брзо лоцирање на кодот), `I` (идентификација на кодот со поглед), `F` (најрамна структура што можете) и `T` (обидете се да останете DRY). Структурата треба да ги задоволува овие 4 основни водичи. *Зошто LIFT?*: Обезбедува конзистентна структура која лесно се скалира, која е модуларна, и лесно може да ја зголеми ефикасноста на програмерите преку брзо лоцирање на кодот. Друг начин да ја проверите вашата структура е да се запрашате: Колку брзо можете да ги отворите и работите во сите датотека со одредена функција? Кога забележувам дека мојата структура е незадоволителна, се навраќам на LIFT водичите - + 1. `L` (лоцирање на вашиот код е лесно) 2. `I` (идентифицирање на кодот со поглед) 3. `F` (рамна структура колку што можеме) @@ -2056,7 +2050,7 @@ ### Изглед ###### [Style [Y151](#style-Y151)] - - Поставете компоненти која го отсликуваат целокупниот изглед на апликацијата во папката `layout`. Овде може да имаме поделеност на посебни секции од прегледот и контролер кој ќе биде контејнер за неговата апликација, навигација, мениа, области со содржина и други региони. + - Поставете компоненти која го отсликуваат целокупниот изглед на апликацијата во папката `layout`. Овде може да имаме поделеност на посебни секции од прегледот и контролер кој ќе биде контејнер за неговата апликација, навигација, мениа, области со содржина и други региони. *Зошто?*: Го организира целиот изглед во единствено место кое може да се употребува низ целата апликација. @@ -2064,7 +2058,7 @@ ###### [Style [Y152](#style-Y152)] - Создадете папки според нивната функција. Кога папката ќе порасне 7+ датотеки, почнете да размислувате за нови папки. Вашиот праг може да биде различен, така да поставете како што е препорачано. - *Зошто?*: Програмерот може да го лоцира кодот, идентификува секоја датотека што претставува, структурата останува рамна и не постојат повторувачки или непотребни имиња. + *Зошто?*: Програмерот може да го лоцира кодот, идентификува секоја датотека што претставува, структурата останува рамна и не постојат повторувачки или непотребни имиња. *Зошто?*: LIFT водичите се покриени. @@ -2080,35 +2074,35 @@ app/ app.module.js app.config.js - components/ - calendar.directive.js - calendar.directive.html - user-profile.directive.js - user-profile.directive.html + components/ + calendar.directive.js + calendar.directive.html + user-profile.directive.js + user-profile.directive.html layout/ - shell.html + shell.html shell.controller.js - topnav.html - topnav.controller.js + topnav.html + topnav.controller.js people/ attendees.html - attendees.controller.js + attendees.controller.js people.routes.js speakers.html speakers.controller.js speaker-detail.html speaker-detail.controller.js - services/ - data.service.js + services/ + data.service.js localstorage.service.js - logger.service.js + logger.service.js spinner.service.js sessions/ - sessions.html + sessions.html sessions.controller.js sessions.routes.js session-detail.html - session-detail.controller.js + session-detail.controller.js ``` ![Пробна апликација пример](https://raw.githubusercontent.com/johnpapa/angular-styleguide/master/assets/modularity-2.png) @@ -2116,48 +2110,48 @@ Забелешка: Не употребувајте структура со папка-по-тип. Со ова ќе се движите низ повеќе папки кога работите на функционалност што станува потешко како што апликацијата има повеќе од 5, 10 или 25 прегледи и контролери (за други функционалности), а со тоа и потешко за лоцирање на датотеките на таа функционалност. ```javascript - /* + /* * избегнувајте * алтернативен папка-по-тип * Препорачаувам "папка-по-функционалност" */ - + app/ app.module.js app.config.js app.routes.js controllers/ - attendees.js - session-detail.js - sessions.js - shell.js - speakers.js - speaker-detail.js - topnav.js - directives/ - calendar.directive.js - calendar.directive.html - user-profile.directive.js - user-profile.directive.html - services/ - dataservice.js + attendees.js + session-detail.js + sessions.js + shell.js + speakers.js + speaker-detail.js + topnav.js + directives/ + calendar.directive.js + calendar.directive.html + user-profile.directive.js + user-profile.directive.html + services/ + dataservice.js localstorage.js - logger.js + logger.js spinner.js views/ - attendees.html + attendees.html session-detail.html - sessions.html - shell.html - speakers.html + sessions.html + shell.html + speakers.html speaker-detail.html - topnav.html - ``` + topnav.html + ``` **[Назад кон содржината](#table-of-contents)** ## Modularity - + ### Многу мали, само содржани модулу ###### [Style [Y160](#style-Y160)] - Создадете мали модули кои содржат една одговорност. @@ -2208,7 +2202,7 @@ Забелешка: Ова е стратегија за конзистентност. Постојат многу добри опции. Одберете една што е конзистентна, што ги следи Angular правилата за зависности, а лесно за одржување и скалабилност. - > Моите структури се разликуваат малку низ проекти, но сите ги запазуваат правилата за структура и модуларност. Имплементацијата може да се разликува во зависност од функционалностите и тимот. Со други зборови, не се засегајте на буквалната структура се додека ја оправдува вашата структура за конзистентност, одржливост и ефикасност. + > Моите структури се разликуваат малку низ проекти, но сите ги запазуваат правилата за структура и модуларност. Имплементацијата може да се разликува во зависност од функционалностите и тимот. Со други зборови, не се засегајте на буквалната структура се додека ја оправдува вашата структура за конзистентност, одржливост и ефикасност. > Во мали апликации можете да ги поставите сите заеднички зависности во апликацискиот модул каде функционалните зависности немаат директни зависности. Ова овозможува полесно одржување кај мали апликации, но станува потешко да се реискористуват тие модули надвор од оваа апликација. @@ -2227,7 +2221,7 @@ .module('app') .config(configure); - configure.$inject = + configure.$inject = ['routerHelperProvider', 'exceptionHandlerProvider', 'toastr']; function configure (routerHelperProvider, exceptionHandlerProvider, toastr) { @@ -2347,13 +2341,13 @@ ###### [Style [Y194](#style-Y194)] - Употребете [PhantomJS](http://phantomjs.org/) за да ги извршувате тестовите на вашиот сервер. - *Зошто?*: PhantomJS е пребарувач кој ги започнува тестовите без потреба од кориснички интерфејс. Така што нема потреба да инсталирате Chrome, Safari, IE, или други пребарувачи на вашиот сервер. + *Зошто?*: PhantomJS е пребарувач кој ги започнува тестовите без потреба од кориснички интерфејс. Така што нема потреба да инсталирате Chrome, Safari, IE, или други пребарувачи на вашиот сервер. Забелешка: Сепак потребно е да ги извршите тестовите на сите пребарувачи во вашата околина како и вашата целна група. ### Анализа на код ###### [Style [Y195](#style-Y195)] - - Извршете JSHint на вашиот код. + - Извршете JSHint на вашиот код. *Зошто?*: Тестовите се код. JSHint лесно ги прикажува грешките во квалитетот на кодот што може да предизвика неправилно извршување на тестовите. @@ -2380,7 +2374,7 @@ - Поставете ги датотеките за unit тестови (спецификација) една поред друга во вашиот клиентски код. Поставете ги спецификациите кои ја покриваат интеграцијата со серверот или тестираат повеќе компоненти во посебна `tests` папка. - *Зошто?*: Unit тестови имаат директна поврзаност со специфична компонента и датотека во изворниот код. + *Зошто?*: Unit тестови имаат директна поврзаност со специфична компонента и датотека во изворниот код. *Зошто?*: Полесно е временски да ги ажурирате бидејќи секогаш се забележителни. Кога кодирате, дали TDD или тестирате пред или после развојот, специкациите се секогаш една поред друга и никогаш нема да се изгубат, што значи дека треба да се одржуваат притоа подобрувајќи ја покриеноста на кодот. @@ -2468,7 +2462,7 @@ /** * @name logError * @desc Logs errors - * @param {String} msg Message to log + * @param {String} msg Message to log * @returns {String} * @memberOf Factories.Logger */ @@ -2700,13 +2694,13 @@ angular ### Sublime Text ###### [Style [Y250](#style-Y250)] - - Angular кратки кодови кои ги следат овие водичи и стилови на код. + - Angular кратки кодови кои ги следат овие водичи и стилови на код. - - Симнете ги [Sublime Angular кратки кодови](assets/sublime-angular-snippets?raw=true) + - Симнете ги [Sublime Angular кратки кодови](assets/sublime-angular-snippets?raw=true) - Поставете ги во вашата Packages папка - - Рестартирајте го Sublime + - Рестартирајте го Sublime - Во JavaScript датотека напишете ја следната команда и потоа кликнете на `TAB` - + ```javascript ngcontroller // создава Angular контролер ngdirective // создава Angular директива @@ -2731,7 +2725,7 @@ angular ###### [Style [Y252](#style-Y252)] - Angular кратки кодови и датотечни шаблони кои ги следат овие стилови и водичи на код. Можете да ги внесете во вашите WebStorm подесувања: - - Симнете ги [WebStorm Angular датотечни шаблони и кратки кодови](../assets/webstorm-angular-file-template.settings.jar?raw=true) + - Симнете ги [WebStorm Angular датотечни шаблони и кратки кодови](../assets/webstorm-angular-file-template.settings.jar?raw=true) - Отворете го WebStorm и одберете го `File` менито - Одберете го `Import Settings` - Одберете ја датотеката и кликнете `OK` @@ -2756,7 +2750,7 @@ angular - Отворете го Atom, потоа отворете го Package Manager (Packages -> Settings View -> Install Packages/Themes) - Побарајте го пакетот 'angular-styleguide-snippets' - Кликнете на 'Install' за да го инсталирате пакетот - + - Во JavaScript датотека напишете ги следните команди и потоа кликнете `TAB` ```javascript @@ -2865,7 +2859,7 @@ angular - Употребете автоматизирање на тестови за вклучување на сите `*.module.js` датотеки пред останатите JavaScript датотеки од апликацијата. - *Зошто?*: На Angular му требаат дефинициите на модулите да бидат регистрирани пред да бидат употребени. + *Зошто?*: На Angular му требаат дефинициите на модулите да бидат регистрирани пред да бидат употребени. *Зошто?*: Именување на модули со слична шема како `*.module.js` е полесно за нивно превземање со glob и да ги постави први. @@ -2901,7 +2895,7 @@ angular *Со придонесување до ова складиште, се придржувате вашата содржина да подлежи на лиценцата на ова складиште.* ### Процес - 1. Дискусирајте за промените во Github Issue. + 1. Дискусирајте за промените во Github Issue. 2. Отворете Pull Request, поставете референца до Issue и објаснете ја промената и како додава на вредност. 3. Pull Request ќе биде оценето и биде или споено или одбиено. diff --git a/i18n/ru-RU.md b/i18n/ru-RU.md index 4d02b836..5ca57cd2 100644 --- a/i18n/ru-RU.md +++ b/i18n/ru-RU.md @@ -2,17 +2,14 @@ *Angular соглашения по стилям для команд разработчиков, предложенные [@john_papa](//twitter.com/john_papa)* -*Перевел на русский язык [Василий Мажекин](https://github.com/mazhekin)* - ->The [original English version](http://jpapa.me/ngstyles) is the source of truth, as it is maintained and updated first. - Если вам нужны стандарты написания кода, соглашения, и руководства структурирования приложений AngularJS, то вы находитесь в правильном месте. Эти соглашения основаны на моем опыте программирования на [AngularJS](//angularjs.org), на моих презентациях [Pluralsight training courses](http://pluralsight.com/training/Authors/Details/john-papa), а также на совместной работе в командах разработчиков. -Главной целью этого документа является желание предоставить вам наиболее полные инструкции для построения приложений AngularJS. Рекомендуя данные соглашения, я стараюсь акцентировать ваше внимание на цели и причины, зачем их нужно придерживаться. +Главной целью этого документа является желание предоставить вам наиболее полные инструкции для построения приложений AngularJS. Рекомендуя данные соглашения, я стараюсь акцентировать ваше внимание на цели и причины, зачем их нужно придерживаться. + >Если это руководство вам понравится, то вы можете также оценить мой курс [Angular Patterns: Clean Code](http://jpapa.me/ngclean), который размещен на сайте Pluralsight. [![Angular Patterns: Clean Code](https://raw.githubusercontent.com/johnpapa/angularjs-styleguide/master/assets/ng-clean-code-banner.png)](http://jpapa.me/ngclean) - + ## Признательность сообществу и коллегам Никогда не работайте в вакууме. Я считаю AngularJS-сообщество невероятно открытым, которое активно обменивается опытом и заботится об этом. Также как и мой друг Todd Motto (отличный Angular эксперт), я работал со многими стилями и соглашениями. Мы с ним сходимся во многом, но иногда и противоречим друг другу. Я предлагаю вам ознакомиться с курсом [Todd's guidelines](https://github.com/toddmotto/angularjs-styleguide) дабы почувствовать разницу подходов. @@ -21,7 +18,7 @@ ## Смотрите стили и шаблоны в приложении-примере Пока данное руководство объясняет *что*, *почему* и *как*, я сразу же показываю, как это работает на практике. Все, что я предлагаю и описываю сопровождается примером-приложения, которое соблюдает и демонстрирует приведенные стили и шаблоны. Вы можете найти [пример приложения (имя modular) здесь](https://github.com/johnpapa/ng-demos) в папке `modular`. Свободно скачивайте, клонируйте и перемещайте эти примеры в свои хранилища. [Инструкциии по запуску примеров находятся в файлах readme](https://github.com/johnpapa/ng-demos/tree/master/modular). -## Переводы +## Переводы [Переводы данного руководства по Angular-стилям](https://github.com/johnpapa/angularjs-styleguide/tree/master/i18n) поддерживаются соообществом разработчиков и могут быть найдены здесь. ## Table of Contents @@ -45,7 +42,7 @@ 1. [Startup Logic (Логика Запуска Приложения)](#startup-logic) 1. [Angular $ Wrapper Services (Angular и Интерфейсные Сервисы)](#angular--wrapper-services) 1. [Testing (Тестирование)](#testing) - 1. [Animations (Анимации)](#animations) + 1. [Animations (Анимации)](#animations) 1. [Comments (Комментарии)](#comments) 1. [JSHint](#js-hint) 1. [Constants (Константы)](#constants) @@ -59,7 +56,7 @@ ## Single Responsibility -### Правило 1 +### Правило 1 ###### [Style [Y001](#style-y001)] - Определяйте 1 компонент в одном файле. @@ -72,7 +69,7 @@ .module('app', ['ngRoute']) .controller('SomeController', SomeController) .factory('someFactory', someFactory); - + function SomeController() { } function someFactory() { } @@ -106,17 +103,17 @@ angular .module('app') .factory('someFactory', someFactory); - + function someFactory() { } ``` **[К Содержанию](#table-of-contents)** ## IIFE -### Замыкания JavaScript +### Замыкания JavaScript ###### [Style [Y010](#style-y010)] - - Оборачивайте компоненты Angular в Немедленно Исполняемые Функции(IIFE - Immediately Invoked Function Expression). + - Оборачивайте компоненты Angular в Немедленно Исполняемые Функции(IIFE - Immediately Invoked Function Expression). *Зачем?*: IIFE удаляют переменные из глобальной области видимости. Этот прием не дает существовать переменным и функциям дольше, чем это необходимо в глобальной области видимости. Иначе это может вызвать непредсказуемые коллизии во время исполнения всего приложения. @@ -143,9 +140,9 @@ ```javascript /** - * рекомендовано + * рекомендовано * - * больше нет глобальных переменных + * больше нет глобальных переменных */ // logger.js @@ -171,7 +168,7 @@ })(); ``` - - Замечание: Только для краткости, в остальных примерах мы не будем прописывать синтаксис с функциями IIFE. + - Замечание: Только для краткости, в остальных примерах мы не будем прописывать синтаксис с функциями IIFE. - Замечание: IIFE не дает тестировать приватный код, так как предотвращает доступ к нему, например, регулярные выражения или вспомогательные функции, которые нужно оттестировать в модульных тестах (unit test) напрямую. Как выход, вы можете тестировать через специальные методы, используемые только в тестах (accessible members) или выставить нужные внутренние функции в собственном компоненте. Например, поместите вспомогательные функции, регулярные выражения или константы в собственную фабрику(factory) или константу(constant). @@ -189,10 +186,10 @@ ### Сеттеры (Setters) ###### [Style [Y021](#style-y021)] - - Объявляйте модули без переменных, используйте сеттеры (setters). + - Объявляйте модули без переменных, используйте сеттеры (setters). *Почему?*: Так как обычно в файле 1 компонент, поэтому вряд ли потребуется вводить переменную для модуля. - + ```javascript /* избегайте этого */ var app = angular.module('app', [ @@ -248,12 +245,12 @@ *Почему?*: Модуль должен быть определен только один раз, а потом используйте его во всех остальных местах. - Используйте `angular.module('app', []);` для определения модуля. - - Используйте `angular.module('app');` чтобы получить модуль. + - Используйте `angular.module('app');` чтобы получить модуль. ### Именованные или Анонимные Функции ###### [Style [Y024](#style-y024)] - - Используйте именованные функции, не передавайте анонимные функции обратного вызова в качестве параметров. + - Используйте именованные функции, не передавайте анонимные функции обратного вызова в качестве параметров. *Почему?*: Так вы производите более читаемый код, его легче отлаживать, и это уменьшает число вложенных функций обратного вызова. @@ -292,7 +289,7 @@ ### Синтаксис controllerAs в представлении ###### [Style [Y030](#style-y030)] - - Используйте синтаксис [`controllerAs`](http://www.johnpapa.net/do-you-like-your-angular-controllers-with-or-without-sugar/), который работает поверх синтаксиса `классический контроллер со $scope`. + - Используйте синтаксис [`controllerAs`](http://www.johnpapa.net/do-you-like-your-angular-controllers-with-or-without-sugar/), который работает поверх синтаксиса `классический контроллер со $scope`. *Почему?*: Контроллер создается, как JavaScript-объект с ключевым словом "new" и затем предоставляется этот единственный экземпляр объекта. То есть синтаксис `controllerAs` намного ближе и похожее на конструктор языка JavaScript, чем `классический синтаксис $scope`. @@ -317,11 +314,11 @@ ### Синтаксис controllerAs в контроллере ###### [Style [Y031](#style-y031)] - - Используйте синтаксис `controllerAs` поверх синтаксиса `классический контроллер со $scope`. + - Используйте синтаксис `controllerAs` поверх синтаксиса `классический контроллер со $scope`. - Синтаксис `controllerAs` использует внутри контроллеров ключевую переменную `this`, которая привязывается к `$scope`. - *Почему?*: `controllerAs` - это только синтаксический сахар поверх `$scope`. Вы все равно можете использовать связывание в представлениях и все равно имеете доступ к методам `$scope`. + *Почему?*: `controllerAs` - это только синтаксический сахар поверх `$scope`. Вы все равно можете использовать связывание в представлениях и все равно имеете доступ к методам `$scope`. *Почему?*: Избавляет от искушения использования методов `$scope` внутри контроллера, когда это не требуется явно, и это позволяет перенести методы в фабрику(factory). Предпочтительнее использовать `$scope` в фабрике, а в контроллере только если это действительно необходимо. Например, когда мы подписываемся и рассылаем события с помощью [`$emit`](https://docs.angularjs.org/api/ng/type/$rootScope.Scope#$emit), [`$broadcast`](https://docs.angularjs.org/api/ng/type/$rootScope.Scope#$broadcast), or [`$on`](https://docs.angularjs.org/api/ng/type/$rootScope.Scope#$on) перенесите эти сервисы в фабрику, и вызывайте методы фабрики в контроллере. @@ -345,7 +342,7 @@ ###### [Style [Y032](#style-y032)] - Сохраните `this` в переменную, когда используете синтаксис `controllerAs`. Выберите постоянное имя для переменной, такое как `vm`, что будет значить ViewModel. - + *Почему?*: Ключевое слово `this` контекстное, и когда его потребуется использовать внутри любой другой функции контроллера, то его содержимое будет другим. Сохранение `this` в переменной `vm` позволит избежать этих проблем. ```javascript @@ -397,7 +394,7 @@ *Почему?*: Размещение привязываемых членов наверху, упрощает чтение и позволяет мгновенно определить, какие члены контроллера привязаны и используются в представлении. - *Почему?*: Написание анонимных функций по месту использования может конечно и проще, но когда такие функции содержат много строк кода, то это значительно снижает читабельность кода. Определяйте функции ниже привязываемых членов, тем самым вы перенесете детали реализации вниз отдельно. Функции определяйте как hoisted, то есть они будут подняты наверх области видимости. А привязываемые члены наверху повысят читабельность кода. + *Почему?*: Написание анонимных функций по месту использования может конечно и проще, но когда такие функции содержат много строк кода, то это значительно снижает читабельность кода. Определяйте функции ниже привязываемых членов, тем самым вы перенесете детали реализации вниз отдельно. Функции определяйте как hoisted, то есть они будут подняты наверх области видимости. А привязываемые члены наверху повысят читабельность кода. ```javascript /* избегайте этого */ @@ -455,8 +452,8 @@ vm.gotoSession = gotoSession; vm.refresh = function() { /** - * эти - * строки + * эти + * строки * кода * ухудшают * читабельность @@ -484,19 +481,19 @@ - Используйте определения функций для скрытия деталей реализации. Держите свои привязываемые члены наверху. Если нужно в контроллере сделать функцию привязываемой, укажите это в группе привязываемых членов и ссылайтесь на данную функцию, которая реализована ниже. Это подробно описано в секции Привязываемые Члены Сверху. Подробнее смотрите [здесь](http://www.johnpapa.net/angular-function-declarations-function-expressions-and-readable-code). - *Почему?*: Размещение привязываемых членов наверху делает код читабельнее, и позволяет мгновенно определить, какие члены привязаны и используются в представлении. (Выше описано тоже самое.) + *Почему?*: Размещение привязываемых членов наверху делает код читабельнее, и позволяет мгновенно определить, какие члены привязаны и используются в представлении. (Выше описано тоже самое.) *Почему?*: Размещение деталей реализации функции внизу скрывает эту сложность ниже и таким образом все важные вещи находятся на видном месте сверху. *Почему?*: Функции определены как hoisted (определены в самом верху области видимости), поэтому не надо заботиться об их использовании перед объявлением, так как это было бы с объявлениями выражений функций (function expressions). - *Почему?*: Вам не надо волноваться, о том в каком порядке объявлены функции. Также как и изменение порядка функций не будет ломать код из-за зависимостей. + *Почему?*: Вам не надо волноваться, о том в каком порядке объявлены функции. Также как и изменение порядка функций не будет ломать код из-за зависимостей. *Почему?*: С выражениями функций(function expressions) порядок будет критичен. ```javascript - /** - * избегайте этого + /** + * избегайте этого * Использование выражений функций (function expressions). */ function Avengers(dataservice, logger) { @@ -604,7 +601,7 @@ vm.isCreditOk; vm.total = 0; - function checkCredit() { + function checkCredit() { return creditService.isOrderTotalOk(vm.total) .then(function(isOk) { vm.isCreditOk = isOk; }) .catch(showServiceError); @@ -617,7 +614,7 @@ - Определяйте контроллер для одного представления, и не пытайтесь использовать этот контроллер для других представлений. Вместо этого, выносите повторно используемую логику в фабрики. Старайтесь держать контроллер простым и сфокусированным только на свое представление. - *Почему?*: Использование контроллера с несколькими представлениями хрупко и ненадежно. А для больших приложений требуется хорошее покрытие тестами end to end (e2e) для проверки стабильности. + *Почему?*: Использование контроллера с несколькими представлениями хрупко и ненадежно. А для больших приложений требуется хорошее покрытие тестами end to end (e2e) для проверки стабильности. ### Получение Контроллеров ###### [Style [Y038](#style-y038)] @@ -626,7 +623,7 @@ Замечание: Если представление загружается не через маршрут, тогда используйте синтаксис `ng-controller="Avengers as vm"`. - *Почему?*: Указание экземпляра контроллера в определении маршрута позволяет различным маршрутам вызывать различные пары контроллеров и представлений. А когда контроллеры указаны в представлении с помощью [`ng-controller`](https://docs.angularjs.org/api/ng/directive/ngController), то представление будет всегда ассоциировано с одним и тем же контроллером. + *Почему?*: Указание экземпляра контроллера в определении маршрута позволяет различным маршрутам вызывать различные пары контроллеров и представлений. А когда контроллеры указаны в представлении с помощью [`ng-controller`](https://docs.angularjs.org/api/ng/directive/ngController), то представление будет всегда ассоциировано с одним и тем же контроллером. ```javascript /* избегайте этого - когда используется маршрут и необходимо динамическое назначение контроллера и представления */ @@ -720,7 +717,7 @@ ### Единственная Обязанность (Single Responsibility) ###### [Style [Y050](#style-y050)] - - Фабрики дожны иметь [единственную обязанность](http://en.wikipedia.org/wiki/Single_responsibility_principle), это следует из их контекста. Если фабрика начинает превышать ту цель для которой она создана, то нужно создать другую фабрику. + - Фабрики дожны иметь [единственную обязанность](http://en.wikipedia.org/wiki/Single_responsibility_principle), это следует из их контекста. Если фабрика начинает превышать ту цель для которой она создана, то нужно создать другую фабрику. ### Синглтон ###### [Style [Y051](#style-y051)] @@ -732,22 +729,22 @@ ### Доступные Члены Наверх ###### [Style [Y052](#style-y052)] - - Помещайте вызываемые члены сервиса (интерфейс) наверх, используя технику [Revealing Module Pattern](http://addyosmani.com/resources/essentialjsdesignpatterns/book/#revealingmodulepatternjavascript). + - Помещайте вызываемые члены сервиса (интерфейс) наверх, используя технику [Revealing Module Pattern](http://addyosmani.com/resources/essentialjsdesignpatterns/book/#revealingmodulepatternjavascript). + + *Почему?*: Размещение вызываемых членов в верхней части улучшает читабельность и дает вам возможность быстро определить, какие члены сервиса могут быть вызваны и должны быть модульно оттестированы (либо фиктивно имплементированы - mocked). - *Почему?*: Размещение вызываемых членов в верхней части улучшает читабельность и дает вам возможность быстро определить, какие члены сервиса могут быть вызваны и должны быть модульно оттестированы (либо фиктивно имплементированы - mocked). - *Почему?*: Это особенно полезно, когда файл становится очень длинным, и вынуждает прокручивать текст кода, чтобы посмотреть, какие методы или свойства сервис предоставляет. - *Почему?*: Размещение функций в обычном прямом порядке может быть и проще, но когда эти функции становятся многострочными, это снижает читабельность и вынуждает много скроллить. Определяя вызываемый интерфейс(в виде возвращаемого сервиса), вы убираете детали реализации вниз. А размещенный сверху интерфейс улучшает читабельность. + *Почему?*: Размещение функций в обычном прямом порядке может быть и проще, но когда эти функции становятся многострочными, это снижает читабельность и вынуждает много скроллить. Определяя вызываемый интерфейс(в виде возвращаемого сервиса), вы убираете детали реализации вниз. А размещенный сверху интерфейс улучшает читабельность. ```javascript /* избегайте этого */ function dataService() { var someValue = ''; - function save() { + function save() { /* */ }; - function validate() { + function validate() { /* */ }; @@ -772,11 +769,11 @@ //////////// - function save() { + function save() { /* */ }; - function validate() { + function validate() { /* */ }; } @@ -791,7 +788,7 @@ - Используйте определения функций, чтобы скрыть детали реализации. Держите вызываемые члены фабрики в верхней части. Свяжите их с определениями функций, которые расположены ниже в файле. Подробную информацию смотрите [здесь](http://www.johnpapa.net/angular-function-declarations-function-expressions-and-readable-code). - *Почему?*: Размещение вызываемых членов в верхней части улучшает читабельность и помогает быстро определить, какие функции фабрики могут быть вызваны извне. + *Почему?*: Размещение вызываемых членов в верхней части улучшает читабельность и помогает быстро определить, какие функции фабрики могут быть вызваны извне. *Почему?*: Размещение функций с деталями реализации в нижней части файла выносит сложные вещи из поля зрения, так что только важные детали вы видите в верхней части файла. @@ -891,11 +888,11 @@ ### Отделите вызовы данных ###### [Style [Y060](#style-y060)] - - Делайте рефакторинг логики работы с данными и взаимодействия этих данных с фабрикой. Создавайте сервисы данных, ответственных за вызовы XHR, локальное хранилище(local storage), работу с памятью или за любые другие операции с данными. + - Делайте рефакторинг логики работы с данными и взаимодействия этих данных с фабрикой. Создавайте сервисы данных, ответственных за вызовы XHR, локальное хранилище(local storage), работу с памятью или за любые другие операции с данными. *Почему?*: Ответственность контроллера - это предоставление или сбор информации для представления. Он не должен заботиться о том, как работать с данными, он только должен знать кого попросить об этом. В сервисы для данных переносится вся логика работы с данными. Это делает контроллер более простым и более сфокусированным для работы с представлением. - *Почему?*: Это позволяет более проще тестировать (фиктивно или реально) вызовы данных в контроллере, который использует сервис для данных. + *Почему?*: Это позволяет более проще тестировать (фиктивно или реально) вызовы данных в контроллере, который использует сервис для данных. *Почему?*: Реализация сервиса данных может иметь очень специфичный код для операций с хранилищем данных. Могут использоваться заголовки для взаимодействовия с данными, или другие сервисы типа $http. Логика в сервисе данных инкапсулируется в одном месте и скрывает реализацию для внешних потребителей (контроллеров), также будет гораздо проще изменить реализацию в случае необходимости. @@ -929,7 +926,7 @@ } } ``` - + Замечание: Сервис данных вызывается потребителем (контроллером), и скрывает реализацию от потребителя. Это показано ниже. ```javascript @@ -961,7 +958,7 @@ return vm.avengers; }); } - } + } ``` ### Возвращение Объекта Promise для Контроллера @@ -969,7 +966,7 @@ - Если сервис данных возвращает promise типа $http, то в вызывающей функции возвращайте promise тоже. - *Почему?*: Вы можете объединить в цепочку объекты promise, и после того как вызов данных закончится, выполнить дальнейшие действия для принятия или отклонения объекта promise. + *Почему?*: Вы можете объединить в цепочку объекты promise, и после того как вызов данных закончится, выполнить дальнейшие действия для принятия или отклонения объекта promise. ```javascript /* рекомендовано */ @@ -979,8 +976,8 @@ function activate() { /** * Шаг 1 - * Запрашиваем функцию getAvengers function - * для получения данных и ждем promise + * Запрашиваем функцию getAvengers function + * для получения данных и ждем promise */ return getAvengers().then(function() { /** @@ -994,7 +991,7 @@ function getAvengers() { /** * Шаг 2 - * Запрашиваем сервис для данных + * Запрашиваем сервис для данных * и ждем promise */ return dataservice.getAvengers() @@ -1012,7 +1009,7 @@ **[К Содержанию](#table-of-contents)** ## Directives -### Одна Директива - Один Файл +### Одна Директива - Один Файл ###### [Style [Y070](#style-y070)] - Создавайте только одну директиву в файле. Называйте файл именем директивы. @@ -1074,7 +1071,7 @@ /** * @desc директива продажи, которая может быть использована везде в модуле продаж компании Acme * @example
- */ + */ angular .module('sales.widgets') .directive('acmeSalesCustomerInfo', salesCustomerInfo); @@ -1101,12 +1098,12 @@ } ``` - Замечание: Существует много способов для именования директив, особенно это зависит от широты области использования (локально или глобально). Выбирайте тот способ, который определяет директиву и ее файл четко и ясно. Несколько примеров будет ниже, но в основном смотрите рекомендации в секции именований. + Замечание: Существует много способов для именования директив, особенно это зависит от широты области использования (локально или глобально). Выбирайте тот способ, который определяет директиву и ее файл четко и ясно. Несколько примеров будет ниже, но в основном смотрите рекомендации в секции именований. ### Манипулирование Элементами DOM в Директиве ###### [Style [Y072](#style-y072)] - - Используйте директивы, если нужно манипулировать элементами DOM напрямую. Но если существуют альтернативные способы, то используйте лучше их. Например, для изменения стилей используйте CSS, для эффектов [сервисы анимации](https://docs.angularjs.org/api/ngAnimate), для управления видимостью используйте [`ngShow`](https://docs.angularjs.org/api/ng/directive/ngShow) и [`ngHide`](https://docs.angularjs.org/api/ng/directive/ngHide). + - Используйте директивы, если нужно манипулировать элементами DOM напрямую. Но если существуют альтернативные способы, то используйте лучше их. Например, для изменения стилей используйте CSS, для эффектов [сервисы анимации](https://docs.angularjs.org/api/ngAnimate), для управления видимостью используйте [`ngShow`](https://docs.angularjs.org/api/ng/directive/ngShow) и [`ngHide`](https://docs.angularjs.org/api/ng/directive/ngHide). *Почему?*: Манипулирование элементами DOM тяжело тестить, отлаживать, и зачастую существуют более лучшие способы для реализации поставленной задачи (например CSS, анимации, шаблоны) @@ -1115,14 +1112,14 @@ - Добавляйте директивам короткий, уникальный, пояснительный префикс, такой как `acmeSalesCustomerInfo`, директива будет объявлена в HTML как `acme-sales-customer-info`. - *Почему?*: Уникальный короткий префикс говорит о контексте и происхождении директивы. Например, префикс `cc-` может рассказать нам, что директива является частью приложения CodeCamper, а `acme-` это директива для компании Acme. + *Почему?*: Уникальный короткий префикс говорит о контексте и происхождении директивы. Например, префикс `cc-` может рассказать нам, что директива является частью приложения CodeCamper, а `acme-` это директива для компании Acme. Замечание: Не используйте префикс `ng-` для своих директив, так как он зарезервирован для директив AngularJS. Также исследуйте префиксы широко используемых директив для избежания конфликтов имен, например, префикс `ion-` используется для директив [Ionic Framework](http://ionicframework.com/). - + ### Ограничивайте Элементы и Атрибуты ###### [Style [Y074](#style-y074)] - - При создании директивы, которая планируется как самостоятельный элемент, применяйте ограничение `E` (разработано, как элемент) или по необходимости ограничение `A` (разработано, как атрибут). В основном, если директива разрабатывается как элемент, ограничения `E` вполне достаточно. Хотя Angular позволяет использовать `EA`, но все же лучше определится как реализовывать директиву, либо как самостоятельный отдельный элемент, либо как атрибут для улучшения функциональности существующего DOM-элемента. + - При создании директивы, которая планируется как самостоятельный элемент, применяйте ограничение `E` (разработано, как элемент) или по необходимости ограничение `A` (разработано, как атрибут). В основном, если директива разрабатывается как элемент, ограничения `E` вполне достаточно. Хотя Angular позволяет использовать `EA`, но все же лучше определится как реализовывать директиву, либо как самостоятельный отдельный элемент, либо как атрибут для улучшения функциональности существующего DOM-элемента. *Почему?*: Это имееет смысл. @@ -1160,7 +1157,7 @@
``` - + ```javascript /* рекомендовано */ angular @@ -1214,7 +1211,7 @@ controller: ExampleController, controllerAs: 'vm' }; - + return directive; function linkFunc(scope, el, attr, ctrl) { @@ -1230,8 +1227,8 @@ // Внедрение $scope сразу для параметра сравнения var vm = this; - vm.min = 3; - vm.max = $scope.max; + vm.min = 3; + vm.max = $scope.max; console.log('CTRL: $scope.max = %i', $scope.max); console.log('CTRL: vm.min = %i', vm.min); console.log('CTRL: vm.max = %i', vm.max); @@ -1252,14 +1249,14 @@ ### Активация объектов promise в контроллере ###### [Style [Y080](#style-y080)] - - Размещайте стартовую начальную логику для контроллера в функции `activate`. - + - Размещайте стартовую начальную логику для контроллера в функции `activate`. + *Почему?*: Размещение стартовой логики в согласованом месте контроллера позволяет ее быстрее находить, более согласованно тестить, и позволить не разбразывать по всему контроллеру логику активации. *Почему?*: Функция `activate` делает удобным повторное использование логики для обновления контроллера/представления, держит все логику вместе, делает более быстрой работу пользователя с представлением, делает анимацию более простой в директивами `ng-view` и `ui-view`, ну и делает ориентирование разработчика в коде более энергичным и быстрым. Замечание: Если вам нужно при каком-то условии отменить маршрут перед началом использования контроллера, используйте для этого [route resolve](#style-y081). - + ```javascript /* избегайте этого */ function Avengers(dataservice) { @@ -1297,7 +1294,7 @@ ### Работа с Объектами Promise в Маршрутах ###### [Style [Y081](#style-y081)] - - Если контроллер зависит от объекта promise, от результата которого зависит активация контроллера, то разрешайте/получайте эти зависимости в `$routeProvider`, перед тем как логика контроллера будет выполена. Если вам нужно по какому-то условию отменить маршрут перед активацией контроллера, то используйте обработчик маршрутов. + - Если контроллер зависит от объекта promise, от результата которого зависит активация контроллера, то разрешайте/получайте эти зависимости в `$routeProvider`, перед тем как логика контроллера будет выполена. Если вам нужно по какому-то условию отменить маршрут перед активацией контроллера, то используйте обработчик маршрутов. - Используйте обработчик маршрутов, если вы решили в последствии отменить маршут до перехода к представлению. @@ -1358,7 +1355,7 @@ } ``` - Замечание: В примере ниже показано, как разрешение маршрута указывает на именованную функцию, которую легче отлаживать и легче оперировать встроенной зависимостью. + Замечание: В примере ниже показано, как разрешение маршрута указывает на именованную функцию, которую легче отлаживать и легче оперировать встроенной зависимостью. ```javascript /* еще лучше */ @@ -1404,8 +1401,8 @@ ### Уязвимости от Минификации ###### [Style [Y090](#style-y090)] - - Избегайте объявления зависимостей без использования безопасного для минификации подхода. - + - Избегайте объявления зависимостей без использования безопасного для минификации подхода. + *Почему?*: Параметры для компонент (типа контроллер, фабрика и т.п.) будут преобразованы в усеченные переменные. Например, `common` и `dataservice` превратятся `a` или `b` и не будут найдены средой AngularJS. ```javascript @@ -1418,7 +1415,7 @@ } ``` - После минификации будут производится усеченные переменные и это будет вызывать ошибки выполнения. + После минификации будут производится усеченные переменные и это будет вызывать ошибки выполнения. ```javascript /* избегайте этого- не безопасно для минификации */ @@ -1429,7 +1426,7 @@ ###### [Style [Y091](#style-y091)] - Используйте `$inject` для ручного определения ваших зависимостей для AngulaJS. - + *Почему?*: Этот техника отражает технику использованную в [`ng-annotate`](https://github.com/olov/ng-annotate), которую я рекомендую для автоматического создания зависимостей, безопасных для минификации. Если `ng-annotate` обнаруживает вставку(injection), которая уже была, то она не будет продублирована. *Почему?*: Это гарантирует вашим зависимостям защиту от повреждений, которую может нанести минификация, путем урезания и укорачивания переменных. Например, `common` и `dataservice` превратятся `a` и `b`, и не будут найдены средой AngularJS. @@ -1440,8 +1437,8 @@ /* избегайте этого */ angular .module('app') - .controller('Dashboard', - ['$location', '$routeParams', 'common', 'dataservice', + .controller('Dashboard', + ['$location', '$routeParams', 'common', 'dataservice', function Dashboard($location, $routeParams, common, dataservice) {} ]); ``` @@ -1450,9 +1447,9 @@ /* избегайте этого */ angular .module('app') - .controller('Dashboard', + .controller('Dashboard', ['$location', '$routeParams', 'common', 'dataservice', Dashboard]); - + function Dashboard($location, $routeParams, common, dataservice) { } ``` @@ -1536,15 +1533,15 @@ ###### [Style [Y100](#style-y100)] - Используйте [ng-annotate](//github.com/olov/ng-annotate) для [Gulp](http://gulpjs.com) или [Grunt](http://gruntjs.com) и комментируйте функции, которые нуждаются в автоматической вставке зависимостей, используйте `/** @ngInject */`. - + *Почему?*: Это гарантирует, что в вашем коде нет зависимостей, которые не используют защиту для повреждений от минификации. - *Почему?*: [`ng-min`](https://github.com/btford/ngmin) не рекомендуется для применения, выводится из употребления + *Почему?*: [`ng-min`](https://github.com/btford/ngmin) не рекомендуется для применения, выводится из употребления >Я предпочитаю Gulp, так как для меня он проще для чтения, написания кода и отладки. Следующий код не использует защиту зависимостей от минификации. - + ```javascript angular .module('app') @@ -1563,7 +1560,7 @@ } ``` - Если код выше запустить через ng-annotate, то будет произведен код с аннотацией `$inject`, и код станет устойчив к минификации. + Если код выше запустить через ng-annotate, то будет произведен код с аннотацией `$inject`, и код станет устойчив к минификации. ```javascript angular @@ -1587,7 +1584,7 @@ Замечание: Если `ng-annotate` обнаруживает вставки которые уже сделаны (например `@ngInject` был обнаружен), он не будет дублирован в коде `$inject`. - Замечание: Если используется маршрутный обработчик, то вы можете перед встраиваемой функцией подставить `/* @ngInject */` и это будет производить корректный аннотационный код, делающий каждую вставленную зависимость безопасной для минификации. + Замечание: Если используется маршрутный обработчик, то вы можете перед встраиваемой функцией подставить `/* @ngInject */` и это будет производить корректный аннотационный код, делающий каждую вставленную зависимость безопасной для минификации. ```javascript // Используем @ngInject аннотацию @@ -1613,7 +1610,7 @@ ###### [Style [Y101](#style-y101)] - Используйте [gulp-ng-annotate](https://www.npmjs.org/package/gulp-ng-annotate) или [grunt-ng-annotate](https://www.npmjs.org/package/grunt-ng-annotate) для автоматических билдов. Вставляйте `/* @ngInject */` перед любой функцией, которая имеет зависимости. - + *Почему?*: ng-annotate будет отлавливать большинство зависимостей, но иногда требуются вставлять подсказки в виде синтаксиса `/* @ngInject */`. Следующий код является примером gulp задания с использованием ngAnnotate. @@ -1646,8 +1643,8 @@ ### декораторы ###### [Style [Y110](#style-y110)] - - Используйте [decorator](https://docs.angularjs.org/api/auto/service/$provide#decorator), во время конфигурации, применяя сервис [`$provide`](https://docs.angularjs.org/api/auto/service/$provide), пользовательские действия будут происходить в сервисе [`$exceptionHandler`](https://docs.angularjs.org/api/ng/service/$exceptionHandler), если произойдут исключения. - + - Используйте [decorator](https://docs.angularjs.org/api/auto/service/$provide#decorator), во время конфигурации, применяя сервис [`$provide`](https://docs.angularjs.org/api/auto/service/$provide), пользовательские действия будут происходить в сервисе [`$exceptionHandler`](https://docs.angularjs.org/api/ng/service/$exceptionHandler), если произойдут исключения. + *Почему?*: Это дает постоянный надежный способ обработки необработанных исключений Angular во время разработки и во время выполнения. Замечание: Другим способом является переопределение сервиса, вместо использования декоратора. Это прекрасный способ, но если вы хотите сохранить поведение по умолчанию, и просто дополнить это поведение, то декоратоор крайне рекомендуем. @@ -1669,9 +1666,9 @@ function extendExceptionHandler($delegate, toastr) { return function(exception, cause) { $delegate(exception, cause); - var errorData = { - exception: exception, - cause: cause + var errorData = { + exception: exception, + cause: cause }; /** * Здесь можно добавить ошибку в сервисную коллекцию, @@ -1687,7 +1684,7 @@ ### Обработчики Исключений ###### [Style [Y111](#style-y111)] - - Создайте фабрику, которая предоставит интерфейс для перехвата и изящной обработки исключений. + - Создайте фабрику, которая предоставит интерфейс для перехвата и изящной обработки исключений. *Почему?*: Это дает постоянный и надежный способ для перехвата исключений, которые могут возникнуть в вашем коде (например, во время вызовов объекта XHR или сбоев в работе объектов promise). @@ -1757,14 +1754,14 @@ - Используйте согласованные имена для всех компонентов по шаблону, который описывает особенность(feature) компонента, а затем (опционально) его тип. Я рекомендую шаблон - `feature.type.js`. Существует два типа имен для большинства случаев: * имя файла (`avengers.controller.js`) * имя компонента, которое зарегистрировано Angular (`AvengersController`) - - *Почему?*: Соглашения об именованиях дает постояннный надежный способ поиска содержимого быстрым беглым взглядом. Согласованность в проекте жизненно важна. Согласованность в команде очень важна. Согласованность между компаниями дает огромную эффективность. - *Почему?*: Соглашения об именованиях просто должны помочь найти вам свой код быстрее, и сделать его проще для понимания. + *Почему?*: Соглашения об именованиях дает постояннный надежный способ поиска содержимого быстрым беглым взглядом. Согласованность в проекте жизненно важна. Согласованность в команде очень важна. Согласованность между компаниями дает огромную эффективность. + + *Почему?*: Соглашения об именованиях просто должны помочь найти вам свой код быстрее, и сделать его проще для понимания. ### Характерные Имена Файлов ###### [Style [Y121](#style-y121)] - - Используйте согласованные имена для всех компонентов используя шаблон, который описывает компонентную особенность, затем опционально его тип. Я рекомендую шаблон - `feature.type.js`. + - Используйте согласованные имена для всех компонентов используя шаблон, который описывает компонентную особенность, затем опционально его тип. Я рекомендую шаблон - `feature.type.js`. *Почему?*: Это надежный способ для быстрой идентификации компонентов. @@ -1801,7 +1798,7 @@ // константы constants.js - + // определение модуля avengers.module.js @@ -1811,14 +1808,14 @@ // конфигурация avengers.config.js - + // директивы avenger-profile.directive.js avenger-profile.directive.spec.js ``` Замечание: Другим общим соглашением является именование файлов контроллера без слова `controller`, например, называем файл `avengers.js` вместо `avengers.controller.js`. Все остальные соглашения все же должны содержать суффикс типа. Просто контроллеры наиболее общий тип компонентов, и таким образом, мы экономим время печатая имя, но контроллеры все равно прекрасно идентифицируются. Я рекомендую выбрать один тип соглашения и быть на одной волне со своей командой. - + ```javascript /** * рекомендовано @@ -1831,7 +1828,7 @@ ### Имена Тестовых Файлов ###### [Style [Y122](#style-y122)] - - Имя тестовой спецификации подобно имени компонента, которая его тестит, только к ней еще добавляется суффикс `spec`. + - Имя тестовой спецификации подобно имени компонента, которая его тестит, только к ней еще добавляется суффикс `spec`. *Почему?*: Это надежный способ для быстрой идентификации компонентов. @@ -1850,7 +1847,7 @@ ### Имена Контроллеров ###### [Style [Y123](#style-y123)] - - Используйте согласованные имена для всех контроллеров, именованных по их характерной особенности. Используйте UpperCamelCase (ВерхнийВерблюжийРегистр) для контроллеров, так как они являются конструкторами. + - Используйте согласованные имена для всех контроллеров, именованных по их характерной особенности. Используйте UpperCamelCase (ВерхнийВерблюжийРегистр) для контроллеров, так как они являются конструкторами. *Почему?*: Это дает надежный и понятный способ для быстрой идентификации и применения контроллеров. @@ -1876,7 +1873,7 @@ *Почему?*: Суффикс `Controller` более общеупотребим и наиболее явно описателен. - *Почему?*: Если не указывать суффикс, то получатся более краткие имена, но контроллеры все равно будут легко идентифицируемы, даже без суффикса. + *Почему?*: Если не указывать суффикс, то получатся более краткие имена, но контроллеры все равно будут легко идентифицируемы, даже без суффикса. ```javascript /** @@ -1949,10 +1946,10 @@ ### Модули ###### [Style [Y127](#style-y127)] - - Если разрабатываются несколько модулей, файл главного модуля будет называться `app.module.js`, а другие модули получат свое название по своему назначению (то что они представляют). Например, модуль администрирования будет назван `admin.module.js`. Соответствующие зарегистрированные имена модулей будут `app` и `admin`. + - Если разрабатываются несколько модулей, файл главного модуля будет называться `app.module.js`, а другие модули получат свое название по своему назначению (то что они представляют). Например, модуль администрирования будет назван `admin.module.js`. Соответствующие зарегистрированные имена модулей будут `app` и `admin`. - *Почему?*: Это дает согласованность для многих модулей приложения, а также позволяет расширяться в огромные приложения. - *Почему?*: Получаем простой способ автоматизировать работу для первоначальной загрузки всех модульных определений, а затем уже остальных файлов angular. + *Почему?*: Это дает согласованность для многих модулей приложения, а также позволяет расширяться в огромные приложения. + *Почему?*: Получаем простой способ автоматизировать работу для первоначальной загрузки всех модульных определений, а затем уже остальных файлов angular. ### Конфигурация ###### [Style [Y128](#style-y128)] @@ -1966,7 +1963,7 @@ ### Маршруты ###### [Style [Y129](#style-y129)] - - Выделяйте конфигурацию маршрута в свой собственный файл. Примеры могут быть такими: `app.route.js` для главного модуля и `admin.route.js` для модуля `admin`. Даже в маленьких приложениях я предпочитаю такое разделение от остальной конфигурации. + - Выделяйте конфигурацию маршрута в свой собственный файл. Примеры могут быть такими: `app.route.js` для главного модуля и `admin.route.js` для модуля `admin`. Даже в маленьких приложениях я предпочитаю такое разделение от остальной конфигурации. **[К Содержанию](#table-of-contents)** @@ -1976,10 +1973,10 @@ - Структура вашего приложения должна быть построена таким образом, чтобы вы могли: `L` - размещать ваш код быстро (`L`ocate your code quickly), `I` - идентифицировать код практически с первого взгляда (`I`dentify the code at a glance), `F` - держать структуру плоской, насколько это возможно (keep the `F`lattest structure you can), и стараться оставаться DRY (Don’t Repeat Yourself) - Не Повторяйте Себя - (`T`ry to stay DRY - Don’t Repeat Yourself). Структура должна придерживаться этим основным 4 правилам. - *Почему LIFT?*: Получаем согласованную структуру, которая хорошо масштабируется, разбита на модули, и легко позволяет увеличить эффективность разработчика, путем быстрого нахождения кода. Другой способ проверить структуру вашего приложения - это спросить себя: Как быстро я могу открыть все сооответствующие файлы, чтобы работать над нужной функциональностью? - + *Почему LIFT?*: Получаем согласованную структуру, которая хорошо масштабируется, разбита на модули, и легко позволяет увеличить эффективность разработчика, путем быстрого нахождения кода. Другой способ проверить структуру вашего приложения - это спросить себя: Как быстро я могу открыть все сооответствующие файлы, чтобы работать над нужной функциональностью? + Когда я чувствую, что работать с моей структурой некомфортно, я возвращаюсь к принципам LIFT. - + 1. `L`Размещать наш код легко (`L`ocating our code is easy) 2. `I`Идентифицировать код быстро (`I`dentify code at a glance) 3. `F`Держать структуру ровной как можно дольше (`F`lat structure as long as we can) @@ -2027,8 +2024,8 @@ ### T-DRY (Try to Stick to DRY) T-DRY (Старайтесь придерживаться принципов DRY) ###### [Style [Y144](#style-y144)] - - Примечание переводчика: Аббревиатура DRY значит Don`t Repeat Yourself (Не повторяйте себя). - + - Примечание переводчика: Аббревиатура DRY значит Don`t Repeat Yourself (Не повторяйте себя). + - Придерживайтесь DRY, но не сходите с ума и не жертвуйте читабельностью. *Почему?*: Быть DRY - это важно, но не критично, если в жертву приносятся другие принципы LIFT. Поэтому я и назвал это T-DRY (Try DRY - попытайтесь быть DRY). Напрмер, я не хочу печатать session-view.html для представления, потому что и так понятно, что это представление(view). Но если это не очевидно или это определено соглашением, тогда нужно давать полное имя. @@ -2047,7 +2044,7 @@ ### Общие элементы ###### [Style [Y151](#style-y151)] - - Размещайте компоненты, которые определяют общий каркас приложения в папке `layout`. Там могут быть представление-оболочка и контроллер, которые являются контейнером для приложения, навигация, меню, регионы содержимого (content areas) и другие общие элементы. + - Размещайте компоненты, которые определяют общий каркас приложения в папке `layout`. Там могут быть представление-оболочка и контроллер, которые являются контейнером для приложения, навигация, меню, регионы содержимого (content areas) и другие общие элементы. *Почему?*: Так организуются все элементы общего назначения, которые размещаются в одном месте и используются во всем приложении. @@ -2104,15 +2101,15 @@ ![Пример Структуры Приложения](https://raw.githubusercontent.com/johnpapa/angularjs-styleguide/master/assets/modularity-2.png) - Замечание: Не используйте структуру папки-по-типу. Так файлы одной функциональности разбрасываются по нескольким папкам, и далее все быстро становится очень громоздким. Как только в приложении создаются 5, 10, или 25+ представлений и контроллеров (и других компонентов), то работа становится очень сложной, в отличиии от структуры папки-по-функциональностям. - + Замечание: Не используйте структуру папки-по-типу. Так файлы одной функциональности разбрасываются по нескольким папкам, и далее все быстро становится очень громоздким. Как только в приложении создаются 5, 10, или 25+ представлений и контроллеров (и других компонентов), то работа становится очень сложной, в отличиии от структуры папки-по-функциональностям. + ```javascript - /* + /* * избегайте этого * Альтернативный способ "папки-по-типу". * Я рекомендую "папки-по-функциональностям". */ - + app/ app.module.js app.config.js @@ -2143,7 +2140,7 @@ speakers.html speaker-detail.html topnav.html - ``` + ``` **[К Содержанию](#table-of-contents)** @@ -2181,14 +2178,14 @@ *Почему?*: Спринты или итерации могут сосредоточиться на функциональных областях, и включить их по завершению спринта или итерации. - *Почему?*: Оформление функциональных областей в модули позволяет проще их тестировать в изолированном или повторно используемом коде. + *Почему?*: Оформление функциональных областей в модули позволяет проще их тестировать в изолированном или повторно используемом коде. ### Повторно Используемые Блоки и Модули ###### [Style [Y164](#style-y164)] - Создавайте модули, которые представляют из себя повторно используемые блоки приложения для общих сервисов таких как обработка исключений, логгирование, диагностика, безопасность и локальная работа с данными. - *Почему?*: Эти типы функциональностей нужны во многих приложениях. Поэтому держите их отдельно в своих собственных модулях, применяйте универсально и повторно используйте во многих приложениях. + *Почему?*: Эти типы функциональностей нужны во многих приложениях. Поэтому держите их отдельно в своих собственных модулях, применяйте универсально и повторно используйте во многих приложениях. ### Зависимости модулей ###### [Style [Y165](#style-y165)] @@ -2203,11 +2200,11 @@ *Почему?*: Функциональности приложения для внутреннего пользования (intra-app) такие как общие сервисы данных становится проще размещать и делится из модуля `app.core` (выберите это имя для такого модуля). - Замечание: Это стратегия для согласованности. Здесь очень много хороших вариантов. Выберите тот, который следует правилам зависимостей AngularJS, и его проще поддерживать и масштабировать. + Замечание: Это стратегия для согласованности. Здесь очень много хороших вариантов. Выберите тот, который следует правилам зависимостей AngularJS, и его проще поддерживать и масштабировать. > Мои структуры слегка отличаются от проекта к проекту, но они всегда следовали этим руководствам структуры и модульности. Реализация может менятся в зависимости от особенностей проекта и команды. Другими словами, не зацикливайтесь на точных воспроизведениях структуры. Регулируйте свою структуру учитывая согласованность, способность поддерживать код и эффективность. - > В небольшом приложении вы можете конечно объединить все общие зависимости в модуль приложения, где функциональные модули не имеют прямых зависимостей. Это проще поддерживать в маленьких приложениях, использовать это вне приложения будет очень затруднительно. + > В небольшом приложении вы можете конечно объединить все общие зависимости в модуль приложения, где функциональные модули не имеют прямых зависимостей. Это проще поддерживать в маленьких приложениях, использовать это вне приложения будет очень затруднительно. **[К Содержанию](#table-of-contents)** @@ -2225,7 +2222,7 @@ .module('app') .config(configure); - configure.$inject = + configure.$inject = ['routerHelperProvider', 'exceptionHandlerProvider', 'toastr']; function configure (routerHelperProvider, exceptionHandlerProvider, toastr) { @@ -2250,7 +2247,7 @@ - Весь код, который должен запуститься, во время старта приложения, должен быть объявлен в фабрике, предоставлен в виде функции, и вставлен в [блок run](https://docs.angularjs.org/guide/module#module-loading-dependencies). - *Почему?*: Если код поместить сразу в блок run, то его будет тяжело тестить. Размещение кода в фабрике облегчает абстрагирование и использование фиктивных объектов для тестов. + *Почему?*: Если код поместить сразу в блок run, то его будет тяжело тестить. Размещение кода в фабрике облегчает абстрагирование и использование фиктивных объектов для тестов. ```javascript angular @@ -2274,7 +2271,7 @@ - Используйте [`$document`](https://docs.angularjs.org/api/ng/service/$document) и [`$window`](https://docs.angularjs.org/api/ng/service/$window) вместо `document` и `window`. - *Почему?*: Эти сервисы являются оберткой среды Angular, они более проще тестируются, чем объекты document и window. Это дает вам возможность не создавать самим фиктивные объекты document and window. + *Почему?*: Эти сервисы являются оберткой среды Angular, они более проще тестируются, чем объекты document и window. Это дает вам возможность не создавать самим фиктивные объекты document and window. ### $timeout and $interval ###### [Style [Y181](#style-y181)] @@ -2331,7 +2328,7 @@ *Почему?*: Karma просто конфигурируется, она просто запускается вручную или автоматически (как только вы измените код). - *Почему?*: Karma просто внедряется в ваш процесс Continuous Integration, как самостоятельно, так и через Grunt или Gulp. + *Почему?*: Karma просто внедряется в ваш процесс Continuous Integration, как самостоятельно, так и через Grunt или Gulp. *Почему?*: Некоторые средства разработки (IDE) начали интегрировать в себя библиотеку Karma, это - [WebStorm](http://www.jetbrains.com/webstorm/) и [Visual Studio](http://visualstudiogallery.msdn.microsoft.com/02f47876-0e7a-4f6c-93f8-1af5d5189225). @@ -2351,14 +2348,14 @@ - Используйте [PhantomJS](http://phantomjs.org/) для запуска тестов на сервере. - *Почему?*: PhantomJS - невизуальный браузер, который помогает запускать тесты, не используя обычные визуальные браузеры. Таким образом, вам не нужно устанавливать на ваш сервер Chrome, Safari, IE, или другие браузеры. + *Почему?*: PhantomJS - невизуальный браузер, который помогает запускать тесты, не используя обычные визуальные браузеры. Таким образом, вам не нужно устанавливать на ваш сервер Chrome, Safari, IE, или другие браузеры. Замечание: Все же проведите тесты на всех браузерах, особенно на браузерах вашей целевой аудитории. ### Анализ Кода ###### [Style [Y195](#style-y195)] - - Запустите JSHint на ваших тестах. + - Запустите JSHint на ваших тестах. *Почему?*: Тесты это код. JSHint помогает идентифицировать проблемы качества кода, которые могут причиной некорректной работы тестов. @@ -2367,7 +2364,7 @@ - Смягчите правила для кода ваших тестов, чтобы разрешить общие глобальные переменные такие как `describe` и `expect`. - *Почему?*: Ваши тесты - это код и он требует того же самого внимания и соблюдения правил качества, как и весь ваш рабочий код. Все же, глобальные переменные используются средой тестирования, и правила для них нужно ослабить в спецификации тестов. + *Почему?*: Ваши тесты - это код и он требует того же самого внимания и соблюдения правил качества, как и весь ваш рабочий код. Все же, глобальные переменные используются средой тестирования, и правила для них нужно ослабить в спецификации тестов. ```javascript /* global sinon, describe, it, afterEach, beforeEach, expect, inject */ @@ -2386,9 +2383,9 @@ *Почему?*: Когда вы изменяете исходный код, всегда проще сразу обновить тесты. - *Почему?*: Размещение файла кода и теста рядом упрощает их поиск и в случае необходимости, перенос в другое место обоих файлов не составляет большого труда. + *Почему?*: Размещение файла кода и теста рядом упрощает их поиск и в случае необходимости, перенос в другое место обоих файлов не составляет большого труда. - *Почему?*: Отделить тестовые файлы(specs), так чтобы они не попали в рабочую сборку можно с помощью grunt или gulp. + *Почему?*: Отделить тестовые файлы(specs), так чтобы они не попали в рабочую сборку можно с помощью grunt или gulp. ``` /src/client/app/customers/customer-detail.controller.js @@ -2416,8 +2413,8 @@ ### Длительность Анимаций ###### [Style [Y211](#style-y211)] - - Используйте короткую длительность анимаций. Я в основном начинаю с 300 миллисекунд и регулирую до нужного состояния. - *Почему?*: Долгие анимации могут иметь обратный эффект для пользователя, приложение будет восприниматься как медленно работающее. + - Используйте короткую длительность анимаций. Я в основном начинаю с 300 миллисекунд и регулирую до нужного состояния. + *Почему?*: Долгие анимации могут иметь обратный эффект для пользователя, приложение будет восприниматься как медленно работающее. ### animate.css ###### [Style [Y212](#style-y212)] @@ -2471,7 +2468,7 @@ /** * @name logError * @desc Logs errors - * @param {String} msg Message to log + * @param {String} msg Message to log * @returns {String} * @memberOf Factories.Logger */ @@ -2565,7 +2562,7 @@ ## Constants -### Глобальные Переменные Сторонних Производителей (Vendors) +### Глобальные Переменные Сторонних Производителей (Vendors) ###### [Style [Y240](#style-y240)] - Создайте константы Angular для глобальных переменных из библиотек сторонних производителей. @@ -2585,16 +2582,16 @@ .constant('moment', moment); })(); ``` - + ###### [Style [Y241](#style-y241)] - - Используйте константы для значений, которые не изменяются и не приходят из другого сервиса. Если константы используются в модуле, который может быть использован в нескольких приложениях, то поместите константу в файле, названному по имени модуля. В противном случае держите константы в главном модуле в файле `constants.js`. + - Используйте константы для значений, которые не изменяются и не приходят из другого сервиса. Если константы используются в модуле, который может быть использован в нескольких приложениях, то поместите константу в файле, названному по имени модуля. В противном случае держите константы в главном модуле в файле `constants.js`. *Почему?*: Значение может измениться, возможно это редкая ситуация, но допустим сервис возвращает нам значение, и таким образом мы не будем менять наш рабочий код, использующий этот сервис. Напрмер, url для сервиса данных мог бы быть помещен в константы, но лучше загружать его из веб сервиса. - + *Почему?*: Константы могут быть инжектированы в любой angular-компонент, включая провайдеры. - *Почему?*: Когда приложение разделено на модули, которые могут быть использованы в других приложениях, каждый отдельный модуль должен быть способен оперировать своими собственными зависимыми константами. + *Почему?*: Когда приложение разделено на модули, которые могут быть использованы в других приложениях, каждый отдельный модуль должен быть способен оперировать своими собственными зависимыми константами. ```javascript // Константы используются во всем приложении @@ -2619,13 +2616,13 @@ ### Sublime Text ###### [Style [Y250](#style-y250)] - - Angular сниппеты, которые соблюдают приведенные здесь стили и руководства. + - Angular сниппеты, которые соблюдают приведенные здесь стили и руководства. - - Скачайте [Sublime Angular сниппеты](assets/sublime-angular-snippets.zip?raw=true) + - Скачайте [Sublime Angular сниппеты](assets/sublime-angular-snippets.zip?raw=true) - Поместите все в вашу папку Packages - - Перезапустите Sublime + - Перезапустите Sublime - В файле JavaScript напечатайте следующие команды после клавиши `TAB` - + ```javascript ngcontroller // создает контроллер Angular ngdirective // создает директиву Angular @@ -2706,7 +2703,7 @@ *Почему?*: Когда мы удаляем или добавляем модуль, то приложение должно содержать только те маршруты, которые указывают на существующие представления. - *Почему?*: Так мы можем включать или исключать части приложения, не заботясь о том, что у нас останутся маршруты на несуществующие представления. + *Почему?*: Так мы можем включать или исключать части приложения, не заботясь о том, что у нас останутся маршруты на несуществующие представления. **[К Содержанию](#table-of-contents)** @@ -2719,7 +2716,7 @@ *Почему?*: Angular должен зарегистрировать все определения модулей, перед тем как их использовать. - *Почему?*: Именование модулей по специальному шаблону `*.module.js` упрощает их поиск и сборку в единую группу, для того чтобы подключить их первыми. + *Почему?*: Именование модулей по специальному шаблону `*.module.js` упрощает их поиск и сборку в единую группу, для того чтобы подключить их первыми. ```javascript var clientApp = './src/client/app/'; @@ -2743,7 +2740,7 @@ *Добавляя материал в данное хранилище вы согласны с тем, ваше содержимое будет доступно согласно приведенной ниже лицензии.* ### Процесс - 1. Обсудите изменения в Issue. + 1. Обсудите изменения в Issue. 2. Откройте Pull Request, сделайте ссылку на issue, объясните изменения и их ценность. 3. Pull Request будет проверен и далее принят или отклонен. diff --git a/i18n/zh-CN.md b/i18n/zh-CN.md index 57da4898..48849ca6 100644 --- a/i18n/zh-CN.md +++ b/i18n/zh-CN.md @@ -2,10 +2,6 @@ *Angular规范[@john_papa](//twitter.com/john_papa)* -*由[ZhaoKe](https://github.com/natee)翻译* - ->The [original English version](http://jpapa.me/ngstyles) is the source of truth, as it is maintained and updated first. - 如果你正在寻找一些关于语法、约定和结构化的Angular应用的一个有建设性的规范,那么你来对地方了。这里所包含的内容是基于我在团队中使用[Angular](//angularjs.org)的一些经验、一些演讲和[Pluralsight培训课程](http://pluralsight.com/training/Authors/Details/john-papa)。 这个规范的目的是为构建Angular应用提供指导,当然更加重要的是让大家知道我为什么要选择它们。 @@ -22,7 +18,7 @@ Angular社区是一个热衷于分享经验的令人难以置信的社区,尽 ## 在示例App中了解这些规范 看示例代码有助于你更好地理解,你可以在`modular`文件夹下找到[命名为modular的示例应用程序](https://github.com/johnpapa/ng-demos),随便克隆。 -##翻译 +##翻译 [Angular规范翻译版本](https://github.com/johnpapa/angular-styleguide/tree/master/i18n)。 ##目录 @@ -45,7 +41,7 @@ Angular社区是一个热衷于分享经验的令人难以置信的社区,尽 1. [启动逻辑](#启动逻辑) 1. [Angular $包装服务](#angular-包装服务) 1. [测试](#测试) - 1. [动画](#动画) + 1. [动画](#动画) 1. [注释](#注释) 1. [JSHint](#js-hint) 1. [JSCS](#jscs) @@ -65,20 +61,20 @@ Angular社区是一个热衷于分享经验的令人难以置信的社区,尽 - 一个文件只定义一个组件。 - 下面的例子在同一个文件中定义了一个`app`的module和它的一些依赖、一个controller和一个factory。 + 下面的例子在同一个文件中定义了一个`app`的module和它的一些依赖、一个controller和一个factory。 ```javascript - /* avoid */ + /* avoid */ angular .module('app', ['ngRoute']) .controller('SomeController', SomeController) .factory('someFactory', someFactory); - + function SomeController() { } function someFactory() { } ``` - + 推荐以下面的方式来做,把上面相同的组件分割成单独的文件。 ```javascript /* recommended */ @@ -105,7 +101,7 @@ Angular社区是一个热衷于分享经验的令人难以置信的社区,尽 angular .module('app') .factory('someFactory', someFactory); - + function someFactory() { } ``` @@ -115,12 +111,12 @@ Angular社区是一个热衷于分享经验的令人难以置信的社区,尽 ### JavaScript闭包 ###### [Style [Y010](#style-y010)] - - 把Angular组件包装到一个立即调用函数表达式中(IIFE)。 - + - 把Angular组件包装到一个立即调用函数表达式中(IIFE)。 + *为什么?*:把变量从全局作用域中删除了,这有助于防止变量和函数声明比预期在全局作用域中有更长的生命周期,也有助于避免变量冲突。 *为什么?*:当你的代码为了发布而压缩了并且被合并到同一个文件中时,可能会有很多变量发生冲突,使用了IIFE(给每个文件提供了一个独立的作用域),你就不用担心这个了。 - + ```javascript /* avoid */ // logger.js @@ -128,7 +124,7 @@ Angular社区是一个热衷于分享经验的令人难以置信的社区,尽 .module('app') .factory('logger', logger); - // logger function会被当作一个全局变量 + // logger function会被当作一个全局变量 function logger() { } // storage.js @@ -136,15 +132,15 @@ Angular社区是一个热衷于分享经验的令人难以置信的社区,尽 .module('app') .factory('storage', storage); - // storage function会被当作一个全局变量 + // storage function会被当作一个全局变量 function storage() { } ``` ```javascript /** - * recommended + * recommended * - * 再也不存在全局变量了 + * 再也不存在全局变量了 */ // logger.js @@ -170,7 +166,7 @@ Angular社区是一个热衷于分享经验的令人难以置信的社区,尽 })(); ``` - - 注:为了简洁起见,本规范余下的示例中将会省略IIFE语法。 + - 注:为了简洁起见,本规范余下的示例中将会省略IIFE语法。 - 注:IIFE阻止了测试代码访问私有成员(正则表达式、helper函数等),这对于自身测试是非常友好的。然而你可以把这些私有成员暴露到可访问成员中进行测试,例如把私有成员(正则表达式、helper函数等)放到factory或是constant中。 @@ -188,10 +184,10 @@ Angular社区是一个热衷于分享经验的令人难以置信的社区,尽 ###定义(aka Setters) ###### [Style [Y021](#style-y021)] - - 不使用任何一个使用了setter语法的变量来定义modules。 + - 不使用任何一个使用了setter语法的变量来定义modules。 *为什么?*:在一个文件只有一个组件的条件下,完全不需要为一个模块引入一个变量。 - + ```javascript /* avoid */ var app = angular.module('app', [ @@ -226,7 +222,7 @@ Angular社区是一个热衷于分享经验的令人难以置信的社区,尽 /* avoid */ var app = angular.module('app'); app.controller('SomeController', SomeController); - + function SomeController() { } ``` @@ -235,7 +231,7 @@ Angular社区是一个热衷于分享经验的令人难以置信的社区,尽 angular .module('app') .controller('SomeController', SomeController); - + function SomeController() { } ``` @@ -243,16 +239,16 @@ Angular社区是一个热衷于分享经验的令人难以置信的社区,尽 ###### [Style [Y023](#style-y023)] - 只能设置一次。 - + *为什么?*:一个module只能被创建一次,创建之后才能被检索到。 - + - 设置module,`angular.module('app', []);`。 - - 获取module,`angular.module('app');`。 + - 获取module,`angular.module('app');`。 ###命名函数 vs 匿名函数 ###### [Style [Y024](#style-y024)] - - 回调函数使用命名函数,不要用匿名函数。 + - 回调函数使用命名函数,不要用匿名函数。 *为什么?*:易读,方便调试,减少嵌套回调函数的数量。 @@ -291,7 +287,7 @@ Angular社区是一个热衷于分享经验的令人难以置信的社区,尽 ###controllerAs在View中的语法 ###### [Style [Y030](#style-y030)] - - 使用[`controllerAs`](http://www.johnpapa.net/do-you-like-your-angular-controllers-with-or-without-sugar/) 语法代替直接用经典的$scope定义的controller的方式。 + - 使用[`controllerAs`](http://www.johnpapa.net/do-you-like-your-angular-controllers-with-or-without-sugar/) 语法代替直接用经典的$scope定义的controller的方式。 *为什么?*:controller被构建的时候,就会有一个新的实例,`controllerAs` 的语法比`经典的$scope语法`更接近JavaScript构造函数。 @@ -316,11 +312,11 @@ Angular社区是一个热衷于分享经验的令人难以置信的社区,尽 ###controllerAs在controller中的语法 ###### [Style [Y031](#style-y031)] - - 使用 `controllerAs` 语法代替 `经典的$scope语法` 语法。 + - 使用 `controllerAs` 语法代替 `经典的$scope语法` 语法。 - 使用`controllerAs` 时,controller中的`$scope`被绑定到了`this`上。 - *为什么?*:`controllerAs` 是`$scope`的语法修饰,你仍然可以绑定到View上并且访问 `$scope`的方法。 + *为什么?*:`controllerAs` 是`$scope`的语法修饰,你仍然可以绑定到View上并且访问 `$scope`的方法。 *为什么?*:避免在controller中使用 `$scope`,最好不用它们或是把它们移到一个factory中。factory中可以考虑使用`$scope`,controller中只在需要时候才使用`$scope`,例如当使用[`$emit`](https://docs.angularjs.org/api/ng/type/$rootScope.Scope#$emit), [`$broadcast`](https://docs.angularjs.org/api/ng/type/$rootScope.Scope#$broadcast),或者 [`$on`](https://docs.angularjs.org/api/ng/type/$rootScope.Scope#$on)来发布和订阅事件时,可以考虑把这些调用挪到factory当中,并从controller中调用。 @@ -344,7 +340,7 @@ Angular社区是一个热衷于分享经验的令人难以置信的社区,尽 ###### [Style [Y032](#style-y032)] - 使用`controllerAs`语法时把`this` 赋值给一个可捕获的变量,选择一个有代表性的名称,例如`vm`代表ViewModel。 - + *为什么?*:`this`在不同的地方有不同的语义(就是作用域不同),在controller中的一个函数内部使用`this`时可能会改变它的上下文。用一个变量来捕获`this`的上下文从而可以避免遇到这样的坑。 ```javascript @@ -365,7 +361,7 @@ Angular社区是一个热衷于分享经验的令人难以置信的社区,尽 ``` - 注:你可以参照下面的做法来避免 [jshint](http://www.jshint.com/)的警告。但是构造函数(函数名首字母大写)是不需要这个的. - + ```javascript /* jshint validthis: true */ var vm = this; @@ -380,7 +376,7 @@ Angular社区是一个热衷于分享经验的令人难以置信的社区,尽 function SomeController($scope, $log) { var vm = this; vm.title = 'Some Title'; - + $scope.$watch('vm.title', function(current, original) { $log.info('vm.title was %s', original); $log.info('vm.title is now %s', current); @@ -388,15 +384,15 @@ Angular社区是一个热衷于分享经验的令人难以置信的社区,尽 } ``` - + ###可绑定成员放到顶部 ###### [Style [Y033](#style-y033)] - 把可绑定的成员放到controller的顶部,按字母排序,并且不要通过controller的代码传播。 - - *为什么?*:易读,可以让你立即识别controller中的哪些成员可以在View中绑定和使用。 - *为什么?*:虽然设置单行匿名函数很容易,但是当这些函数的代码超过一行时,这将极大降低代码的可读性。在可绑定成员下面定义函数(这些函数被提出来),把具体的实现细节放到下面,可绑定成员放到顶部,这会提高代码的可读性。 + *为什么?*:易读,可以让你立即识别controller中的哪些成员可以在View中绑定和使用。 + + *为什么?*:虽然设置单行匿名函数很容易,但是当这些函数的代码超过一行时,这将极大降低代码的可读性。在可绑定成员下面定义函数(这些函数被提出来),把具体的实现细节放到下面,可绑定成员放到顶部,这会提高代码的可读性。 ```javascript /* avoid */ @@ -453,8 +449,8 @@ Angular社区是一个热衷于分享经验的令人难以置信的社区,尽 vm.gotoSession = gotoSession; vm.refresh = function() { - /** - * lines + /** + * lines * of * code * affects @@ -482,20 +478,20 @@ Angular社区是一个热衷于分享经验的令人难以置信的社区,尽 ###### [Style [Y034](#style-y034)] - 使用函数声明来隐藏实现细节,把绑定成员放到顶部,当你需要在controller中绑定一个函数时,把它指向一个在文件的后面会出现函数声明。更多详情请看[这里](http://www.johnpapa.net/angular-function-declarations-function-expressions-and-readable-code)。 - + *为什么?*:易读,易识别哪些成员可以在View中绑定和使用。 *为什么?*:把函数的实现细节放到后面,你可以更清楚地看到重要的东西。 *为什么?*:由于函数声明会被提到顶部,所以没有必要担心在声明它之前就使用函数的问题。 - *为什么?*:你再也不用担心当 `a`依赖于 `b`时,把`var a`放到`var b`之前会中断你的代码的函数声明问题。 + *为什么?*:你再也不用担心当 `a`依赖于 `b`时,把`var a`放到`var b`之前会中断你的代码的函数声明问题。 *为什么?*:函数表达式中顺序是至关重要的。 ```javascript - /** - * avoid + /** + * avoid * Using function expressions. */ function Avengers(dataservice, logger) { @@ -575,7 +571,7 @@ Angular社区是一个热衷于分享经验的令人难以置信的社区,尽 vm.isCreditOk; vm.total = 0; - function checkCredit () { + function checkCredit () { var settings = {}; // Get the credit service base URL from config // Set credit service required headers @@ -605,7 +601,7 @@ Angular社区是一个热衷于分享经验的令人难以置信的社区,尽 vm.isCreditOk; vm.total = 0; - function checkCredit () { + function checkCredit () { return creditService.isOrderTotalOk(vm.total) .then(function(isOk) { vm.isCreditOk = isOk; }) .catch(showServiceError); @@ -616,16 +612,16 @@ Angular社区是一个热衷于分享经验的令人难以置信的社区,尽 ###保持Controller的专一性 ###### [Style [Y037](#style-y037)] - - 一个view定义一个controller,尽量不要在其它view中使用这个controller。把可重用的逻辑放到factory中,保证controller只服务于当前视图。 - + - 一个view定义一个controller,尽量不要在其它view中使用这个controller。把可重用的逻辑放到factory中,保证controller只服务于当前视图。 + *为什么?*:不同的view用同一个controller是非常不科学的,良好的端对端测试覆盖率对于保证大型应用稳定性是必需的。 ###分配Controller ###### [Style [Y038](#style-y038)] - - 当一个controller必须匹配一个view时或者任何一个组件可能被其它controller或是view重用时,连同controller的route一起定义。 - - 注:如果一个view是通过route外的其它形式加载的,那么就用`ng-controller="Avengers as vm"`语法。 + - 当一个controller必须匹配一个view时或者任何一个组件可能被其它controller或是view重用时,连同controller的route一起定义。 + + 注:如果一个view是通过route外的其它形式加载的,那么就用`ng-controller="Avengers as vm"`语法。 *为什么?*:在route中匹配controller允许不同的路由调用不同的相匹配的controller和view,当在view中通过[`ng-controller`](https://docs.angularjs.org/api/ng/directive/ngController)分配controller时,这个view总是和相同的controller相关联。 @@ -683,7 +679,7 @@ Angular社区是一个热衷于分享经验的令人难以置信的社区,尽 ###### [Style [Y040](#style-y040)] - 用`new`实例化service,用`this`实例化公共方法和变量,由于这和factory是类似的,所以为了保持统一,推荐用facotry来代替。 - + 注意:[所有的Angular services都是单例](https://docs.angularjs.org/guide/services),这意味着每个injector都只有一个实例化的service。 ```javascript @@ -727,7 +723,7 @@ Angular社区是一个热衷于分享经验的令人难以置信的社区,尽 ###### [Style [Y051](#style-y051)] - facotry是一个单例,它返回一个包含service成员的对象。 - + 注:[所有的Angular services都是单例](https://docs.angularjs.org/guide/services),这意味着每个injector都只有一个实例化的service。 ###可访问的成员放到顶部### @@ -735,7 +731,7 @@ Angular社区是一个热衷于分享经验的令人难以置信的社区,尽 - 使用从[显露模块模式](http://addyosmani.com/resources/essentialjsdesignpatterns/book/#revealingmodulepatternjavascript)派生出来的技术把service(它的接口)中可调用的成员暴露到顶部, - *为什么?*:易读,并且让你可以立即识别service中的哪些成员可以被调用,哪些成员必须进行单元测试(或者被别人嘲笑)。 + *为什么?*:易读,并且让你可以立即识别service中的哪些成员可以被调用,哪些成员必须进行单元测试(或者被别人嘲笑)。 *为什么?*:当文件内容很长时,这可以避免需要滚动才能看到暴露了哪些东西。 @@ -748,7 +744,7 @@ Angular社区是一个热衷于分享经验的令人难以置信的社区,尽 function save () { /* */ }; - function validate () { + function validate () { /* */ }; @@ -773,11 +769,11 @@ Angular社区是一个热衷于分享经验的令人难以置信的社区,尽 //////////// - function save () { + function save () { /* */ }; - function validate () { + function validate () { /* */ }; } @@ -798,9 +794,9 @@ Angular社区是一个热衷于分享经验的令人难以置信的社区,尽 *为什么?*:由于函数声明会被提到顶部,所以没有必要担心在声明它之前就使用函数的问题。 - *为什么?*:你再也不用担心当 `a`依赖于 `b`时,把`var a`放到`var b`之前会中断你的代码的函数声明问题。 + *为什么?*:你再也不用担心当 `a`依赖于 `b`时,把`var a`放到`var b`之前会中断你的代码的函数声明问题。 - *为什么?*:函数表达式中顺序是至关重要的。 + *为什么?*:函数表达式中顺序是至关重要的。 ```javascript /** @@ -962,7 +958,7 @@ Angular社区是一个热衷于分享经验的令人难以置信的社区,尽 return vm.avengers; }); } - } + } ``` ###数据调用返回一个Promise @@ -1016,7 +1012,7 @@ Angular社区是一个热衷于分享经验的令人难以置信的社区,尽 ###一个directive一个文件 ###### [Style [Y070](#style-y070)] - - 一个文件中只创建一个directive,并依照directive来命名文件。 + - 一个文件中只创建一个directive,并依照directive来命名文件。 *为什么?*:虽然把所有directive放到一个文件中很简单,但是当一些directive是跨应用的,一些是跨模块的,一些仅仅在一个模块中使用时,想把它们独立出来就非常困难了。 @@ -1077,7 +1073,7 @@ Angular社区是一个热衷于分享经验的令人难以置信的社区,尽 /** * @desc sales directive that can be used anywhere across the sales app at a company named Acme * @example
- */ + */ angular .module('sales.widgets') .directive('acmeSalesCustomerInfo', salesCustomerInfo); @@ -1163,7 +1159,7 @@ Angular社区是一个热衷于分享经验的令人难以置信的社区,尽
``` - + ```javascript /* recommended */ angular @@ -1218,9 +1214,9 @@ Angular社区是一个热衷于分享经验的令人难以置信的社区,尽 controllerAs: 'vm', bindToController: true // because the scope is isolated }; - + return directive; - + function linkFunc(scope, el, attr, ctrl) { console.log('LINK: scope.min = %s *** should be undefined', scope.min); console.log('LINK: scope.max = %s *** should be undefined', scope.max); @@ -1228,7 +1224,7 @@ Angular社区是一个热衷于分享经验的令人难以置信的社区,尽 console.log('LINK: scope.vm.max = %s', scope.vm.max); } } - + ExampleController.$inject = ['$scope']; function ExampleController($scope) { @@ -1252,7 +1248,7 @@ Angular社区是一个热衷于分享经验的令人难以置信的社区,尽 ``` 注意:当你把controller注入到link的函数或可访问的directive的attributes时,你可以把它命名为控制器的属性。 - + ```javascript // Alternative to above example function linkFunc(scope, el, attr, vm) { // 和上面例子的区别在于把vm直接传递进来 @@ -1317,13 +1313,13 @@ Angular社区是一个热衷于分享经验的令人难以置信的社区,尽 ###### [Style [Y080](#style-y080)] - 在`activate`函数中解决controller的启动逻辑。 - + *为什么?*:把启动逻辑放在一个controller中固定的位置可以方便定位、有利于保持测试的一致性,并能够避免controller中到处都是激活逻辑。 *为什么?*:`activate`这个controller使得重用刷新视图的逻辑变得很方便,把所有的逻辑都放到了一起,可以让用户更快地看到视图,可以很轻松地对`ng-view` 或 `ui-view`使用动画,用户体验更好。 注意:如果你需要在开始使用controller之前有条件地取消路由,那么就用[route resolve](#style-y081)来代替。 - + ```javascript /* avoid */ function Avengers(dataservice) { @@ -1365,7 +1361,7 @@ Angular社区是一个热衷于分享经验的令人难以置信的社区,尽 - 当你决定在过渡到视图之前取消路由时,使用route resolve。 - *为什么?*:controller在加载前可能需要一些数据,这些数据可能是从一个通过自定义factory或是[$http](https://docs.angularjs.org/api/ng/service/$http)的promise而来的。[route resolve](https://docs.angularjs.org/api/ngRoute/provider/$routeProvider)允许promise在controller的逻辑执行之前解决,因此它可能对从promise中来的数据做一些处理。 + *为什么?*:controller在加载前可能需要一些数据,这些数据可能是从一个通过自定义factory或是[$http](https://docs.angularjs.org/api/ng/service/$http)的promise而来的。[route resolve](https://docs.angularjs.org/api/ngRoute/provider/$routeProvider)允许promise在controller的逻辑执行之前解决,因此它可能对从promise中来的数据做一些处理。 *为什么?*:这段代码将在路由后的controller的激活函数中执行,视图立即加载,promise resolve的时候将会开始进行数据绑定,可以(通过`ng-view`或`ui-view`)在视图的过渡之间加个loading状态的动画。 @@ -1469,7 +1465,7 @@ Angular社区是一个热衷于分享经验的令人难以置信的社区,尽 ###### [Style [Y090](#style-y090)] - 声明依赖时避免使用缩写语法。 - + *为什么?*:组件的参数(例如controller、factory等等)将会被转换成各种乱七八糟错误的变量。例如,`common`和`dataservice`可能会变成`a`或者`b`,但是这些转换后的变量在Angular中是找不到的。 ```javascript @@ -1493,30 +1489,30 @@ Angular社区是一个热衷于分享经验的令人难以置信的社区,尽 ###### [Style [Y091](#style-y091)] - 用`$inject`手动添加Angular组件所需的依赖。 - + *为什么?*:这种技术反映了使用[`ng-annotate`](https://github.com/olov/ng-annotate)的技术,这就是我推荐的对依赖关系进行自动化创建安全压缩的方式,如果`ng-annotate`检测到已经有了注入,那么它就不会再次重复执行。 *为什么?*:可以避免依赖变成其它Angular找不到的变量,例如,`common`和`dataservice`可能会变成`a`或者`b`。 - *为什么?*:避免创建内嵌的依赖,因为一个数组太长不利于阅读,此外,内嵌的方式也会让人感到困惑,比如数组是一系列的字符串,但是最后一个却是组件的function。 + *为什么?*:避免创建内嵌的依赖,因为一个数组太长不利于阅读,此外,内嵌的方式也会让人感到困惑,比如数组是一系列的字符串,但是最后一个却是组件的function。 ```javascript /* avoid */ angular .module('app') - .controller('Dashboard', - ['$location', '$routeParams', 'common', 'dataservice', + .controller('Dashboard', + ['$location', '$routeParams', 'common', 'dataservice', function Dashboard($location, $routeParams, common, dataservice) {} - ]); + ]); ``` ```javascript /* avoid */ angular .module('app') - .controller('Dashboard', + .controller('Dashboard', ['$location', '$routeParams', 'common', 'dataservice', Dashboard]); - + function Dashboard($location, $routeParams, common, dataservice) { } ``` @@ -1528,7 +1524,7 @@ Angular社区是一个热衷于分享经验的令人难以置信的社区,尽 .controller('Dashboard', Dashboard); Dashboard.$inject = ['$location', '$routeParams', 'common', 'dataservice']; - + function Dashboard($location, $routeParams, common, dataservice) { } ``` @@ -1571,7 +1567,7 @@ Angular社区是一个热衷于分享经验的令人难以置信的社区,尽 ###### [Style [Y092](#style-y092)] - 用`$inject`手动给Angular组件添加路由解析器依赖。 - + *为什么?*:这种技术打破了路由解析的匿名函数的形式,易读。 *为什么?*:`$inject`语句可以让任何依赖都可以安全压缩。 @@ -1604,7 +1600,7 @@ Angular社区是一个热衷于分享经验的令人难以置信的社区,尽 ###### [Style [Y100](#style-y100)] - 在[Gulp](http://gulpjs.com)或[Grunt](http://gruntjs.com)中使用[ng-annotate](//github.com/olov/ng-annotate),用`/** @ngInject */`对需要自动依赖注入的function进行注释。 - + *为什么?*:可以避免代码中的依赖使用到任何不安全的写法。 *为什么?*:不推荐用[`ng-min`](https://github.com/btford/ngmin)。 @@ -1681,7 +1677,7 @@ Angular社区是一个热衷于分享经验的令人难以置信的社区,尽 ###### [Style [Y101](#style-y101)] - 在自动化任务中使用[gulp-ng-annotate](https://www.npmjs.org/package/gulp-ng-annotate)或[grunt-ng-annotate](https://www.npmjs.org/package/grunt-ng-annotate),把`/* @ngInject */`注入到任何有依赖关系函数的前面。 - + *为什么?*:ng-annotate会捕获大部分的依赖关系,但是有时候需要借助于`/* @ngInject */`语法提示。 下面的代码是gulp任务使用ngAnnotate的例子。 @@ -1716,7 +1712,7 @@ Angular社区是一个热衷于分享经验的令人难以置信的社区,尽 ###### [Style [Y110](#style-y110)] - 使用一个[decorator](https://docs.angularjs.org/api/auto/service/$provide#decorator),在配置的时候用[`$provide`](https://docs.angularjs.org/api/auto/service/$provide)服务,当发生异常时,在[`$exceptionHandler`](https://docs.angularjs.org/api/ng/service/$exceptionHandler)服务中执行自定义的处理方法。 - + *为什么?*:在开发时和运行时提供了一种统一的方式来处理未被捕获的Angular异常。 注:另一个选项是用来覆盖service的,这个可以代替decorator,这是一个非常nice的选项,但是如果你想保持默认行为,那么推荐你扩展一个decorator。 @@ -1738,9 +1734,9 @@ Angular社区是一个热衷于分享经验的令人难以置信的社区,尽 function extendExceptionHandler($delegate, toastr) { return function(exception, cause) { $delegate(exception, cause); - var errorData = { - exception: exception, - cause: cause + var errorData = { + exception: exception, + cause: cause }; /** * Could add the error to a service's collection, @@ -1839,10 +1835,10 @@ Angular社区是一个热衷于分享经验的令人难以置信的社区,尽 - 遵循以描述组件功能,然后是类型(可选)的方式来给所有的组件提供统一的命名,我推荐的做法是`feature.type.js`。大多数文件都有2个名字。 * 文件名 (`avengers.controller.js`) * 带有Angular的注册组件名 (`AvengersController`) - + *为什么?*:命名约定有助于为一目了然地找到内容提供一个统一的方式,在项目中和团队中保持统一性是非常重要的,保持统一性对于跨公司来说提供了巨大的效率。 - *为什么?*:命名约定应该只为代码的检索和沟通提供方便。 + *为什么?*:命名约定应该只为代码的检索和沟通提供方便。 ###功能文件命名 ###### [Style [Y121](#style-y121)] @@ -1855,7 +1851,7 @@ Angular社区是一个热衷于分享经验的令人难以置信的社区,尽 ```javascript /** - * common options + * common options */ // Controllers @@ -1884,7 +1880,7 @@ Angular社区是一个热衷于分享经验的令人难以置信的社区,尽 // constants constants.js - + // module definition avengers.module.js @@ -1894,14 +1890,14 @@ Angular社区是一个热衷于分享经验的令人难以置信的社区,尽 // configuration avengers.config.js - + // directives avenger-profile.directive.js avenger-profile.directive.spec.js ``` 注意:另外一种常见的约定就是不要用`controller`这个词来给controller文件命名,例如不要用`avengers.controller.js`,而是用`avengers.js`。所有其它的约定都坚持使用类型作为后缀,但是controller是组件中最为常用的类型,因此这种做法的好处貌似仅仅是节省了打字,但是仍然很容易识别。我建议你为你的团队选择一种约定,并且要保持统一性。我喜欢的命名方式是`avengers.controller.js`。 - + ```javascript /** * recommended @@ -1914,7 +1910,7 @@ Angular社区是一个热衷于分享经验的令人难以置信的社区,尽 ###测试文件命名 ###### [Style [Y122](#style-y122)] - - 和组件命名差不多,带上一个`spec`后缀。 + - 和组件命名差不多,带上一个`spec`后缀。 *为什么?*:为快速识别组件提供统一的方式。 @@ -1949,7 +1945,7 @@ Angular社区是一个热衷于分享经验的令人难以置信的社区,尽 .module .controller('HeroAvengersController', HeroAvengersController); - function HeroAvengers(){ } + function HeroAvengers(){ } ``` ###Controller命名后缀 @@ -1971,7 +1967,7 @@ Angular社区是一个热衷于分享经验的令人难以置信的社区,尽 function AvengersController(){ } ``` - + ###Factory命名 ###### [Style [Y125](#style-y125)] @@ -1980,7 +1976,7 @@ Angular社区是一个热衷于分享经验的令人难以置信的社区,尽 *为什么?*:可以快速识别和引用factory。 *为什么?*:避免与内部使用`$`前缀的服务发生冲突。 - + ```javascript /** * recommended @@ -2006,7 +2002,7 @@ Angular社区是一个热衷于分享经验的令人难以置信的社区,尽 * recommended */ - // avenger-profile.directive.js + // avenger-profile.directive.js angular .module .directive('xxAvengerProfile', xxAvengerProfile); @@ -2050,7 +2046,7 @@ Angular社区是一个热衷于分享经验的令人难以置信的社区,尽 *为什么是LIFT?*: 提供一个有良好扩展的结构,并且是模块化的,更快的找到代码能够帮助开发者提高效率。另一种检查你的app结构的方法就是问你自己:你能多块地打开涉及到一个功能的所有相关文件并开始工作? 当我发现我的的代码结构很恶心的时候,我就重新看看LIFT准则。 - + 1. 轻松定位代码(L) 2. 一眼识别代码(I) 3. 平直的代码结构(层级不要太多)(F) @@ -2083,7 +2079,7 @@ Angular社区是一个热衷于分享经验的令人难以置信的社区,尽 ###Identify ###### [Style [Y142](#style-y142)] - + - 当你看到一个文件时你应该能够立即知道它包含了什么、代表了什么。 *为什么?*:你花费更少的时间来了解代码代表了什么,并且变得更加高效。如果这意味着你需要更长的名字,那么就这么干吧。文件名一定要具有描述性,保持和文件内容互为一体。避免文件中有多个controller,多个service,甚至是混合的。 @@ -2119,13 +2115,13 @@ Angular社区是一个热衷于分享经验的令人难以置信的社区,尽 - 把定义应用程序总体布局的组件放到`layout`文件夹中,如导航、内容区等等。 *为什么?*:复用。 - + ###按功能划分文件夹结构 ###### [Style [Y152](#style-y152)] - 按照它们代表的功能来给创建的文件夹命名,当文件夹包含的文件超过7个(根据需要自行调整数量限制),就考虑新建文件夹。 - *为什么?*:开发者可以快速定位代码、快速识别文件代表的意思,结构尽可能平直,没有重复,没有多余名字。 + *为什么?*:开发者可以快速定位代码、快速识别文件代表的意思,结构尽可能平直,没有重复,没有多余名字。 *为什么?*:LIFT规范都包括在内。 @@ -2141,21 +2137,21 @@ Angular社区是一个热衷于分享经验的令人难以置信的社区,尽 app/ app.module.js app.config.js - directives/ - calendar.directive.js - calendar.directive.html - user-profile.directive.js - user-profile.directive.html - services/ - dataservice.js + directives/ + calendar.directive.js + calendar.directive.html + user-profile.directive.js + user-profile.directive.html + services/ + dataservice.js localstorage.js - logger.js + logger.js spinner.js layout/ - shell.html + shell.html shell.controller.js - topnav.html - topnav.controller.js + topnav.html + topnav.controller.js people/ attendees.html attendees.controller.js @@ -2165,11 +2161,11 @@ Angular社区是一个热衷于分享经验的令人难以置信的社区,尽 speaker-detail.html speaker-detail.controller.js sessions/ - sessions.html + sessions.html sessions.controller.js sessions.routes.js session-detail.html - session-detail.controller.js + session-detail.controller.js ``` ![实例App结构](https://raw.githubusercontent.com/johnpapa/angular-styleguide/master/assets/modularity-2.png) @@ -2177,49 +2173,49 @@ Angular社区是一个热衷于分享经验的令人难以置信的社区,尽 注意:不要使用按类型划分文件夹结构,因为如果这样的话,当做一个功能时,需要在多个文件夹中来回切换。当应用程序有5个、10个,甚至是25个以上的view、controller(或其他feature)时,这种方式将迅速变得不实用,这就使得它定位文件比按功能分文件夹的方式要困难的多。 ```javascript - /* + /* * avoid * Alternative folders-by-type. * I recommend "folders-by-feature", instead. */ - + app/ app.module.js app.config.js app.routes.js directives.js controllers/ - attendees.js - session-detail.js - sessions.js - shell.js - speakers.js - speaker-detail.js + attendees.js + session-detail.js + sessions.js + shell.js + speakers.js + speaker-detail.js topnav.js directives/ calendar.directive.js calendar.directive.html user-profile.directive.js user-profile.directive.html - services/ - dataservice.js + services/ + dataservice.js localstorage.js - logger.js - spinner.js + logger.js + spinner.js views/ - attendees.html + attendees.html session-detail.html - sessions.html - shell.html - speakers.html + sessions.html + shell.html + speakers.html speaker-detail.html - topnav.html - ``` - + topnav.html + ``` + **[返回顶部](#目录)** ## 模块化 - + ###许多小的、独立的模块 ###### [Style [Y160](#style-y160)] @@ -2260,7 +2256,7 @@ Angular社区是一个热衷于分享经验的令人难以置信的社区,尽 - 为通用service创建代表可重用的应用程序块的模块,例如异常处理、日志记录、诊断、安全性和本地数据储藏等模块。 *为什么?*:这些类型的功能在很多应用程序中都需要用到,所以把它们分离到自己的模块中,它们可以变成通用的应用程序,也能被跨应用地进行重用。 - + ###模块依赖 ###### [Style [Y165](#style-y165)] @@ -2296,9 +2292,9 @@ Angular社区是一个热衷于分享经验的令人难以置信的社区,尽 .module('app') .config(configure); - configure.$inject = + configure.$inject = ['routerHelperProvider', 'exceptionHandlerProvider', 'toastr']; - + function configure (routerHelperProvider, exceptionHandlerProvider, toastr) { exceptionHandlerProvider.configure(config.appErrorPrefix); configureStateHelper(); @@ -2424,7 +2420,7 @@ Angular社区是一个热衷于分享经验的令人难以置信的社区,尽 - 在服务器上使用[PhantomJS](http://phantomjs.org/)来运行你的测试。 - *为什么?*:PhantomJS是一个headless browser,无需一个“可视”的浏览器来帮助你运行测试。因此你的服务器上不需要安装Chrome、Safari、IE或是其它浏览器。 + *为什么?*:PhantomJS是一个headless browser,无需一个“可视”的浏览器来帮助你运行测试。因此你的服务器上不需要安装Chrome、Safari、IE或是其它浏览器。 注意:你仍然需要在你的环境下测试所有浏览器,来满足用户的需求。 @@ -2497,7 +2493,7 @@ Angular社区是一个热衷于分享经验的令人难以置信的社区,尽 ###Sub Second ###### [Style [Y211](#style-y211)] - - 使用短持续性的动画,我一般使用300ms,然后调整到合适的时间。 + - 使用短持续性的动画,我一般使用300ms,然后调整到合适的时间。 *为什么?*:长时间的动画容易造成用户认为程序性能太差的影响。 @@ -2553,7 +2549,7 @@ Angular社区是一个热衷于分享经验的令人难以置信的社区,尽 /** * @name logError * @desc Logs errors - * @param {String} msg Message to log + * @param {String} msg Message to log * @returns {String} * @memberOf Factories.Logger */ @@ -2575,7 +2571,7 @@ Angular社区是一个热衷于分享经验的令人难以置信的社区,尽 - 用JS Hint来分析你的JavaScript代码,确保你自定义了JS Hint选项文件并且包含在源控制里。详细信息:[JS Hint文档](http://www.jshint.com/docs/)。 - *为什么?*:提交代码到原版本之前先发出警告。 + *为什么?*:提交代码到原版本之前先发出警告。 *为什么?*:统一性。 @@ -2789,11 +2785,11 @@ Angular社区是一个热衷于分享经验的令人难以置信的社区,尽 ###Sublime Text ###### [Style [Y250](#style-y250)] - - Angular片段遵循这些规范。 + - Angular片段遵循这些规范。 - - 下载[Sublime Angular snippets](assets/sublime-angular-snippets?raw=true) + - 下载[Sublime Angular snippets](assets/sublime-angular-snippets?raw=true) - 把它放到Packages文件夹中 - - 重启Sublime + - 重启Sublime - 在JavaScript文件中输入下面的命令然后按下`TAB`键即可: ```javascript @@ -2819,12 +2815,12 @@ Angular社区是一个热衷于分享经验的令人难以置信的社区,尽 - 你可以把它们导入到WebStorm设置中: - - 下载[WebStorm Angular file templates and snippets](https://github.com/johnpapa/angular-styleguide/blob/master/assets/webstorm-angular-file-template.settings.jar?raw=true) + - 下载[WebStorm Angular file templates and snippets](https://github.com/johnpapa/angular-styleguide/blob/master/assets/webstorm-angular-file-template.settings.jar?raw=true) - 打开WebStorm点击`File`菜单 - 选择`Import Settings`菜单选项 - 选择文件点击`OK` - 在JavaScript文件中输入下面的命令然后按下`TAB`键即可: - + ```javascript ng-c // creates an Angular controller ng-f // creates an Angular factory @@ -3075,7 +3071,7 @@ Angular社区是一个热衷于分享经验的令人难以置信的社区,尽 ## 许可证 - - **tldr;** 如果可以的话,使用本规范的时候还是指明归属吧。 + - **tldr;** 如果可以的话,使用本规范的时候还是指明归属吧。 ### Copyright From f42ee71a8fb6070440e0a7294d116b96448a0c3e Mon Sep 17 00:00:00 2001 From: Javier Pena Date: Thu, 20 Aug 2015 01:26:27 -0500 Subject: [PATCH 402/567] Added modified snippets for vim's ultisnips plugin Filenames are prepended with 'javascript_' so UltiSnips will load them for javascript files. --- README.md | 6 ++++ .../javascript_angular.controller.snippets | 22 ++++++++++++ .../javascript_angular.directive.snippets | 35 +++++++++++++++++++ .../javascript_angular.factory.snippets | 22 ++++++++++++ .../javascript_angular.filter.snippets | 19 ++++++++++ .../javascript_angular.module.snippets | 10 ++++++ .../javascript_angular.service.snippets | 19 ++++++++++ 7 files changed, 133 insertions(+) create mode 100644 assets/vim-angular-ultisnips/javascript_angular.controller.snippets create mode 100644 assets/vim-angular-ultisnips/javascript_angular.directive.snippets create mode 100644 assets/vim-angular-ultisnips/javascript_angular.factory.snippets create mode 100644 assets/vim-angular-ultisnips/javascript_angular.filter.snippets create mode 100644 assets/vim-angular-ultisnips/javascript_angular.module.snippets create mode 100644 assets/vim-angular-ultisnips/javascript_angular.service.snippets diff --git a/README.md b/README.md index 3f5ef258..47bbbfc3 100644 --- a/README.md +++ b/README.md @@ -2974,6 +2974,12 @@ Use file templates or snippets to help follow consistent styles and patterns. He - set [neosnippet.vim](https://github.com/Shougo/neosnippet.vim) - copy snippets to snippet directory + - vim UltiSnips snippets that follow these styles and guidelines. + + - Download the [vim Angular UltiSnips snippets](assets/vim-angular-ultisnips?raw=true) + - set [UltiSnips](https://github.com/SirVer/ultisnips) + - copy snippets to UltiSnips directory + ```javascript ngcontroller // creates an Angular controller ngdirective // creates an Angular directive diff --git a/assets/vim-angular-ultisnips/javascript_angular.controller.snippets b/assets/vim-angular-ultisnips/javascript_angular.controller.snippets new file mode 100644 index 00000000..51cfdc16 --- /dev/null +++ b/assets/vim-angular-ultisnips/javascript_angular.controller.snippets @@ -0,0 +1,22 @@ +snippet ngcontroller +(function() { + 'use strict'; + + angular + .module('${1:module}') + .controller('${2:Controller}Controller', $2Controller); + + /* @ngInject */ + function $2Controller(${3:dependencies}) { + var vm = this; + vm.title = '$2Controller'; + + activate(); + + //////////////// + + function activate() { + } + } +})(); +endsnippet diff --git a/assets/vim-angular-ultisnips/javascript_angular.directive.snippets b/assets/vim-angular-ultisnips/javascript_angular.directive.snippets new file mode 100644 index 00000000..14c882f5 --- /dev/null +++ b/assets/vim-angular-ultisnips/javascript_angular.directive.snippets @@ -0,0 +1,35 @@ +snippet ngdirective +(function() { + 'use strict'; + + angular + .module('${1:module}') + .directive('${2:directive}', $2); + + /* @ngInject */ + function $2(${3:dependencies}) { + // Usage: + // + // Creates: + // + var directive = { + bindToController: true, + controller: ${4:Controller}, + controllerAs: '${5:vm}', + link: link, + restrict: 'A', + scope: { + } + }; + return directive; + + function link(scope, element, attrs) { + } + } + + /* @ngInject */ + function $4() { + + } +})(); +endsnippet diff --git a/assets/vim-angular-ultisnips/javascript_angular.factory.snippets b/assets/vim-angular-ultisnips/javascript_angular.factory.snippets new file mode 100644 index 00000000..41966ff7 --- /dev/null +++ b/assets/vim-angular-ultisnips/javascript_angular.factory.snippets @@ -0,0 +1,22 @@ +snippet ngfactory +(function() { + 'use strict'; + + angular + .module('${1:module}') + .factory('${2:factory}', $2); + + /* @ngInject */ + function $2(${3:dependencies}) { + var service = { + ${4:func}: $4 + }; + return service; + + //////////////// + + function $4() { + } + } +})(); +endsnippet diff --git a/assets/vim-angular-ultisnips/javascript_angular.filter.snippets b/assets/vim-angular-ultisnips/javascript_angular.filter.snippets new file mode 100644 index 00000000..e2b10ef6 --- /dev/null +++ b/assets/vim-angular-ultisnips/javascript_angular.filter.snippets @@ -0,0 +1,19 @@ +snippet ngfilter +(function() { + 'use strict'; + + angular + .module('${1:module}') + .filter('${2:filter}', $2); + + function $2() { + return $2Filter; + + //////////////// + function $2Filter(${3:params}) { + return $3; + }; + } + +})(); +endsnippet diff --git a/assets/vim-angular-ultisnips/javascript_angular.module.snippets b/assets/vim-angular-ultisnips/javascript_angular.module.snippets new file mode 100644 index 00000000..972018df --- /dev/null +++ b/assets/vim-angular-ultisnips/javascript_angular.module.snippets @@ -0,0 +1,10 @@ +snippet ngmodule +(function() { + 'use strict'; + + angular + .module('${1:module}', [ + '${2:dependencies}' + ]); +})(); +endsnippet diff --git a/assets/vim-angular-ultisnips/javascript_angular.service.snippets b/assets/vim-angular-ultisnips/javascript_angular.service.snippets new file mode 100644 index 00000000..53a8692d --- /dev/null +++ b/assets/vim-angular-ultisnips/javascript_angular.service.snippets @@ -0,0 +1,19 @@ +snippet ngservice +(function() { + 'use strict'; + + angular + .module('${1:module}') + .service('${2:Service}', $2); + + /* @ngInject */ + function $2(${3:dependencies}) { + this.${4:func} = $4; + + //////////////// + + function $4() { + } + } +})(); +endsnippet From 7333a935ab76b9d8433e9897c3ea27331ec8ff7a Mon Sep 17 00:00:00 2001 From: Bruno Wego Date: Sat, 22 Aug 2015 17:38:27 -0300 Subject: [PATCH 403/567] Rename PT-BR.md to pt-BR.md --- i18n/{PT-BR.md => pt-BR.md} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename i18n/{PT-BR.md => pt-BR.md} (100%) diff --git a/i18n/PT-BR.md b/i18n/pt-BR.md similarity index 100% rename from i18n/PT-BR.md rename to i18n/pt-BR.md From 326a0fa5ffa15646611fa00d8af7103abba889ae Mon Sep 17 00:00:00 2001 From: jedgell Date: Sun, 23 Aug 2015 02:56:28 -0400 Subject: [PATCH 404/567] Clarified a statement which suggested $scope was injectable into factories. Per the docs at https://docs.angularjs.org/error/$injector/unpr Attempting to inject a scope object into anything that's not a controller or a directive, for example a service, will also throw an Unknown provider: $scopeProvider <- $scope error. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 47bbbfc3..26b3da03 100644 --- a/README.md +++ b/README.md @@ -329,7 +329,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see *Why?*: `controllerAs` is syntactic sugar over `$scope`. You can still bind to the View and still access `$scope` methods. - *Why?*: Helps avoid the temptation of using `$scope` methods inside a controller when it may otherwise be better to avoid them or move them to a factory. Consider using `$scope` in a factory, or if in a controller just when needed. For example when publishing and subscribing events using [`$emit`](https://docs.angularjs.org/api/ng/type/$rootScope.Scope#$emit), [`$broadcast`](https://docs.angularjs.org/api/ng/type/$rootScope.Scope#$broadcast), or [`$on`](https://docs.angularjs.org/api/ng/type/$rootScope.Scope#$on) consider moving these uses to a factory and invoke from the controller. + *Why?*: Helps avoid the temptation of using `$scope` methods inside a controller when it may otherwise be better to avoid them or move the method to a factory, and reference them from the controller. Consider using `$scope` in a controller only when needed. For example when publishing and subscribing events using [`$emit`](https://docs.angularjs.org/api/ng/type/$rootScope.Scope#$emit), [`$broadcast`](https://docs.angularjs.org/api/ng/type/$rootScope.Scope#$broadcast), or [`$on`](https://docs.angularjs.org/api/ng/type/$rootScope.Scope#$on) consider moving these uses to a factory and invoke from the controller. ```javascript /* avoid */ From 7c50c85d08a84bc456e5a76c215cf60dadd7fe2b Mon Sep 17 00:00:00 2001 From: angelochiello Date: Thu, 27 Aug 2015 11:16:27 +0200 Subject: [PATCH 405/567] [it-IT] PR #485 Updated as PR #485 --- i18n/it-IT.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/i18n/it-IT.md b/i18n/it-IT.md index f2910846..a1c69207 100644 --- a/i18n/it-IT.md +++ b/i18n/it-IT.md @@ -1610,7 +1610,7 @@ Invece usa la più semplice sintassi setter. ### ng-annotate ###### [Stile [Y100](#stile-y100)] - - Usa [ng-annotate](//github.com/olov/ng-annotate) per [Gulp](http://gulpjs.com) o [Grunt](http://gruntjs.com) e commenta le funzioni che necessitano di automatizzare la dependency injection usando `/** @ngInject */` + - Usa [ng-annotate](//github.com/olov/ng-annotate) per [Gulp](http://gulpjs.com) o [Grunt](http://gruntjs.com) e commenta le funzioni che necessitano di automatizzare la dependency injection usando `/* @ngInject */` *Perché?*: Questo salvaguarda il tuo codice da ogni dipendenza che non segua le pratiche a prova di minificazione From efb5f55bf6d35ebb7f0a9b45b8e2e09f5787fe07 Mon Sep 17 00:00:00 2001 From: angelochiello Date: Thu, 27 Aug 2015 11:20:19 +0200 Subject: [PATCH 406/567] [it-IT] PR #498 Updated as PR #498 --- i18n/it-IT.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/i18n/it-IT.md b/i18n/it-IT.md index a1c69207..50af9867 100644 --- a/i18n/it-IT.md +++ b/i18n/it-IT.md @@ -2967,7 +2967,12 @@ Usa file template o snippet che ti aiutino a seguire stili e schemi consistentem - Scarica gli [snippet vim per Angular](assets/vim-angular-snippets?raw=true) - setta [neosnippet.vim](https://github.com/Shougo/neosnippet.vim) - copia gli snippets nella directory snippet + + - snippet vim UltiSnips che seguono questi stilili e linee guida. + - Scarica gli [snippet vim Angular UltiSnips](assets/vim-angular-ultisnips?raw=true) + - setta [UltiSnips](https://github.com/SirVer/ultisnips) + - copia gli snippet nella directory UltiSnips ```javascript ngcontroller // crea un controller Angular ngdirective // crea una directive Angular From c0268ac05117c3e276ae9f6cbf72a4a8cad3dde7 Mon Sep 17 00:00:00 2001 From: angelochiello Date: Thu, 27 Aug 2015 11:28:14 +0200 Subject: [PATCH 407/567] [it-IT] PR #504 Updated as PR #504 --- i18n/it-IT.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/i18n/it-IT.md b/i18n/it-IT.md index 50af9867..a48e0f29 100644 --- a/i18n/it-IT.md +++ b/i18n/it-IT.md @@ -329,7 +329,7 @@ Invece usa la più semplice sintassi setter. *Perché?*: `controllerAs` è una semplificazione sintattica per `$scope`. Puoi ancora fare il binding con la View ed accedere ai metodi di `$scope`. - *Perché?*: Aiuta ad evitare la tentazione ad usare i metodi di `$scope` dentro un controller quando sarebbe meglio evitare o spostarli in una factory. Considera l'uso di `$scope` in una factory o, se in un controller, soltanto quando necessario. Per esempio, quando si pubblicano o sottoscrivono eventi usando [`$emit`](https://docs.angularjs.org/api/ng/type/$rootScope.Scope#$emit), [`$broadcast`](https://docs.angularjs.org/api/ng/type/$rootScope.Scope#$broadcast), o [`$on`](https://docs.angularjs.org/api/ng/type/$rootScope.Scope#$on) considera di spostare questi tipi di utilizzi in una facotry e di invocarli da un controller. + *Perché?*: Aiuta ad evitare la tentazione ad usare i metodi di `$scope` dentro un controller quando sarebbe meglio evitare o spostarli in una factory quindi referenziarli dal controller. Considera l'uso di `$scope` in un controller soltanto quando necessario. Per esempio, quando si pubblicano o sottoscrivono eventi usando [`$emit`](https://docs.angularjs.org/api/ng/type/$rootScope.Scope#$emit), [`$broadcast`](https://docs.angularjs.org/api/ng/type/$rootScope.Scope#$broadcast), o [`$on`](https://docs.angularjs.org/api/ng/type/$rootScope.Scope#$on) considera di spostare questi tipi di utilizzi in una facotry e di invocarli da un controller. ```javascript /* evitare */ From 23feefefb21977f067c6ef53c668317689713e00 Mon Sep 17 00:00:00 2001 From: Zlati Pehlivanov Date: Thu, 27 Aug 2015 14:07:17 +0300 Subject: [PATCH 408/567] fix #458 add: netbeans code templates xml --- ...es-editor-settings-CustomCodeTemplates.xml | 208 ++++++++++++++++++ 1 file changed, 208 insertions(+) create mode 100644 assets/org-netbeans-modules-editor-settings-CustomCodeTemplates.xml diff --git a/assets/org-netbeans-modules-editor-settings-CustomCodeTemplates.xml b/assets/org-netbeans-modules-editor-settings-CustomCodeTemplates.xml new file mode 100644 index 00000000..93f7bfa1 --- /dev/null +++ b/assets/org-netbeans-modules-editor-settings-CustomCodeTemplates.xml @@ -0,0 +1,208 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From c75a0eacaf583378502fd745895ded669a899e46 Mon Sep 17 00:00:00 2001 From: Lauriane Date: Thu, 27 Aug 2015 21:50:26 +0200 Subject: [PATCH 409/567] Correct french wording --- i18n/fr-FR.md | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/i18n/fr-FR.md b/i18n/fr-FR.md index 96f369c1..25f18d79 100644 --- a/i18n/fr-FR.md +++ b/i18n/fr-FR.md @@ -901,7 +901,7 @@ Bien que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'est ut - *Refactorez* la logique pour faire les opérations et interactions avec les données dans une *factory*. Rendez les services de données responsables des appels *XHR*, du *local storage*, du stockage en mémoire, ou de toute autre opération sur les données. - *Pourquoi ?* : Les responsabilités du contrôleur sont la présentation et l'assemblage des informations pour la vue. Il ne devrait pas avoir à se soucier de la façon dont les données sont récupérées mais seulement de la façon de les demander. Séparer les services de données transforme la logique du contrôleur en logique de « À quel service vais-je demander ces données ? ». Le contrôleur esr alors plus simple est plus focalisé sur sa vue. + *Pourquoi ?* : Les responsabilités du contrôleur sont la présentation et l'assemblage des informations pour la vue. Il ne devrait pas avoir à se soucier de la façon dont les données sont récupérées mais seulement de la façon de les demander. Séparer les services de données transforme la logique du contrôleur en logique de « À quel service vais-je demander ces données ? ». Le contrôleur est alors plus simple est plus focalisé sur sa vue. *Pourquoi ?* : Cela rend plus facile à tester (*mocké* ou en utilisant le vrai) les appels aux données lorsque l'on teste un contrôleur qui utilise un service de données. @@ -1116,7 +1116,7 @@ Bien que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'est ut ### Manipuler le DOM dans une directive ###### [Style [Y072](#style-y072)] - - Quand vous manipulez le DOM est directement, utilisez une directive. S'il existe des alternatives, comme par exemple le CSS pour définir les styles ou les [services d'animation](https://docs.angularjs.org/api/ngAnimate), les *templates* Angular , [`ngShow`](https://docs.angularjs.org/api/ng/directive/ngShow) ou [`ngHide`](https://docs.angularjs.org/api/ng/directive/ngHide), utilisez les à la place. Par exemple si la directive affiche ou cache un élément, utilisez ngHide ou ngShow. + - Quand vous manipulez le DOM directement, utilisez une directive. S'il existe des alternatives, comme par exemple le CSS pour définir les styles ou les [services d'animation](https://docs.angularjs.org/api/ngAnimate), les *templates* Angular , [`ngShow`](https://docs.angularjs.org/api/ng/directive/ngShow) ou [`ngHide`](https://docs.angularjs.org/api/ng/directive/ngHide), utilisez les à la place. Par exemple si la directive affiche ou cache un élément, utilisez ngHide ou ngShow. *Pourquoi ?* : La manipulation du DOM peut être difficile à tester, déboguer, et il y a souvent une meilleure façon de faire (ex : CSS, animations, *templates*). @@ -1767,7 +1767,7 @@ Bien que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'est ut *Pourquoi ?* : Cela fournit un moyen cohérent pour intercepter les exceptions qui peuvent être déclenchées dans votre code (par exemple, pendant une requête XHR ou lors d'un échec de *promise*). - Note : Le intercepteur d'exceptions est bon pour intercepter et réagir à des exceptions spécifiques potentielles provenant d'appels qui pourraient en produire. Par exemple, lorsque on fait une requête XHR pour récupérer des données d'un service web distant et que vous voulez intercepter n'importe quelles exceptions provenant de ce service uniquement et réagir seulement à celles-ci. + Note : L'intercepteur d'exceptions est bon pour intercepter et réagir à des exceptions spécifiques potentielles provenant d'appels qui pourraient en produire. Par exemple, lorsque on fait une requête XHR pour récupérer des données d'un service web distant et que vous voulez intercepter n'importe quelles exceptions provenant de ce service uniquement et réagir seulement à celles-ci. ```javascript /* recommandé */ @@ -2305,7 +2305,7 @@ Bien que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'est ut *Pourquoi ?* : Les fonctionnalités propres à l'application telles que les services de données partagées deviennent faciles à repérer et partager au sein d'un `app.core` (choisissez un nom de votre choix pour ce module). - Note : C'est un stratégie pour la cohérence. Il y a ici beaucoup de bons choix. Choisissez-en une qui soit cohérente, suivez les règles des dépendances d'Angular, et la maintenance et la montée en charge sera facilitée. + Note : C'est une stratégie pour la cohérence. Il y a ici beaucoup de bons choix. Choisissez-en une qui soit cohérente, qui suit les règles des dépendances d'Angular, et qui facilite la maintenance et la montée en charge. > Mes structures peuvent varier légèrement entre les projets mais elles suivent toutes ces règles pour la structure et la modularité. L'implémentation peut varier en fonction des fonctionnalités et de l'équipe. En d'autres termes, ne vous paralysez pas sur une structure exactement semblable mais pensez votre structure en termes de cohérence, maintenabilité, et efficacité. @@ -2388,9 +2388,9 @@ Bien que ce guide explique le *quoi*, le *pourquoi* et le *comment*, il m'est ut **[Retour en haut de page](#table-des-matières)** ## Tests -Les tests unitaires aident à maintenir un code source propre, ainsi j'ai inclut quelques unes de mes recommandations sur les bases des tests unitaires avec des liens pour plus d'informations. +Les tests unitaires aident à maintenir un code source propre, ainsi j'ai inclus quelques unes de mes recommandations sur les bases des tests unitaires avec des liens pour plus d'informations. -### Écrire les tests avec des scenarii +### Écrire les tests avec des scenario ###### [Style [Y190](#style-y190)] - Écrivez un ensemble de tests pour chaque scenario. Commencer avec un test vide et complétez-les à mesure que vous écrivez le code pour le scenario. @@ -2510,7 +2510,7 @@ Les tests unitaires aident à maintenir un code source propre, ainsi j'ai inclut - Exécutez JSHint sur vos tests. - *Pourquoi ?* : Les tests' c'est aussi du code. JSHint peut vous aider à identifier les problèmes de qualité de code qui pourrait amener les tests à fonctionner de façon incorrecte. + *Pourquoi ?* : Les tests c'est aussi du code. JSHint peut vous aider à identifier les problèmes de qualité de code qui pourrait amener les tests à fonctionner de façon incorrecte. ### Assouplissement des règles de JSHint avec les variables globales dans les tests ###### [Style [Y196](#style-y196)] @@ -2531,10 +2531,10 @@ Les tests unitaires aident à maintenir un code source propre, ainsi j'ai inclut ![Outils de test](https://raw.githubusercontent.com/johnpapa/angular-styleguide/master/assets/testing-tools.png) -### Organizing Tests +### Organisation des tests ###### [Style [Y197](#style-y197)] - - Placez les fichiers des tests unitaires (specs) à parallèlement du code client. Placez les specs qui sont en charge de l'intégration avec le serveur ou les celles qui testent plusieurs composants dans un répertoire `tests` séparé. + - Placez les fichiers des tests unitaires (specs) parallèle au code client. Placez les specs qui sont en charge de l'intégration avec le serveur ou celles qui testent plusieurs composants dans un répertoire `tests` séparé. *Pourquoi ?* : Les tests unitaires sont en corrélation directe avec les composants et fichiers qu'ils testent dans le code source. @@ -2837,7 +2837,7 @@ Les tests unitaires aident à maintenir un code source propre, ainsi j'ai inclut ###### [Style [Y241](#style-y241)] - - Utilisez des constantes pour les valeurs qui ne changent pas et ne viennent pas d'un autre service. Quand des contentes ne sont pas utilisées que par un module qui peut être ré-utilisé dans d'autres applications, placez les constantes dans un seul fichier par module nommé comme le module. Tant que c'est possible, gardez les constantes dans le module principal dans un fichier `constants.js`. + - Utilisez des constantes pour les valeurs qui ne changent pas et ne viennent pas d'un autre service. Quand des constantes ne sont utilisées que par un module qui peut être ré-utilisé dans d'autres applications, placez les constantes dans un seul fichier par module nommé comme le module. Tant que c'est possible, gardez les constantes dans le module principal dans un fichier `constants.js`. *Pourquoi ?* : Une valeur qui peut changer, même rarement, devrait être récupérée d'un service afin de ne pas avoir à changer le code source. Par exemple, une URL pour un service de données pourrait être définie comme constante mais il serait mieux de lire cette valeur par appel à un web service. @@ -3114,7 +3114,7 @@ Utilisez [Gulp](http://gulpjs.com) ou [Grunt](http://gruntjs.com) pour créer de - Utilisez l'automatisation des tâches pour lister les fichiers de définition de module `*.module.js` avant tout autre fichier JavaScript de l'application. - *Pourquoi ?* : Angular a besoin que la définition des modules soit faire avant qu'ils puissent être utilisés. + *Pourquoi ?* : Angular a besoin que la définition des modules soit faite avant qu'ils puissent être utilisés. *Pourquoi ?* : Nommer les modules avec un pattern spécifique tel que `*.module.js` les rends faciles à aller chercher avec une expression régulière et à les lister. From 9edaf82eb08bee018e554140d2c1d71a7a04e98a Mon Sep 17 00:00:00 2001 From: matt Date: Thu, 27 Aug 2015 13:28:02 -0700 Subject: [PATCH 410/567] typo --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 26b3da03..1b48be9d 100644 --- a/README.md +++ b/README.md @@ -2017,7 +2017,7 @@ While this guide explains the *what*, *why* and *how*, I find it helpful to see function creditService() { } - // credit.service.js + // customer.service.js angular .module .service('customersService', customersService); From 58006aa88ccc7fa8ba86d3c63a4cd8d7ef6c820a Mon Sep 17 00:00:00 2001 From: John Papa Date: Thu, 27 Aug 2015 22:13:55 -0700 Subject: [PATCH 411/567] Revert "fix #458" --- ...es-editor-settings-CustomCodeTemplates.xml | 208 ------------------ 1 file changed, 208 deletions(-) delete mode 100644 assets/org-netbeans-modules-editor-settings-CustomCodeTemplates.xml diff --git a/assets/org-netbeans-modules-editor-settings-CustomCodeTemplates.xml b/assets/org-netbeans-modules-editor-settings-CustomCodeTemplates.xml deleted file mode 100644 index 93f7bfa1..00000000 --- a/assets/org-netbeans-modules-editor-settings-CustomCodeTemplates.xml +++ /dev/null @@ -1,208 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - From 8ffb4a5849bff666f9ff0eb759c0d0bf79522022 Mon Sep 17 00:00:00 2001 From: John Papa Date: Mon, 31 Aug 2015 07:39:24 -0400 Subject: [PATCH 412/567] added angular snippets for js and ts for vscode --- assets/vscode-snippets/javascript.json | 124 +++++++++++++++++++++++++ assets/vscode-snippets/typescript.json | 64 +++++++++++++ 2 files changed, 188 insertions(+) create mode 100644 assets/vscode-snippets/javascript.json create mode 100644 assets/vscode-snippets/typescript.json diff --git a/assets/vscode-snippets/javascript.json b/assets/vscode-snippets/javascript.json new file mode 100644 index 00000000..b0957f61 --- /dev/null +++ b/assets/vscode-snippets/javascript.json @@ -0,0 +1,124 @@ +{ + "Angular Controller": { + "prefix": "ngcontroller", + "body": [ + "(function() {", + "'use strict';", + "", + "\tangular", + "\t\t.module('${Module}')", + "\t\t.controller('${Controller}Controller', ${Controller}Controller);", + "", + "\t${Controller}Controller.$inject = ['${dependency1}'];", + "\tfunction ${Controller}Controller(${dependency1}) {", + "\t\tvar vm = this;", + "\t\t$0", + "", + "\t\tactivate();", + "", + "\t\t////////////////", + "", + "\t\tfunction activate() { }", + "\t}", + "})();" + ], + "description": "Angular 1 controller" + }, + "Angular Service": { + "prefix": "ngservice", + "body": [ + "(function() {", + "'use strict';", + "", + "\tangular", + "\t\t.module('${Module}')", + "\t\t.service('${Service}', ${Service});", + "", + "\t${Service}.$inject = ['${dependency1}'];", + "\tfunction ${Service}(${dependency1}) {", + "\t\tthis.${exposedFn} = ${exposedFn};", + "\t\t$0", + "\t\t////////////////", + "\t\tfunction ${exposedFn}() { }", + "\t}", + "})();" + ], + "description": "Angular 1 service" + }, + "Angular Factory": { + "prefix": "ngfactory", + "body": [ + "(function() {", + "'use strict';", + "", + "\tangular", + "\t\t.module('${Module}')", + "\t\t.factory('${Service}', ${Service});", + "", + "\t${Service}.$inject = ['${dependency1}'];", + "\tfunction ${Service}(${dependency1}) {", + "\t\tvar service = {", + "\t\t\t${exposedFn}:${exposedFn}", + "\t\t};", + "\t\t$0", + "\t\treturn service;", + "", + "\t\t////////////////", + "\t\tfunction ${exposedFn}() { }", + "\t}", + "})();" + ], + "description": "Angular 1 factory" + }, + "Angular Directive": { + "prefix": "ngdirective", + "body": [ + "(function() {", + "\t'use strict';", + "", + "\tangular", + "\t\t.module('${Module}')", + "\t\t.factory('${Directive}', ${Directive});", + "", + "\t${Directive}.$inject = ['${dependency1}'];", + "\tfunction ${Directive}(${dependency1}) {", + "\t\t// Usage:", + "\t\t//", + "\t\t// Creates:", + "\t\t//", + "\t\tvar directive = {", + "\t\t bindToController: true,", + "\t\t controller: ${Controller}Controller,", + "\t\t controllerAs: '${vm}',", + "\t\t link: link,", + "\t\t restrict: 'A',", + "\t\t scope: {", + "\t\t }", + "\t\t};", + "\t\treturn directive;", + "\t\t", + "\t\tfunction link(scope, element, attrs) {", + "\t\t}", + "\t}", + "\t/* @ngInject */", + "\tfunction ${Controller}Controller () {", + "\t\t$0", + "\t}", + "})();" + ], + "description": "Angular 1 directive" + }, + "Angular Module": { + "prefix": "ngmodule", + "body": [ + "(function() {", + "\t'use strict';", + "", + "\tangular.module('${module}', [", + "\t\t$0", + "\t]);", + "})();" + ], + "description": "Angular 1 module" + } +} \ No newline at end of file diff --git a/assets/vscode-snippets/typescript.json b/assets/vscode-snippets/typescript.json new file mode 100644 index 00000000..716dc70e --- /dev/null +++ b/assets/vscode-snippets/typescript.json @@ -0,0 +1,64 @@ +{ + "Angular Controller": { + "prefix": "ngcontroller", + "body": [ + "namespace ${module} {", + "'use strict';", + "", + "export class ${Controller}Controller {", + "\tstatic $inject: Array = ['${dependency1}'];", + "\tconstructor(private ${dependency1}: ${dependency1Type}) {", + "$0", + "}", + "", + "\t${property}: ${propertyType} = ${propertyValue};", + "", + "\t${fn}() { }", + "}", + "", + "angular", + "\t.module('${Module}')", + "\t.controller('${Controller}Controller', ${Controller}Controller);", + "}" + ] + }, + "Angular Service": { + "prefix": "ngservice", + "body": [ + "namespace ${module} {", + "'use strict';", + "", + "export interface I${Service} {", + "\t${serviceFn}: (${dependency1}:${dependency1Type}) => ${returnType};", + "}", + "export class ${Service} implements I${Service} {", + "\tstatic $inject: Array = ['${dependency1}'];", + "\tconstructor(private ${dependency1}: ${dependency1Type}) {", + "", + "}", + "", + "\t${serviceFn}: (${dependency1}:${dependency1Type}) => ${returnType} = (${dependency1}:${dependency1Type}) => {", + "\t\t$0", + "\t}", + "", + "}", + "", + "angular", + "\t.module('${Module}')", + "\t.service('${Service}', ${Service});", + "}" + ] + }, + "Angular Module": { + "prefix": "ngmodule", + "body": [ + "namespace ${module} {", + "\t'use strict';", + "", + "\tangular.module('${module}', [", + "\t$0", + "\t]);", + "}" + ] + } +} \ No newline at end of file From 28d01f88b4ba9514c47ea024fbe304ecaaf8af8b Mon Sep 17 00:00:00 2001 From: John Papa Date: Mon, 31 Aug 2015 07:42:55 -0400 Subject: [PATCH 413/567] added link to vscode snips --- README.md | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/README.md b/README.md index 1b48be9d..3596dedb 100644 --- a/README.md +++ b/README.md @@ -2988,7 +2988,22 @@ Use file templates or snippets to help follow consistent styles and patterns. He ngservice // creates an Angular service ngfilter // creates an Angular filter ``` +### vim + +###### [Style [Y256](#style-y256)] + + - [Visual Studio Code](http://code.visualstudio.com) snippets that follow these styles and guidelines. + - Download the [VS Code Angular snippets](assets/vscode-snippets/javascript.json?raw=true) + - copy snippets to snippet directory, or alternatively copy and paste the snippets into your existing ones + + ```javascript + ngcontroller // creates an Angular controller + ngdirective // creates an Angular directive + ngfactory // creates an Angular factory + ngmodule // creates an Angular module + ngservice // creates an Angular service + ``` **[Back to top](#table-of-contents)** From 97ae8cec6c41d8f3a9c4f28e9ae353aa78f9c51c Mon Sep 17 00:00:00 2001 From: John Papa Date: Mon, 31 Aug 2015 07:43:36 -0400 Subject: [PATCH 414/567] added link to vscode snips --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 3596dedb..31ea00d2 100644 --- a/README.md +++ b/README.md @@ -2988,7 +2988,7 @@ Use file templates or snippets to help follow consistent styles and patterns. He ngservice // creates an Angular service ngfilter // creates an Angular filter ``` -### vim +### Visual Studio Code ###### [Style [Y256](#style-y256)] From d2fc75468c042b59ac32d35ef44ca05e8967aa16 Mon Sep 17 00:00:00 2001 From: John Papa Date: Mon, 31 Aug 2015 07:44:53 -0400 Subject: [PATCH 415/567] added link to vscode snips --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 31ea00d2..eb166a02 100644 --- a/README.md +++ b/README.md @@ -2988,6 +2988,7 @@ Use file templates or snippets to help follow consistent styles and patterns. He ngservice // creates an Angular service ngfilter // creates an Angular filter ``` + ### Visual Studio Code ###### [Style [Y256](#style-y256)] From 9489a238b0d1f5de7904fbc5fd56c27591b36eda Mon Sep 17 00:00:00 2001 From: John Papa Date: Tue, 1 Sep 2015 08:32:37 -0400 Subject: [PATCH 416/567] directive for vs code snippets --- assets/vscode-snippets/javascript.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets/vscode-snippets/javascript.json b/assets/vscode-snippets/javascript.json index b0957f61..0b1920ad 100644 --- a/assets/vscode-snippets/javascript.json +++ b/assets/vscode-snippets/javascript.json @@ -78,7 +78,7 @@ "", "\tangular", "\t\t.module('${Module}')", - "\t\t.factory('${Directive}', ${Directive});", + "\t\t.directive('${Directive}', ${Directive});", "", "\t${Directive}.$inject = ['${dependency1}'];", "\tfunction ${Directive}(${dependency1}) {", From 9bbd7b625e20af312c5394f39a17760cd8ab8dbb Mon Sep 17 00:00:00 2001 From: Angelo Chiello Date: Thu, 10 Sep 2015 08:39:24 +0200 Subject: [PATCH 417/567] [it-IT] PR #510 Updated as PR #510 --- i18n/it-IT.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/i18n/it-IT.md b/i18n/it-IT.md index a48e0f29..915de520 100644 --- a/i18n/it-IT.md +++ b/i18n/it-IT.md @@ -2016,7 +2016,7 @@ Invece usa la più semplice sintassi setter. function creditService() { } - // credit.service.js + // customer.service.js angular .module .service('customersService', customersService); From 57fb9ca6ed73ca81569fa14a57dace96df21d52a Mon Sep 17 00:00:00 2001 From: Angelo Chiello Date: Thu, 10 Sep 2015 08:43:32 +0200 Subject: [PATCH 418/567] [it-IT] PRs: #515, #516, #517 Updated as PRs: #515, #516, #517 --- i18n/it-IT.md | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/i18n/it-IT.md b/i18n/it-IT.md index 915de520..4730777b 100644 --- a/i18n/it-IT.md +++ b/i18n/it-IT.md @@ -2981,6 +2981,24 @@ Usa file template o snippet che ti aiutino a seguire stili e schemi consistentem ngservice // crea un service Angular ngfilter // crea un filter Angular ``` + +### Visual Studio Code + +###### [Stile [Y256](#stile-y256)] + + - Snippet [Visual Studio Code](http://code.visualstudio.com) che seguono questi stili e linee guida. + + - Scarica gli [snippet VS Code Angular](assets/vscode-snippets/javascript.json?raw=true) + - copia gli snippet nella directory snippet o, in alternativa, copia ed incolla gli snippet in quella esistente. + + ```javascript + ngcontroller // crea un controller Angular + ngdirective // crea una directive Angular + ngfactory // crea una factory Angular + ngmodule // crea un modulo Angular + ngservice // crea un service Angular + ``` + **[Torna all'inizio](#tavola-dei-contenuti)** ## Generatore Yeoman From 9f48188c2b904356615e79c8d3f5103220f7bf26 Mon Sep 17 00:00:00 2001 From: Melissa Austin Date: Wed, 23 Sep 2015 14:28:14 -0700 Subject: [PATCH 419/567] PR for issue #529 - Replace/Add WebStorm live templates, i.e., controller, directive, factory, filter, module, service - Replace .jar file with native .xml format - Enhance original template with default values - Update README WebStorm Style Y252 --- README.md | 18 +- ...ebstorm-angular-file-template.settings.jar | Bin 3862 -> 0 bytes ...gular.controller.webstorm-live-template.js | 25 +++ ...ngular.directive.webstorm-live-template.js | 28 +++ .../angular.factory.webstorm-live-template.js | 24 +++ .../angular.filter.webstorm-live-template.js | 18 ++ .../angular.module.webstorm-live-template.js | 9 + .../angular.service.webstorm-live-template.js | 21 ++ .../webstorm-angular-live-templates.xml | 184 ++++++++++++++++++ 9 files changed, 319 insertions(+), 8 deletions(-) delete mode 100644 assets/webstorm-angular-file-template.settings.jar create mode 100644 assets/webstorm-angular-live-templates/angular.controller.webstorm-live-template.js create mode 100644 assets/webstorm-angular-live-templates/angular.directive.webstorm-live-template.js create mode 100644 assets/webstorm-angular-live-templates/angular.factory.webstorm-live-template.js create mode 100644 assets/webstorm-angular-live-templates/angular.filter.webstorm-live-template.js create mode 100644 assets/webstorm-angular-live-templates/angular.module.webstorm-live-template.js create mode 100644 assets/webstorm-angular-live-templates/angular.service.webstorm-live-template.js create mode 100644 assets/webstorm-angular-live-templates/webstorm-angular-live-templates.xml diff --git a/README.md b/README.md index eb166a02..8b321ad4 100644 --- a/README.md +++ b/README.md @@ -2896,18 +2896,20 @@ Use file templates or snippets to help follow consistent styles and patterns. He ### WebStorm ###### [Style [Y252](#style-y252)] - - Angular snippets and file templates that follow these styles and guidelines. You can import them into your WebStorm settings: + - Angular live templates that follow these styles and guidelines. - - Download the [WebStorm Angular file templates and snippets](assets/webstorm-angular-file-template.settings.jar?raw=true) - - Open WebStorm and go to the `File` menu - - Choose the `Import Settings` menu option - - Select the file and click `OK` + - Download the [webstorm-angular-live-templates.xml](assets/webstorm-angular-live-templates.xml?raw=true) + - Place it in your [templates folder](https://www.jetbrains.com/webstorm/help/project-and-ide-settings.html) + - Restart WebStorm - In a JavaScript file type these commands followed by a `TAB`: ```javascript - ng-c // creates an Angular controller - ng-f // creates an Angular factory - ng-m // creates an Angular module + ngcontroller // creates an Angular controller + ngdirective // creates an Angular directive + ngfactory // creates an Angular factory + ngmodule // creates an Angular module + ngservice // creates an Angular service + ngfilter // creates an Angular filter ``` ### Atom diff --git a/assets/webstorm-angular-file-template.settings.jar b/assets/webstorm-angular-file-template.settings.jar deleted file mode 100644 index 38763068aad28f3bcc300c681c715fe2e09516a7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3862 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 + + + + + + + \ No newline at end of file From e9238b9d0c3f16851e519f6ddbb42795fda102e4 Mon Sep 17 00:00:00 2001 From: Melissa Austin Date: Wed, 23 Sep 2015 14:45:12 -0700 Subject: [PATCH 420/567] Correct link to .xml file --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 8b321ad4..b6ca3a63 100644 --- a/README.md +++ b/README.md @@ -2898,7 +2898,7 @@ Use file templates or snippets to help follow consistent styles and patterns. He - Angular live templates that follow these styles and guidelines. - - Download the [webstorm-angular-live-templates.xml](assets/webstorm-angular-live-templates.xml?raw=true) + - Download the [webstorm-angular-live-templates.xml](assets/webstorm-angular-live-templates/webstorm-angular-live-templates.xml?raw=true) - Place it in your [templates folder](https://www.jetbrains.com/webstorm/help/project-and-ide-settings.html) - Restart WebStorm - In a JavaScript file type these commands followed by a `TAB`: From e05726ec06c6d050b42e83463a026c1ce1008bc3 Mon Sep 17 00:00:00 2001 From: Melissa Austin Date: Wed, 23 Sep 2015 15:23:23 -0700 Subject: [PATCH 421/567] Replace .js with .xml to allow optional download of individual templates --- ...gular.controller.webstorm-live-template.js | 25 -------------- ...ular.controller.webstorm-live-template.xml | 32 ++++++++++++++++++ ...ngular.directive.webstorm-live-template.js | 28 ---------------- ...gular.directive.webstorm-live-template.xml | 33 +++++++++++++++++++ .../angular.factory.webstorm-live-template.js | 24 -------------- ...angular.factory.webstorm-live-template.xml | 33 +++++++++++++++++++ .../angular.filter.webstorm-live-template.js | 18 ---------- .../angular.filter.webstorm-live-template.xml | 32 ++++++++++++++++++ .../angular.module.webstorm-live-template.js | 9 ----- .../angular.module.webstorm-live-template.xml | 31 +++++++++++++++++ .../angular.service.webstorm-live-template.js | 21 ------------ ...angular.service.webstorm-live-template.xml | 33 +++++++++++++++++++ 12 files changed, 194 insertions(+), 125 deletions(-) delete mode 100644 assets/webstorm-angular-live-templates/angular.controller.webstorm-live-template.js create mode 100644 assets/webstorm-angular-live-templates/angular.controller.webstorm-live-template.xml delete mode 100644 assets/webstorm-angular-live-templates/angular.directive.webstorm-live-template.js create mode 100644 assets/webstorm-angular-live-templates/angular.directive.webstorm-live-template.xml delete mode 100644 assets/webstorm-angular-live-templates/angular.factory.webstorm-live-template.js create mode 100644 assets/webstorm-angular-live-templates/angular.factory.webstorm-live-template.xml delete mode 100644 assets/webstorm-angular-live-templates/angular.filter.webstorm-live-template.js create mode 100644 assets/webstorm-angular-live-templates/angular.filter.webstorm-live-template.xml delete mode 100644 assets/webstorm-angular-live-templates/angular.module.webstorm-live-template.js create mode 100644 assets/webstorm-angular-live-templates/angular.module.webstorm-live-template.xml delete mode 100644 assets/webstorm-angular-live-templates/angular.service.webstorm-live-template.js create mode 100644 assets/webstorm-angular-live-templates/angular.service.webstorm-live-template.xml diff --git a/assets/webstorm-angular-live-templates/angular.controller.webstorm-live-template.js b/assets/webstorm-angular-live-templates/angular.controller.webstorm-live-template.js deleted file mode 100644 index 9e74834b..00000000 --- a/assets/webstorm-angular-live-templates/angular.controller.webstorm-live-template.js +++ /dev/null @@ -1,25 +0,0 @@ -(function() { - 'use strict'; - - angular - .module('$moduleName$') - .controller('$ControllerName$', $ControllerName$); - - $ControllerName$.$inject = ['$dependency$']; - - /* @ngInject */ - function $ControllerName$($dependency$) { - var vm = this; - vm.title = '$ControllerName$'; - - activate(); - - //////////////// - - function activate() { - $END$ - } - } - -})(); - diff --git a/assets/webstorm-angular-live-templates/angular.controller.webstorm-live-template.xml b/assets/webstorm-angular-live-templates/angular.controller.webstorm-live-template.xml new file mode 100644 index 00000000..15b80cc0 --- /dev/null +++ b/assets/webstorm-angular-live-templates/angular.controller.webstorm-live-template.xml @@ -0,0 +1,32 @@ + + + \ No newline at end of file diff --git a/assets/webstorm-angular-live-templates/angular.directive.webstorm-live-template.js b/assets/webstorm-angular-live-templates/angular.directive.webstorm-live-template.js deleted file mode 100644 index 22d9e0be..00000000 --- a/assets/webstorm-angular-live-templates/angular.directive.webstorm-live-template.js +++ /dev/null @@ -1,28 +0,0 @@ -(function() { - 'use strict'; - - angular - .module('$moduleName$') - .directive('$directiveName$', $directiveName$); - - $directiveName$.$inject = ['$dependency$']; - - /* @ngInject */ - function $directiveName$ ($dependency$) { - var directive = { - bindToController: true, - controller: $ControllerName$, - controllerAs: 'vm', - link: link, - restrict: 'A', - scope: { - } - }; - return directive; - - function link(scope, element, attrs) { - $END$ - } - } - -})(); diff --git a/assets/webstorm-angular-live-templates/angular.directive.webstorm-live-template.xml b/assets/webstorm-angular-live-templates/angular.directive.webstorm-live-template.xml new file mode 100644 index 00000000..6ca95b29 --- /dev/null +++ b/assets/webstorm-angular-live-templates/angular.directive.webstorm-live-template.xml @@ -0,0 +1,33 @@ + + + \ No newline at end of file diff --git a/assets/webstorm-angular-live-templates/angular.factory.webstorm-live-template.js b/assets/webstorm-angular-live-templates/angular.factory.webstorm-live-template.js deleted file mode 100644 index 8c3c934a..00000000 --- a/assets/webstorm-angular-live-templates/angular.factory.webstorm-live-template.js +++ /dev/null @@ -1,24 +0,0 @@ -(function() { - 'use strict'; - - angular - .module('$moduleName$') - .factory('$factoryName$', $factoryName$); - - $factoryName$.$inject = ['$dependency$']; - - /* @ngInject */ - function $factoryName$($dependency$) { - var service = { - $functionName$: $functionName$ - }; - return service; - - //////////////// - - function $functionName$() { - $END$ - } - } - -})(); diff --git a/assets/webstorm-angular-live-templates/angular.factory.webstorm-live-template.xml b/assets/webstorm-angular-live-templates/angular.factory.webstorm-live-template.xml new file mode 100644 index 00000000..ac5e6e23 --- /dev/null +++ b/assets/webstorm-angular-live-templates/angular.factory.webstorm-live-template.xml @@ -0,0 +1,33 @@ + + + \ No newline at end of file diff --git a/assets/webstorm-angular-live-templates/angular.filter.webstorm-live-template.js b/assets/webstorm-angular-live-templates/angular.filter.webstorm-live-template.js deleted file mode 100644 index 6a6f3fe4..00000000 --- a/assets/webstorm-angular-live-templates/angular.filter.webstorm-live-template.js +++ /dev/null @@ -1,18 +0,0 @@ -(function() { - 'use strict'; - - angular - .module('$moduleName$') - .filter('$filterName$', $filterName$); - - function $filterName$() { - return $filterName$Filter; - - //////////////// - - function $filterName$Filter($parameters$) { - return $parameters$; - } $END$ - } - -})(); diff --git a/assets/webstorm-angular-live-templates/angular.filter.webstorm-live-template.xml b/assets/webstorm-angular-live-templates/angular.filter.webstorm-live-template.xml new file mode 100644 index 00000000..b3f7cfc9 --- /dev/null +++ b/assets/webstorm-angular-live-templates/angular.filter.webstorm-live-template.xml @@ -0,0 +1,32 @@ + + + \ No newline at end of file diff --git a/assets/webstorm-angular-live-templates/angular.module.webstorm-live-template.js b/assets/webstorm-angular-live-templates/angular.module.webstorm-live-template.js deleted file mode 100644 index 3224bfdc..00000000 --- a/assets/webstorm-angular-live-templates/angular.module.webstorm-live-template.js +++ /dev/null @@ -1,9 +0,0 @@ -(function() { - 'use strict'; - - angular - .module('$moduleName$', [ - '$dependency$' - ]); $END$ - -})(); diff --git a/assets/webstorm-angular-live-templates/angular.module.webstorm-live-template.xml b/assets/webstorm-angular-live-templates/angular.module.webstorm-live-template.xml new file mode 100644 index 00000000..c578b788 --- /dev/null +++ b/assets/webstorm-angular-live-templates/angular.module.webstorm-live-template.xml @@ -0,0 +1,31 @@ + + + \ No newline at end of file diff --git a/assets/webstorm-angular-live-templates/angular.service.webstorm-live-template.js b/assets/webstorm-angular-live-templates/angular.service.webstorm-live-template.js deleted file mode 100644 index 7349a433..00000000 --- a/assets/webstorm-angular-live-templates/angular.service.webstorm-live-template.js +++ /dev/null @@ -1,21 +0,0 @@ -(function() { - 'use strict'; - - angular - .module('$moduleName$') - .service('$ServiceName$', $ServiceName$); - - $ServiceName$.$inject = ['$dependency$']; - - /* @ngInject */ - function $ServiceName$($dependency$) { - this.$functionName$ = $functionName$; - - //////////////// - - function $functionName$() { - $END$ - } - } - -})(); diff --git a/assets/webstorm-angular-live-templates/angular.service.webstorm-live-template.xml b/assets/webstorm-angular-live-templates/angular.service.webstorm-live-template.xml new file mode 100644 index 00000000..e48258cd --- /dev/null +++ b/assets/webstorm-angular-live-templates/angular.service.webstorm-live-template.xml @@ -0,0 +1,33 @@ + + + \ No newline at end of file From 2eebc5bed09882e0ba259a016373865ac3f5b416 Mon Sep 17 00:00:00 2001 From: Melissa Austin Date: Wed, 23 Sep 2015 15:39:34 -0700 Subject: [PATCH 422/567] Update README to include link to individual templates --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index b6ca3a63..7527b627 100644 --- a/README.md +++ b/README.md @@ -2911,6 +2911,8 @@ Use file templates or snippets to help follow consistent styles and patterns. He ngservice // creates an Angular service ngfilter // creates an Angular filter ``` + + *Individual templates are also available for download within the [webstorm-angular-live-templates](assets/webstorm-angular-live-templates?raw=true) folder* ### Atom ###### [Style [Y253](#style-y253)] From 979c55a6477ef073abd0b7ab2b29e9184a1ccf7d Mon Sep 17 00:00:00 2001 From: Melissa Austin Date: Wed, 23 Sep 2015 15:54:10 -0700 Subject: [PATCH 423/567] Update templateSet to individual group name --- .../angular.controller.webstorm-live-template.xml | 2 +- .../angular.directive.webstorm-live-template.xml | 2 +- .../angular.factory.webstorm-live-template.xml | 2 +- .../angular.filter.webstorm-live-template.xml | 2 +- .../angular.module.webstorm-live-template.xml | 2 +- .../angular.service.webstorm-live-template.xml | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/assets/webstorm-angular-live-templates/angular.controller.webstorm-live-template.xml b/assets/webstorm-angular-live-templates/angular.controller.webstorm-live-template.xml index 15b80cc0..ec548a54 100644 --- a/assets/webstorm-angular-live-templates/angular.controller.webstorm-live-template.xml +++ b/assets/webstorm-angular-live-templates/angular.controller.webstorm-live-template.xml @@ -1,4 +1,4 @@ - +