Shared posts

29 Jul 07:08

Phalcon PHP – Higher Performance Web Framework

by Ray Cheung
Benjamin

Will have to test it

Advertise here via BSA

Phalcon PHP is a web framework delivered as a C extension providing high performance and lower resource consumption. Phalcon PHP is written in C with platform independence in mind. As a result, Phalcon PHP is available on Microsoft Windows, GNU/Linux, Mac OS X, You can either download a binary package for the system of your choice or build it from sources.

You don’t need learn or use the C language, since the functionality is exposed as PHP classes ready for you to use. Phalcon also is loosely coupled, allowing you to use its objects as glue components based on the needs of your application. Phalcon is not only about performance, it is pretty robust, rich in features and easy to use. Phalcon is open-sourced software licensed under the New BSD License.

phalcon

Requirements: PHP 5.x and GCC compiler
Demo: http://phalconphp.com/
License: New BSD License

Sponsors

Professional Web Icons for Your Websites and Applications

22 Jul 09:09

Learn Ember With Us for Free

by Jeffrey Way

Hopefully, it’s clear by now that Envato and Tuts+ are dedicated to education. In addition to the various Tuts+ sites like this one, we also offer Tuts+ Premium, which provides the best web development courses and ebooks available today for a small monthly cost. Members of Premium help to contribute back to Tuts+ and ensure that we can continue offering as much free content as possible.

Speaking of free: each month, we release one new entirely free course. This month, I’m proud to announce that you can learn Ember with us for free!

Let's Learn Ember
Bookmark Me!

Lessons

Introduction

The Object Model

Application Components

Demonstration

Conclusion


There Will Always Be More!

Be sure to bookmark freecourses.tutsplus.com (and subscribe to the newsletter) to stay updated on each new free course that we offer to the community!

If you’d like to learn more, of course a Tuts+ Premium membership is only $19 a month, and includes countless courses and downloadable eBooks on the topics that I guarantee you’re most interested in learning: HTML5, jQuery, Ember, Laravel, PHP 5.5, Rails 4, architecture, design patterns, and so much more.

19 Jul 07:34

Télétravail en 2013 – Outils et bonnes pratiques

by Nadia Bellifa

Où en est le télétravail en France ?

Le télétravail a le vent en poupe et les télétravailleurs en sont satisfaits ! Plus de stress dans les transports, meilleure gestion de la vie privée, productivité améliorée, réduction des budgets des locaux et de l’énergie… Pour l’entreprise comme pour le salarié, le télétravail, c’est la santé !

En France, selon une étude de LBMG Worklabs, près de 16,7% de la population travaillent à distance, dont 79% de leur domicile et 8% dans des espaces de coworking. Le nombre réel de télétravailleur provenant du secteur privé et public serait de 14,2%, le reste étant des indépendants qui ne sont pas considérés comme des télétravailleurs puisque non-salariés.

Si de nombreux dirigeants doutent de leurs collaborateurs avant de les passer en mode télétravail (78%), une grande majorité est satisfaite après l’avoir mis en place. Les entreprises constatent que l’absentéisme diminue de 20%. De plus, elles réalisent énormément d’économies sur la surface des locaux loués pour l’activité. Autant dire que tout le monde y trouve son compte. D’ailleurs, selon un sondage de l’institut OpinionWay, le télétravail intéresserait 76% des salariés demeurant en Île-de-France. Étant donné l’amplitude du trafic en heure de pointe, on ne peut que comprendre ce souhait massif des Franciliens !

D’après ces nouveaux chiffres, la France, qui jusque-là paraissait réticente au télétravail, semble donc engagée dans la voie du travail à distance. Ce qui ne sera certainement pas pour déplaire aux futurs télétravailleurs qui pourront exercés leur métier dans la région de leur choix.

 

Liste d’outils du télétravailleur en 2013

Webdesigner, développeur, rédacteur, traducteur, marqueteur… entrepreneur, freelance ou bien salarié, nous avons tous besoin de retrouver confort et ergonomie de travail à notre domicile ou en mobilité.

Voici donc une petite sélection d’outils qui, selon nous, méritent d’être essayés.

 

Outils de communication

Skype : Leader de la voix IP, Skype reste l’outil le plus fiable. Le hic est qu’à plusieurs personnes en visioconférence il devient payant. Pour utiliser Skype gratuitement en visioconférence mieux vaut préférer les duos.

Google Hangouts : le nouvel outil de visioconférence de Gmail est plutôt réussi, évidemment, pour y avoir accès, il faut d’abord créer un compte Google. Les visioconférences sont accessibles gratuitement jusqu’à 10 personnes. Hangout permet d’intégrer les documents collaboratifs de Google Drive ainsi que d’autres applications. Un onglet développeur invite à développer des applications via l’API Hangouts. Petit bémol sur le partage d’écran qui tarde à s’améliorer.

Adobe Connect : solution de webconférence sous licence ou par abonnement. Cet outil permet de rassembler une grande audience et de pouvoir partager son écran. Le son est cependant parfois médiocre et quelques décalages dans le temps entravent la fluidité de la diffusion. Une webconférence demande aussi un petit support technique pour faciliter la prise en main de l’outil et le déroulement de la conférence.

Les réseaux sociaux d’entreprise (RSE) pour retrouver un espace d’échange, de convivialité, mais aussi de travail entre collaborateurs : Chatter, Yammer, Jamespot, …

La version entreprise de Google + place désormais la firme dans le créneau des RSE. Le cerclage, l’administration des pages par plusieurs collaborateurs, la convergence des services Google Drive, Google Hangouts, Gmail… ainsi que le nouvel impact des résultats sociaux dans le référencement du moteur de recherche jouent fortement sur la croissance du réseau.

 

Outils collaboratifs

La palette d’outils Drive de Google App est parmi les favoris et se démarque comme un indispensable pour le travail collaboratif. Tous les logiciels office sont en ligne avec parfois, il est vrai, un manque de performance comparé au pack office de Microsoft, notamment pour l’outil de présentation et le tableur. Autre faiblesse, lorsque plusieurs collaborateurs travaillent sur le même drive, l’arborescence peut vite devenir complexe et il est parfois difficile de retrouver un fichier. L’insertion des bons mots clés dans le champ de recherche permet toutefois de retrouver les documents. L’outil manque aussi cruellement d’un correcteur d’orthographe et les déconnexions sont parfois sources de ralentissement dans le travail. En cas de longue coupure, la synchronisation sur PC des dossiers favoris permet de parer ce désagrément.

Lighthouse : plate-forme de projets collaboratifs qui permet d’organiser automatiquement des tâches. C’est un outil efficace avec une petite faiblesse au niveau de l’interface qui est un peu lourde.

Evernote : avec ce logiciel, plus de post-it et de notes collées partout ! Evernote permet un rangement en arborescence, ainsi que le partage avec plusieurs utilisateurs. Installé sur PC, les notes sont consultables en ligne depuis n’importe quel ordinateur avec une connexion internet et vite accessibles avec le module de recherche.

Basecamp : outil de gestion de projets en ligne. Il permet un suivi des tâches à effectuer pour chacun des collaborateurs et de stocker les fichiers relatifs au projet.

FeatureMap : solution SaaS pour la gestion de projets de manière collaborative. Il permet d’avoir une vue globale sur les projets et facilite l’organisation.

Azendoo : plate-forme collaborative pour la gestion de projet qui intègre divers outils pour fluidifier le travail collaboratif (Evernote, Google Drive, Dropbox, Box).

Dropbox et Box : solution de stockage en ligne qui permet de synchroniser et partager des fichiers avec d’autres collaborateurs sur divers terminaux (PC, iPhone, Android, etc).

Tonido : cette solution permet de créer un espace de travail collaboratif sur un Cloud personnel. Cet espace sécurisé ne se trouve pas sur un divers distant, pour pouvoir y accéder il faut que l’ordinateur soit allumé.

 

Télétravail – les bonnes pratiques en 2013

De la rigueur
La meilleure attitude pour réussir dans un poste en télétravail est de s’imposer une rigueur de vie et de dresser un mur entre vie privée et vie professionnelle.

Un lieu de travail unique
Déterminez un lieu de travail (une pièce, un bureau) isolé et exclusif. Pour rester performant dans son métier et disponible pour sa famille, mieux vaut ne pas mélanger vos pièces de vie à votre travail.

Du matériel fiable et confortable
Cela parait peut-être absurde de le préciser, cependant la fiabilité du matériel est primordiale. Suivant l’organisation décidée par l’entreprise, le télétravailleur accède à ces fichiers professionnels soit par un serveur privé, soit par un serveur distant. Dans tous les cas, une bonne connexion internet, un ordinateur avec une performance adaptée aux tâches principales du métier, deux écrans, et un bon fauteuil sont le minimum pour travailler dans de bonnes conditions.

Une activité extérieure
Travailler chez soi a aussi ses inconvénients, et les premiers qui apparaissent très vite sont le manque d’exercice physique et le sentiment d’isolement pour certains.  S’abonner à une salle de sport ou une autre activité est recommandé pour rester en forme et garder un bon mental.

Ces recommandations, et la liste d’outils qui précède, méritent certainement d’être complétées, si vous avez d’autres outils ou d’autres conseils en tête, libre à vous de les partager !

 


Sources


12 Jul 06:49

Nokia Lumia 1020 : 41MP et plein de possibilités

by Lâm
Benjamin

test partage

Très attendu des fans de photophonie, Nokia vient de dévoiler son smartphone Lumia 1020, un haut de gamme très, très costaud côté photo et vidéo. On vous fait le tour du proprio !

…………………………

- Le Pitch :

Depuis son introduction début 2012, la technologie Pureview a autant fait rire qu’elle a ensuite impressionné. On parle bien sûr de ce fameux capteur 41MP (oui, 41) capable de produire des images finales de 5MP extrêmement propres, même pour un appareil compact traditionnel. Problème, Pureview était implémenté dans un appareil sous Symbian.

Tout le monde attendait donc que Nokia livre sa technologie avec un OS autrement plus moderne, comme le Windows Phone 8 auquel le géant finlandais s’est associé depuis… Elle a donc esquivé les Lumia 800, 900, 920, 720 et 928 pour finalement revenir dans le nouveau Lumia 1020, tout juste officialisé.

Dans ce smartphone au design désormais reconnaissable, Nokia a ainsi intégré une nouvelle version de son capteur :

  • ce dernier “pèse” toujours 41MP, pour une résolution maximale de 7712 x 5360 pixels…
  • … Mais se retrouve avec une technologie CMOS rétro-éclairée, pour améliorer les performances en basse lumière, l’un des talons d’Achille des photophones.
  • Ce capteur offre différents modes :38MP en 4:3, 34MP en 16:9, 5MP en oversampling (7 pixels en forment 1)
  • La taille s’étend sur 1/1,5 pouce, un poil plus petit que le capteur du 808, avec donc des photosites 1,1 µm, contre 1,4 µm auparavant.

photos : The Verge

Différents outils accompagnent et enrichissent ensuite cette base :

  • La stabilisation optique est toujours de la partie, en photo comme en vidéo. Elle est annoncé encore plus performante que celle utilisée sur les Lumias 9xx, avec notamment un nouveau système de roulements à bille.
  • Le flash Xenon du 928, très puissant, est ici de retour et se transforme en torche LED continue pour la vidéo.
  • L’optique, estampillée Zeiss, contient 6 verres, apparemment équivalent à un 24mm f/2.2
  • Un grip optionnel servira de protection, de batterie supplémentaire et de déclencheur hardware et de support trepied

Côté software, Nokia a également mis les bouchées doubles :

  • Le zoom software profite évidemment de la résolution, pour zoomer en vidéo sans perte de qualité d’image, ou zoomer en photo, puis pouvoir même dézoomer plus tard.
  • L’app “Pro Camera” permet tous les réglages manuels d’un appareil photo classique (vitesse, ouverture, ISOs, balance des blancs…)
  • Nokia fourni dès aujourd’hui un kit de développement orienté Imagerie pour les développeurs, donnant accès à plus de features avancées que l’API Windows Phone de base.
  • Flipboard, Path sont annoncé pour Windows Phone, de même qu’une app d’Hipstamatic exclusive au 1020, pouvant uploader vers Instagram

Le Nokia 1020 sera disponible cet Eté, à un tarif encore non communiqué (299$ avec abonnement 2 ans aux Etats-Unis)

…………………………

- A retenir :

  • Capteur 41MP avec divers modes
  • Flash Xenon, Stabilisation optique
  • Zoom software
  • Contrôles manuels

…………………………

- Nos premiers avis :

On attendait Nokia au tournant, force est de constater que le 1020 ne déçoit pas et ne surprend pas non plus. On espérait ainsi un smartphone évolué qui fait avancer le genre, on l’a : entre toutes ses features avancées (réglages manuels, stabilisation, flash Xenon/LED…) et son capteur unique, le 1020 impressionne. Restent deux points d’interrogation.

La prise en main, tout d’abord. Les Lumias ne sont pas réputés pour être des petites créatures, entre leur épaisseur conséquente et leur poids qui en a calmé plus d’un. Si le 1020 est annoncé comme 30 grammes plus léger que le 920 et un poil plus petit, il faudra le prendre pour en juger en réalité, sans oublier l’excroissance au dos de l’appareil, dédiée à la partie photo, qui rajoute de l’épaisseur. En attendant, gardons bien ses mensurations en tête : 130.4 x 71.4 x 10.4 mm pour 158 grammes.

photo : The Verge

L’autre interrogation est plus cruciale, puisqu’elle concerne le principal point faible de Windows Phone 8 : le manque d’applications. On pense bien sûr à Instagram, mais aussi à des dizaines d’apps comme Vine, SnapSeed, Diptic, Layover, VSCO Cam etc. Aussi puissant soit-il sur le papier, le Lumia 1020 reste un photophone. Et la raison d’être des Photophones reste de retoucher et de partager.

On saluera l’effort de Nokia et Microsoft pour offrir un environnement aussi complet et suffisant que possible. L’app “Pro Camera” semble très convaincante, de même que sa soeur “Smart Camera”. On notera enfin “l’astuce” pour accéder à Instagram, LE grand absent du programme : une app de l’editeur Hipstamatic, permettant de partager des photos sur Instagram (sans pouvoir y accéder directement). Ca sent la rustine, mais on prendra pour le moment…

photo : The Verge

En attendant la réponse de la concurrence (beaucoup de rumeurs tournent autour de Sony et bien sûr d’Apple), vous pouvez regarder à la loupe ces premières officielles prises avec ce Lumia 1020, un smartphone très impressionnant au niveau hardware, encore un peu décevant au niveau software.

 

…………………………

- Tarif et disponibilité du Nokia Lumia 1020 :

Disponible ce trimestre

Coloris : Jaune, Noir ou Blanc

Tarif encore non annoncé

Camera Grip : 69€

…………………………

- Images haute résolution du Nokia Lumia 1020 :

700-1-nokia-lumia-1020-smart-1 700-1-nokia-lumia-1020-smart-2 700-nokia-lumia-1020-cinemagraph-1 700-nokia-lumia-1020-pro-11 700-nokia-lumia-1020-pro-18 700-nokia-lumia-1020-pro-highres-17 700-nokia-lumia-1020-pro-lowlight 700-nokia_lumia_1020_back 700-nokia_lumia_1020_color_range 700-nokia_lumia_1020_color_range-1 700-nokia_lumia_1020_duo 700-nokia_lumia_1020_front DSC_5764-hero_verge_super_wide DSC_5825-hero_verge_super_wide grip LB_7235 LB_7342 lumia1020back Nokia-Lumia-1020-with-Camera-Grip-600x300 nokia_lumia_1020_banniere Picture 2900

 

 

10 Jul 21:33

L’industrialisation du front-end, les frameworks de création d’interfaces CSS JS

by Jean-François Fraisse
Benjamin

Twitter Boootrap c'est si mal ?

Difficile de passer à côté du phénomène Twitter Bootstrap, cet ensemble d’outils CSS JS et UI pour créer des interfaces web-app en moins de deux.
Il doit notamment sa renommée à sa gestion du responsive qui propose deux grilles css dont une entièrement gérée en unités relatives.

C’est un framework de création d’interfaces web avancées tout comme « Zurb Foundation », ou le nouveau framework « Pure ». Il diffère sur ce point de ses cousins les frameworks css « Zen grids », « KNACSS », et autres qui n’embarquent aucun plugin javascript et se concentrent sur la structuration de la vue.

Pour reprendre la phrase d’introduction sur le site de TB « Sleek, intuitive, and powerful front-end framework for faster and easier web developement » qu’on pourrait traduire par « un  kit de composants web html css js (front) puissant, intuitif et élégant, qui va vous faire gagner du temps et vous simplifiera la tâche ».

Sur le papier ça fait rêver, mais est-ce que dans les faits c’est toujours le cas ?

On va essayer de voir jusqu’à quel point cette affirmation tient la route, si il existe des contrindications à l’utilisation de ces outils et quelles sont les alternatives possibles.

I. Le cas de Twitter Bootstrap:

Ahh le framework, c’est un peu le couteau suisse de la conception. Ça aide bien dans certaines situations mais dès qu’on veut passer sur du gros œuvre ou de la précision, soit ça casse soit c’est difficilement maniable car trop lourd.

Bien qu’ayant de grandes qualités Twitter Bootstrap n’échappe pas à ce constat. En effet il a été créé avec des outils et des champs d’applications bien spécifiques.

Et de ces champs d’applications naissent des limites, comment peut-on alors les définir ?

Observons à la loupe la bête alias Twitter Bootstrap V2.2.2.

 

1. La loupe :

Deux feuilles de styles CSS dont une globale (124ko pour 6000 lignes) et l’autre qui gère l’aspect responsive « adaptif » mais sans les composants d’interface utilisateur (22ko pour 1200 lignes).

 

a. La surcharge pondérale CSS chez Twitter Bootstrap

Mr Fat (un des deux principaux créateurs de ce framework) ne dira pas le contraire, même si la mise en forme des formulaires, boutons et autres tableaux est bien gérée chez Twitter Bootstrap ça fait quand même beaucoup de CSS pour tenter de répondre à tout les cas d’usages.

La grille de mise en page CSS dans Twitter Bootstrap c’est :

  • une rangée appelée « row » (layout),
  • des gabarits de tailles différentes appelés « span » et des marges « offset » qui forment la grille CSS.
    Le tout fait à peu près 123 lignes de code CSS non minifié, « et le reste ? » me direz-vous.

Le reste c’est :

  • reset des valeurs CSS sur les éléments HTML (le même que HTML5 boilerplate),
  • édition et titrages (tailles, couleurs, comportement sur les « hover »),
  • style des formulaires, tableaux et boutons,
  • icones,
  • style des plugins js,
  • media queries pour gérer le passage aux petites résolutions

Ajoutez à ça les CSS propres au design du site et les surcharges éventuelles de la CSS de bootstrap…

De plus l’utilisation de sélecteurs avancés CSS3 ordonne des comportements génériques à certains blocks html, exemple :

.row-fluid [class*="span"] {

}

.row-fluid [class*="span"]:first-child {

margin-left: 0;

}

Le tout se transforme en un véritable casse-tête difficilement maintenable.

b. Le même constat en Javascript

On trouve le panel classique des plugins jQuery UI type tooltip, popover  modal, dropdown, carousel et autres interactions et bien sur la librairie jQuery elle même (32ko).

Encore une fois le constat est décevant, ces outils ne sont pas encore optimisés pour une utilisation mobile.

Un comble pour un framework qui se veut « responsive » donc mobile–friendly…

Le plugin « bootstrap-transition.js » n’en permet pas la compatibilité même si

partant d’une bonne intention il permet un fall-back sur les transitions javascript. Mais en choisissant la propriété « transition » à la place de « transform » il n’offre pas à ce fall-back l’accélération matérielle du téléphone et ainsi une animation plus fluide.

De la même façon qu’en CSS il faudra donc procéder au nettoyage des plugins non nécessaires à notre site internet.

 

2. D’autres solutions ?

a. adapter son Twitter Bootstrap

Autour de moi la plupart des cas d’usages pour Twitter Bootstrap concernent la structuration, responsive ou non. En effet les plugins javascript embarqués sont généralement peu utilisés car peu performants et dotés d’effets de transitions plutôt moyens.

Pour nettoyer l’archive des éléments non nécessaires, TB a mis à disposition un outil pour customiser son framework selon les besoins.

Mais cet outil suffit-il à répondre à toutes les situations ?

Le web front étant en perpétuelle évolution que ce soit graphiquement ou structurellement il est bien difficile de prévoir tous les cas de figure et futures optimisations possibles.

 

b. Zurb Foundation, un concurrent mal connu

Le cas de Foundation est intéressant, méconnu il est pourtant supérieur à TB sur certains points.

Alors que TB v1 ne gérait les tailles que par des unités absolues, celui-ci disposait déjà d’une grille CSS en «  responsive fluide ».

Il utilise la propriété CSS3 « box-sizing: border-box; » qui lui permet de contrôler le modèle de fonctionnement CSS des blocks html et ainsi de palier aux comportements récalcitrants des éléments HTML type « textearea » (dépendant du nombre de colonnes pour calculer sa taille).
Son système de grille est à mon sens plus respectueux des équilibres qu’on peut retrouver dans le monde de l’infographie. En effet il n’est pas basé sur le nombre d’éléments affichés mais offre un panel de choix plus large permettant ainsi de répondre à plus de design.

Utilisant un balisage plus « sémantique » que son concurrent, les mises à jours et autres modifications s’en trouvent simplifiées, mais là c’est plus une question de goût.

Son slideshow « Orbit » qui gère l’accélération matérielle est aussi plus adapté aux besoins de performance mobile.

À noter que la version 4 de « Zurb » ne permet plus le support sur ie7 et 8, mais qu’il existe un fix mis à disposition par les développeurs.

Mais bien que paramètrable, cette solution n’est malheureusement pas parfaite non plus.

On va donc essayer de comprendre quels sont les cas d’usages types, les limites et comment appréhender au mieux son projet pour savoir si celui-ci est compatible avec un framework web ou nécessite un travail sur mesure ?

 

II. Les limites des frameworks CSS

 

1. Grille typographique et gestion du contexte web

a. Grille modulaire éclatée et nombre d’or

La structure tabulaire des grilles CSS dans la plupart des frameworks CSS est prévue pour gérer des cas simples, c’est à dire des tailles de cellules calculées en fonction du nombre de conteneurs affichés. Mais que ce passe-t-il lorsque le designer utilise des valeurs tel que le « nombre d’or » ou la suite de Fibonacci pour calculer les tailles de ses blocks ?

C’est le cas bien plus souvent qu’on ne le croit, en effet la conception des grilles et équilibres dans le monde du design échappe à la plupart du commun des mortels, laissant apparaître la magie créative de nos supers DA.

Lorsqu’on veut intégrer une maquette photoshop basée sur une grille un peu plus avancée que celle présente dans un framework CSS, les acrobaties à réaliser pour adapter les gabarits tiennent parfois de la haute voltige !

Et il sera difficile de modifier les grilles CSS via les outils précités en fonction de ces équilibres autrement qu’en les surchargeant.

 

b. la volatilité actuelle du développement front

Les spécifications CSS3  n’étant toujours pas standardisées, les techniques pour gérer certaines problématiques liées au design responsive ne sont donc pas officiellement stables.

Et que dire de la démocratisation d’écrans HD et UHD qui maintenant est aussi à prendre en compte.

La logique webkit actuelle d’implémentation de propriétés CSS orphelines (non supportés par les autres navigateurs) type « -webkit-font-smoothing » n’aide pas non plus à stabiliser les conditions de développement-front.

Sans parler des sites à effets Parallax, et autres performances front avancées comme on peut trouver sur des plateformes type awwwards ou FWA.

 

2. Comment appréhender les besoins CSS pour son projet web

a. Web-app ou plateforme de communication web ?

Selon les besoins, l’utilisation de telle ou telle solution CSS peut-être définie.

En effet pour faire des applications web le frameworks CSS est la solution ! Profitant de gabarits génériques et embarquant des outils js et autres style UI, il constitue la manière la plus rapide de créer un prototype ou une web-app. De plus ses grilles sont adaptées au design générique des formulaires, boutons et autres menus contextuelles ou de navigation.

Mais lorsque le projet web est un peu plus complexe, difficile de se passer d’une stratégie CSS spécifique.

 

b. CSS ce n’est pas si compliqué

Il existe donc des cas où le sur-mesure reste une nécessité, et figurez-vous que ce n’est pas si compliqué !
En effet les unités relatives sont comprises depuis le navigateur Internet explorer 6, le responsive dit « fluide » est donc supporté par les navigateurs depuis de nombreuses années.

Voici un tutoriel rapide pour réaliser sa propre grille responsive CSS (compatibilité internet explorer 7 inclus) :

La démo

Le HTML :

<div class="grid-layout">

<div class="cell-1-3">
</div>
<div class="cell-1-3">
</div>
<div class="cell-1-6">
</div>
<div class="cell-1-6">
</div>

</div>

Notre conteneur se nomme « grid-layout » et les cellules contenues « cell-X-X ».  Ici « X-X » représente la taille en largeur de la grille divisée par le nombre de cellules. Cette indication permettra de savoir quelle taille en % fait la cellule par rapport à son conteneur (ndlr : ceci est ma propre convention de nommage, à vous de choisir celle qui vous convient). Gardez en tête que la taille globale ne doit pas dépasser 100%, ce qui équivaut à  » cell-1-1 « .

La grille CSS :

  • Tout d’abord assurons nous que cette grille saura résister aux comportements flottants dans les cellules (clear: both;),
  • Ensuite on attribue le ou les comportements par défauts pour toutes les cellules ([class*="cell "]{…}),
  • On construit la grille (.cell-1-1, .cell-1-2, etc),
  • Enfin on ajoute la touche « media querie » qui ajustera le layout pour les terminaux dotés de petits écrans (@media (max-width: 620px) {…}).

Et voilà notre grille flexible et responsive, vous n’avez plus qu’à créer ou récupérer vos éléments d’interfaces et les injecter à l’intérieur des cellules de la grille.

So hard ?

09 Jul 07:32

Tutorial : Installer Android 4.2.2 (Jelly Bean) sur votre PC/MAC

by Laure Renouard

Windows, Mac OS, ChromeOS et les autres : les possibilités sont multiples lorsqu’il s’agit de choisir l’OS d’un ordinateur de bureau. Android s’invite dans la cour de récréation, en version Jelly Bean 4.2.2, alors même que Jelly Bean 4.1 avait eu droit au même traitement il y a quelques mois.

Jelly Bean pour PC

Envie de tester Android Jelly Bean 4.2.2 sur votre PC ? L’expérience a surtout du sens si votre machine possède un écran tactile, mais est néanmoins possible sur tout type d’ordinateur. C’est l’équipe de Learn2Crack qui s’est collée à la tâche et nous a concocté un tutoriel pour aider les néophytes à se lancer dans l’aventure.

Pour ce faire, il vous faut télécharger la dernière version du logiciel VirtualBox ainsi qu’Android x86. Nul besoin d’être un geek accompli (quoique…), il suffit de suivre les 10 étapes recensées par Learn2Crack.

  • Installer VirtualBox sur le PC.
  • Ouvrir VirtualBox et sélectionner “New”. Dans la boîte de dialogue qui s’ouvre, tapez le nom que vous souhaitez et choisissez “Type : Linux” puis “Version : Other Linux”, et choisissez Continuer (Next).
  • Choisissez dans la boîte de dialogue suivante la taille de mémoire que vous souhaitez (512 Mo minimum).
  • Dans la boîte de dialogue suivante, choisissez la création d’un disque dur virtuel. Sélectionnez “VDI” puis une localisation fixe ou dynamique, puis créez le disque dur virtuel.
  • Choisissez “Virtual Device” puis réglages, et une boîte de dialogue doit s’ouvrir. Dans celle-ci, choisissez : Storage > Storage Tree > Empty puis dans les section concernées, sélection le dossier iso Android 4.2 que vous avez téléchargé, puis cloquez sur OK.
  • Ouvrez le disque dur virtuel. Choisissez Install Android-x86 sur le disque dur.
  • Sur l’écran suivant, choisissez Create/Modify Partition.
  • Créez une partition “bootable” et choisissez “écrire”. Quittez ensuite.
  • Installez Android dans sda1 et choisissez le type ext3, puis cochez oui à l’installation demandée.
  • Après l’installation, effacez l’iso de VirtualBox et rebootez.

Après l’opération, il est possible de booter sur Android. Qui prendra le temps de tester ?

28 Jun 10:59

Building a Web App From Scratch in AngularJS

by Leon Revill

In a previous AngularJS tutorial I covered all the basics of how to get up and running with Angular in around 30 minutes. This tutorial will expand on what was covered there by creating a simple real world web application.

This simple web application will allow its users to view, search and filter TV Show Premieres for the next 30 days. As a keen series viewer, I am always looking for something new to watch when my favorite shows are off air, so I thought I would create an app to help me find what I am looking for.

Before we get started, you may want to take a look at the demo from above, to see what we will be creating in this tutorial.


Getting Started

To begin, we need a skeleton AngularJS application which already has all the required JavaScript and CSS to create the TV Show Premieres app. Go ahead and download this skeleton from the “download source files” button above.

Once you have downloaded the files you should have a directory structure as shown below:

figure1-skeleton-directory-structure

Looking at the directory structure and the included files you will see that we will be using Twitter Bootstrap to make our web app a little prettier, but this tutorial will not look at Twitter Bootstrap in any detail (learn more about Twitter Bootstrap). Additionally, this tutorial will not be covering how to setup a new AngularJS application as the aforementioned AngularJS tutorial already covers this in detail.

Upon opening index.html, with your browser of choice, you should see a very simple web page with just a title and some basic formatting as seen below:

figure2-basic-web-page

Loading In Our Data

The first thing we are going to need to create our TV Show app, is information about TV shows. We are going to use an API provided by Trakt.tv. Before we can get started you are going to need an API key, you can register for one on their website.

Why use this API? Do I really have to register? We are using this API so our app will use real data and will actually provide some use once completed. Also, by using this API we do not need to go over any server side implementations within this tutorial and can focus completely on AngularJS. An extra couple of minutes to register for the API will be well worth it.

Now that you have your own API key, we can utilize the Trakt API to get some information on TV shows. We are going to use one of the available API calls for this tutorial, more information on this is available in the api docs. This API call will provide us with all the TV Show Premieres within a specified time frame.

Open mainController.js and modify it to match the below code:

    app.controller("mainController", function($scope, $http){

        $scope.apiKey = "[YOUR API KEY HERE]";
        $scope.init = function() {
            //API requires a start date
            var today = new Date();
            //Create the date string and ensure leading zeros if required
            var apiDate = today.getFullYear() + ("0" + (today.getMonth() + 1)).slice(-2) + "" + ("0" + today.getDate()).slice(-2);
            $http.jsonp('http://api.trakt.tv/calendar/premieres.json/' + $scope.apiKey + '/' + apiDate + '/' + 30 + '/?callback=JSON_CALLBACK').success(function(data) {
                console.log(data);
            }).error(function(error) {

            });
        };

    });

If you look within the index.html file, for the following line:

    <div class="container main-frame" ng-app="TVPremieresApp" ng-controller="mainController" ng-init="init()">

You will see that the ng-init method is calling the init function, this means that the init() function within our mainController will be called after the page has been loaded.

If you read the API documentation for the calendar/premieres method you will have seen that it takes three parameters, your API key, the start date (e.g. 20130616) and the number of days.

To provide all three parameters, we first need to get today’s date using JavaScripts Date() method and format it to the API specified date format to create the apiDate string. Now that we have everything we need, we can create an $http.jsonp call to the API method. This will allow our web app to call a URL that is not within our own domain and receive some JSON data. Ensure that ?callback=JSON_CALLBACK is prepended onto the request URI so that our attached .success callback function is called on response.

Within our .success function we then simply output the received data to the console. Open index.html within your browser and open the JavaScript console, you should see something like the following:

figure3-javascript-console

This demonstrates that we are successfully performing a call to the Trakt API, authenticating with our API key and receiving some JSON data. Now that we have our TV show data, we can move on to the step.


Displaying Our Data

Processing the JSON Objects

Before we can display our data, we need to process and store it. As the API returns the premiere episodes grouped by date, we want to remove this grouping and just create a single array with all the premiere episodes and their associated data. Modify mainController.js to be as follows:

    app.controller("mainController", function($scope, $http){
        $scope.apiKey = "[YOUR API KEY]";
        $scope.results = [];
        $scope.init = function() {
            //API requires a start date
            var today = new Date();
            //Create the date string and ensure leading zeros if required
            var apiDate = today.getFullYear() + ("0" + (today.getMonth() + 1)).slice(-2) + "" + ("0" + today.getDate()).slice(-2);
            $http.jsonp('http://api.trakt.tv/calendar/premieres.json/' + $scope.apiKey + '/' + apiDate + '/' + 30 + '/?callback=JSON_CALLBACK').success(function(data) {
                //As we are getting our data from an external source, we need to format the data so we can use it to our desired effect
                //For each day, get all the episodes
                angular.forEach(data, function(value, index){
                    //The API stores the full date separately from each episode. Save it so we can use it later
                    var date = value.date;
                    //For each episodes, add it to the results array
                    angular.forEach(value.episodes, function(tvshow, index){
                        //Create a date string from the timestamp so we can filter on it based on user text input
                        tvshow.date = date; //Attach the full date to each episode
                        $scope.results.push(tvshow);
                    });
                });
            }).error(function(error) {

            });
        };
    });

The above code is well commented and should be easy to follow, lets take a look at these changes. First, we declare a scope variable $scope.results as an array which will hold our processed results. We then use angular.forEach (which is similar to jQuery’s $.each method for those who know it) to loop through each date group and store the date in a local date variable.

We then create another loop which loops through each of the TV shows within that date group, adds the locally stored date to the tvshow object and then finally adds each tvshow object to the $scope.results array. With all of this done, our $scope.results array will look like the following:

figure4-formatted-tvshow-json-objects

Creating the List HTML

We now have some data we wish to display within a list, on our page. We can create some HTML with ng-repeat to dynamically create the list elements based on the data within $scope.results. Add the following HTML code within the unordered list that has the episode-list class in index.html:

    <li ng-repeat="tvshow in results">
        <div class="row-fluid">
            <div class="span3">
                <img src="{{tvshow.episode.images.screen}}" />
                <div class="ratings"><strong>Ratings:</strong> <span class="label"><i class="icon-thumbs-up"></i> {{tvshow.episode.ratings.loved}}</span> <span class="label"><i class="icon-thumbs-down"></i> {{tvshow.episode.ratings.hated}}</span> <span class="label label-important" ng-class="{'label-success': tvshow.episode.ratings.percentage >= 50}"><strong>%</strong> {{tvshow.episode.ratings.percentage}}</div>
            </div>
            <div class="span6">
                <h3>{{tvshow.show.title}}: {{tvshow.episode.title}}</h3>
                <p>{{tvshow.episode.overview}}</p>
            </div>
            <div class="span3">
                <div class="fulldate pull-right label label-info">{{tvshow.date}}</div>
                <ul class="show-info">
                    <li><strong>On Air:</strong> {{tvshow.show.air_day}} {{tvshow.show.air_time}}</li>
                    <li><strong>Network:</strong> {{tvshow.show.network}}</li>
                    <li><strong>Season #:</strong> {{tvshow.episode.season}}</li>
                    <li><strong>Genres:</strong> <span class="label label-inverse genre" ng-repeat="genre in tvshow.show.genres">{{genre}}</span></li>
                </ul>
            </div>
        </div>
    </li>

This HTML is simply creating a single list element with ng-repeat. ng-repeat="tvshow in results" is telling angular to repeat this list element for each object within the $scope.results array. Remember that we do not need to include the $scope, as we are within an element with a specified controller (refer to the previous tutorial for more on this).

Inside the li element we can then reference tvshow as a variable which will hold all of the objects data for each of the TV shows within $scope.results. Below is an example of one of the objects within $scope.results so you can easily see how to reference each slice of data:

    {
    "show":{
        "title":"Agatha Christie's Marple",
        "year":2004,
        "url":"http://trakt.tv/show/agatha-christies-marple",
        "first_aired":1102838400,
        "country":"United Kingdom",
        "overview":"Miss Marple is an elderly spinster who lives in the village of St. Mary Mead and acts as an amateur detective. Due to her long and eventful life crimes often remind her of other incidents. Although Miss Marple looks sweet, frail, and old, she fears nothing; either dead or living.",
        "runtime":120,
        "network":"ITV",
        "air_day":"Monday",
        "air_time":"9:00pm",
        "certification":"TV-14",
        "imdb_id":"tt1734537",
        "tvdb_id":"78895",
        "tvrage_id":"2515",
        "images":{
            "poster":"http://slurm.trakt.us/images/posters/606.jpg",
            "fanart":"http://slurm.trakt.us/images/fanart/606.jpg",
            "banner":"http://slurm.trakt.us/images/banners/606.jpg"
        },
        "ratings":{
            "percentage":91,
            "votes":18,
            "loved":18,
            "hated":0
        },
        "genres":[
            "Drama",
            "Crime",
            "Adventure"
        ]
    },
    "episode":{
        "season":6,
        "number":1,
        "title":"A Caribbean Mystery",
        "overview":"\"Would you like to see a picture of a murderer?\", Jane Marple is asked by Major Palgrave whilst on a luxurious holiday in the West Indies. When she replies that she would like to hear the story, he explains. There once was a man who had a wife who tried to hang herself, but failed. Then she tried again later, and succeeded in killing herself. The man remarried to a woman who then tried to gas herself to death. She failed, but then tried again later and succeeded. Just as Major Palgrave is about to show the picture to her, he looks over her shoulder, appears startled, and changes the subject. The next morning, a servant, Victoria Johnson, finds him dead in his room. Doctor Graham concludes that the man died of heart failure; he showed all the symptoms, and had a bottle of serenite (a drug for high blood pressure) on his table.",
        "url":"http://trakt.tv/show/agatha-christies-marple/season/6/episode/1",
        "first_aired":1371366000,
        "images":{
            "screen":"http://slurm.trakt.us/images/fanart/606-940.jpg"
        },
        "ratings":{
            "percentage":0,
            "votes":0,
            "loved":0,
            "hated":0
        }
    },
    "date":"2013-06-16"
    }

As an example, within the li element, we can get the show title by referencing tvshow.show.title and wrapping it in double curly brackets:{{ }}. With this understanding, it should be easy to see what information will be displayed for each list element. Thanks to the CSS bundled with the skeleton structure, if you save these changes and open index.html within your browser, you should see a nicely formatted list of TV shows with the associated information and images. This is shown in the figure below:

figure5-formatted-show-list

Conditional Classes

You may or may not have noticed:

ng-class="{'label-success': tvshow.episode.ratings.percentage >= 50}"

…which is attached to one of the span elements, within the ratings section, in the above HTML. ng-class allows us to conditionally apply classes to HTML elements. This is particularly useful here, as we can then apply a different style to the percentage span element depending on whether the TV show rating percentage is high or not.

In the above HTML example, we want to apply the class label-success, which is a Twitter Bootstrap class, which will style the span to have a green background and white text. We only want to apply this class to the element if the rating percentage is greater than or equal to 50. We can do this as simply as tvshow.episode.ratings.percentage >= 50. Take a look down the list of formatted TV shows in your browser, if any of the percentages meet this condition, they should be displayed green.


Creating a Search Filter

We now have a list of upcoming TV show premieres, which is great, but it doesn’t offer much in the way of functionality. We are now going to add a simple text search which will filter all of the objects within the results array.

Binding HTML Elements to Scope Variables

Firstly we need to declare a $scope.filterText variable within mainController.js as follows:

    app.controller("mainController", function($scope, $http){
        $scope.apiKey = "[YOUR API KEY]";
        $scope.results = [];
        $scope.filterText = null;
        $scope.init = function() {
            //API requires a start date
            var today = new Date();
            //Create the date string and ensure leading zeros if required
            var apiDate = today.getFullYear() + ("0" + (today.getMonth() + 1)).slice(-2) + "" + ("0" + today.getDate()).slice(-2);
            $http.jsonp('http://api.trakt.tv/calendar/premieres.json/' + $scope.apiKey + '/' + apiDate + '/' + 30 + '/?callback=JSON_CALLBACK').success(function(data) {
                //As we are getting our data from an external source, we need to format the data so we can use it to our desired affect
                //For each day get all the episodes
                angular.forEach(data, function(value, index){
                    //The API stores the full date separately from each episode. Save it so we can use it later
                    var date = value.date;
                    //For each episodes add it to the results array
                    angular.forEach(value.episodes, function(tvshow, index){
                        //Create a date string from the timestamp so we can filter on it based on user text input
                        tvshow.date = date; //Attach the full date to each episode
                        $scope.results.push(tvshow);
                    });
                });
            }).error(function(error) {

            });
        };
    });

Now we need to add a text input so that the user can actually input a search term. We then need to bind this input to the newly declared variable. Add the following HTML within the div which has the search-box class in index.html.

    <label>Filter: </label>
    <input type="text" ng-model="filterText"/>

Here we have used ng-model to bind this input to the $scope.filterText variable we declared within our scope. Now this variable will always equal what is inputted into this search input.

Enforcing Filtering On ng-repeat Output

Now that we have the text to filter on, we need to add the filtering functionality to ng-repeat. Thanks to the built-in filter functionality of AngularJS, we do not need to write any JavaScript to do this, just modify your ng-repeat as follows:

    <li ng-repeat="tvshow in results | filter: filterText">

It’s as simple as that! We are telling AngularJS – before we output the data using ng-repeat, we need to apply the filter based on the filterText variable. Open index.html in a browser and perform a search. Assuming you searched for something that exists, you should see a selection of the results.


Creating a Genre Custom Filter

So, our users can now search for whatever they are wanting to watch, which is better than just a static list of TV shows. But we can take our filter functionality a little further and create a custom filter that will allow the user to select a specific genre. Once a specific genre has been selected, the ng-repeat should only display TV shows with the chosen genre attached.

First of all, add the following HTML under the filterText input in index.html that we added previously.

    <label>Genre: </label>
    <select ng-model="genreFilter" ng-options="label for label in availableGenres">
        <option value="">All</option>
    </select>

You can see from the above HTML that we have created a select input bound to a model variable called genreFilter. Using ng-options we are able to dynamically populate this select input using an array called availableGenres.

First of all, we need to declare these scope variables. Update your mainController.js file to be as follows:

    app.controller("mainController", function($scope, $http){
        $scope.apiKey = "[YOUR API KEY HERE]";
        $scope.results = [];
        $scope.filterText = null;
        $scope.availableGenres = [];
        $scope.genreFilter = null;
        $scope.init = function() {
            //API requires a start date
            var today = new Date();
            //Create the date string and ensure leading zeros if required
            var apiDate = today.getFullYear() + ("0" + (today.getMonth() + 1)).slice(-2) + "" + ("0" + today.getDate()).slice(-2);
            $http.jsonp('http://api.trakt.tv/calendar/premieres.json/' + $scope.apiKey + '/' + apiDate + '/' + 30 + '/?callback=JSON_CALLBACK').success(function(data) {
                //As we are getting our data from an external source, we need to format the data so we can use it to our desired affect
                //For each day get all the episodes
                angular.forEach(data, function(value, index){
                    //The API stores the full date separately from each episode. Save it so we can use it later
                    var date = value.date;
                    //For each episodes add it to the results array
                    angular.forEach(value.episodes, function(tvshow, index){
                        //Create a date string from the timestamp so we can filter on it based on user text input
                        tvshow.date = date; //Attach the full date to each episode
                        $scope.results.push(tvshow);
                        //Loop through each genre for this episode
                        angular.forEach(tvshow.show.genres, function(genre, index){
                            //Only add to the availableGenres array if it doesn't already exist
                            var exists = false;
                            angular.forEach($scope.availableGenres, function(avGenre, index){
                                if (avGenre == genre) {
                                    exists = true;
                                }
                            });
                            if (exists === false) {
                                $scope.availableGenres.push(genre);
                            }
                        });
                    });
                });
            }).error(function(error) {

            });
        };
    });

It is obvious that we have now declared both genreFilter and availableGenres which we saw referenced within our HTML. We have also added some JavaScript which will populate our availableGenres array. Within the init() function, while we are processing the JSON data returned from the API, we are now doing some additional processing and adding any genres that are not already within the availableGenres array to this array. This will then populate the select input with any available genres.

If you open index.html within your browser, you should see the genre select drop down populate as illustrated below:

figure6-genre-select-drop-down

When the user chooses a genre, the $scope.genreFilter variable will be updated to equal the selected value.

Creating the Custom Filter

As we are wanting to filter on a specific part of the TV show objects, we are going to create a custom filter function and apply it alongside the AngularJS filter within the ng-repeat.

At the very bottom of mainController.js, after all of the other code, add the following JavaScript:

    app.filter('isGenre', function() {
        return function(input, genre) {
            if (typeof genre == 'undefined' || genre == null) {
                return input;
            } else {
                var out = [];
                for (var a = 0; a < input.length; a++){
                    for (var b = 0; b < input[a].show.genres.length; b++){
                        if(input[a].show.genres[b] == genre) {
                            out.push(input[a]);
                        }
                    }
                }
                return out;
            }
        };
    });

The above JavaScript declares a custom filter to our app called isGenre. The function within the filter takes two parameters, input and genre. input is provided by default (which we will see in a moment) and is all the data that the ng-repeat is processing. genre is a value we need to pass in. All this filter does, is take the specified genre and checks to see if each of the TV show objects within input have the specified genre attached to them. If an object has the specified genre, it adds it to the out array, which will then be returned to the ng-repeat. If this doesn’t quite make sense, don’t worry! It should shortly.

Applying the Custom Filter

Now that we have our customer filter available, we can add this additional filter to our ng-repeat. Modify your ng-repeat in index.html as follows:

    <li ng-repeat="tvshow in results | filter: filterText | isGenre:genreFilter">

This simply chains another filter onto the ng-repeat output. Now the output will be processed by both filters before it is displayed on the screen. As you can see we have specified our custom filter as isGenre: and then we are passing the scope variable genreFilter as a parameter, which is how we provide our customer filter with the genre variable we talked about earlier. Remember that AngularJS is also providing our filter with the data that the ng-repeat is processing as the input variable.

OK, our custom genre filter is complete. Open index.html in a browser and test out the new functionality. With this filter in place, a user can easily filter out genres they are not interested in.


Calling Scope Functions

You may have noticed that each TV show listing also shows the genre itself. For some additional functionality, we are going to allow the user to click these genres, which will then automatically apply the genre filter for the genre they have clicked on. First of all, we need to create a scope function that the ng-click can call. Add the following code within the mainController on mainController.js:

    $scope.setGenreFilter = function(genre) {
        $scope.genreFilter = genre;
    }

In the above code, this function takes a genre value and then sets the $scope.genreFilter to the specified value. When this happens, the genre filter select box’s value will update and the filter will be applied to the ng-repeat output. To trigger this function when the genre span elements are clicked, add an ng-click to the genre span elements within index.html as follows:

    <span class="label label-inverse genre" ng-repeat="genre in tvshow.show.genres" ng-click="setGenreFilter(genre)">{{genre}}</span>

The ng-click calls our previously created setGenreFilter function and specifies a genre. Open index.html and try it out!


Custom Ordering With AngularJS

Our TV show premiere app is looking pretty good, users can easily refine the results displayed using a series of intuitive filters. To enhance this experience we are going to add some custom ordering functionality so our users will be able to choose a range of ordering options.

Add the following HTML under the genre select drop down:

    <label>Order by: </label>
    <select ng-model="orderField" ng-options="label for label in orderFields" class="input-medium"></select>
    <select ng-model="orderReverse"class="input-medium">
        <option value="true">Descending</option>
        <option value="false">Ascending</option>
    </select>

With this code added, we have two more drop downs. One to select how to order the data and another to choose the direction in which to order the data. We now need to create a function within our controller to make the order comparison. Add the following JavaScript under our setGenreFilter function:

    $scope.customOrder = function(tvshow) {
        switch ($scope.orderField) {
            case "Air Date":
                return tvshow.episode.first_aired;
                break;
            case "Rating":
                return tvshow.episode.ratings.percentage;
                break;
        }
    };

We also need to declare some additional scope variables:

    $scope.orderFields = ["Air Date", "Rating"];
    $scope.orderDirections = ["Descending", "Ascending"];
    $scope.orderField = "Air Date"; //Default order field
    $scope.orderReverse = false;

If you now open index.html within your browser, you should see the added drop downs populated with Air Date already selected as the default order field. This is shown in the figure below:

figure7-order-drop-downs

Finally, as we have done with our other filters, we are going to need to append this to our ng-repeat, update this as follows:

    <li ng-repeat="tvshow in results | filter: filterText | isGenre:genreFilter | orderBy:customOrder:orderReverse">

We are now applying an order-by-filter on our data in addition to the other filters. We are telling the order by to use our customOrder function and we are passing our orderReverse scope variable through as well. Open index.html in a browser and see the ordering in action.


Conclusion

AngularJS has allowed us to quickly create a detailed and functional web application with minimum effort. Utilizing AngularJS’s built-in filter functions, alongside some of our own custom code, our web application allows our users to easily filter and search through the TV show premieres.

After reading this tutorial you should now be able to understand and use the following principles:

  • Using ng-repeat to display information on screen.
  • Binding to inputs, allowing users to search and filter ng-repeat output.
  • Chaining filters on ng-repeat to perform multiple filtering functions.
  • Custom ordering of data.
  • Using events such as ng-click to respond to user interaction.
  • Using ng-class to conditionally apply styling to page elements.

So in conclusion, the topics covered in this tutorial should give you a strong foundation and understanding of what you can achieve when creating rich web applications in AngularJS.

19 Jun 12:19

A Realtime Monitoring System for PHP using MySQL

by Ray Cheung

Advertise here via BSA

Pinba is a MySQL storage engine that acts as a realtime monitoring/statistics server for PHP using MySQL as a read-only interface. It accumulates and processes data sent over UDP by multiple PHP processes and displays statistics in a nice human-readable form of simple “reports”, also providing read-only interface to the raw data in order to make possible generation of more sophisticated reports and stats.

Intaro Pinboard is a simple PHP monitoring system, which aggregates and displays Pinba data. Originally Pinba saves realtime (or nearly realtime) data in own tables. Pinboard periodically dumps this data in own tables and displays core metrics on basis of own data and realtime data from Pinba.

php-monitor

Requirements: PHP Framework
Demo: http://intaro.github.io/pinboard/
License: MIT License

Sponsors

Professional Web Icons for Your Websites and Applications

17 Jun 09:28

Packing a Symfony full-stack Framework Application in one File -- Introduction

by Fabien Potencier
Benjamin

J'aime le challenge

This article is part of a series of articles that explains how to pack a Symfony full-stack application in one file. The first article explains why this might actually be useful: 1) Introduction, 2) Bootstrapping, ...

Sometimes, I'm wondering if I'm not just completely crazy. I like small things, but I'm the author of Symfony, a not-so-small framework (about eighty thousand lines of code excluding comments as of today). And that's probably because I like to push the limits of what's possible when coding.

In 1985, my first useful piece of code was about managing a portfolio of stocks for my parents. I was twelve years old at that time. I won a contest. It was an interesting challenge: coding a full game in less than 10 lines of code. And my code was published in a French magazine.

In 2009, I tweeted an implementation of a dependency injection container in less than 140 characters (I did the same with a web framework).

And most of the time, those experiments helped me get to the next level. Twittee, my service container that fits in a Tweet, was an experiment, but then, it became Pimple, a small dependency injection container that is used today in Silex, a micro-framework based on the Symfony components.

So, that's not about just trying to push the limits, or trying to have fun. It's also about experimenting different approaches to known problems and see if they can have practical usage.

So, 2013... time for another challenge, right? What about packing a Symfony full-stack application in a single file. No Silex, no phar allowed, no compilation phase, just everything in a single readable file: from assets to controllers, from templates to Composer configuration.

Why?

This is yet another step toward my Quest of the PHP Holy Grail. But besides being a though challenge, there are many other reasons that makes it interesting for everyone.

First, that's a good way to learn more about the Symfony internals and especially about the Kernel class. Nowadays, thanks to all the talks about HttpKernel given by various speakers at various conferences, and thanks to my series of articles about it on my blog, a lot of developers understand how Symfony handles requests and how it manages the conversion to responses. There is even a full chapter about it in the official documentation.

But the Symfony Kernel is less well-known. This is a shame as it is also a very interesting piece of software. I hope that this challenge will give you more information about the Symfony Kernel and that, as a result, more Open-Source projects will adopt it instead of just using the components.

Then, I want to showcase once more the flexibility of the Symfony core framework and the decoupling between all aspects of the framework. If you are just a Symfony developer, you might not realize how the low level architecture of Symfony works, and I'm going to give you some insights about it.

Also, there is a more practical usage: bug reporting. When you report a Symfony bug, sometimes, it is not that easy to reproduce it. Probably because it involves third-party bundles, a specific configuration, or a chain of controller calls. For such bugs, it is almost impossible to make a patch without a way to reproduce it. As a matter of fact, we often ask reporters to fork the Symfony Standard Edition and modify it in a way that exhibits the issue. But doing so is tedious for both the reporter and the developer that will try to fix the bug. Doing the same with Silex is more easier as most of the time, the reporter is able to package everything is a single file. So, being able to do the same with the full-stack framework would be a huge step forward.

Reporting bugs is fine, but being able to experiment things in a small environment also helps. A few weeks ago, Jordi submitted a new API layer to simplify the configuration of Symfony's Security. To better understand how to use it and to get a feeling for the new API, I decided to create a small project to test different common configurations. And being able to do that in one file would have helped me a lot.

Being able to pack a whole application in one file is also very useful when you are teaching Symfony to someone, or if you want to show how to use a specific Symfony feature.

Micro vs Full-Stack

So, let's sum up things a bit. I created Twitto, a micro-framework that fits in a tweet. Then, Silex, a micro-framework based on the Symfony components. And now, I want to make it possible to create a full-stack Symfony application in just one file. Does it mean that Symfony full-stack is also a micro-framework?

What is a micro-framework? Micro means "extremely small" and a framework is a set of tools that structures an application. It abstracts the low-level architecture of a project.

To me, micro does not mean less code. The user of a framework does not care about the number of lines of code in the framework. It does not matter when using the framework.

To me, micro means less structure, less constraints, less decisions made for you. Full-stack frameworks are great as they provide a sensible default directory structure; they come with many integrated features; they allow you to get started faster; they allow you to easily understand what's going on on an existing project.

A micro-framework is just about the bare minimum you need to get started. It lets you decide which directory structure you want, it lets you decide which feature you want to enable, it lets decide how you want to work.

Two different approaches to solve the same problem. And both have valid use cases. So, comparing a micro-framework to a full-stack one should not be based on the number of lines of code, but the comparison should be done on the way you are using the framework.

The Challenge

So, is it possible to pack a Symfony full-stack application in one file? And, is it possible to do that in less than 200 lines of code? Well, take a seat, fasten your seatbelt, grab a coffee, and relax. I'm going to show you how I took up the challenge in this series of articles, and along the way, I'm going to explain how Symfony works. Hopefully, you're also going to learn a few tricks about PHP and Symfony.

That's all for the philosophy of the challenge. Next time, we will start tweaking the Symfony Standard Edition.

13 Jun 14:45

Helium CSS - Déctecter le CSS non utilisé sur votre site

by Ouark
Helium CSS est un outil javascript qui analyse les pages de votre site à la recherche de déclarations CSS qui ne seraient jamais utilisées.
11 Jun 12:15

iOS 7 looks to catch up to Symbian circa 2010

Benjamin

rien à ajouter !

The headline is slightly tongue in cheek, of course, but there were some striking 'Duh' moments for Symbian users during last night's launch of Apple's iOS 7 for their iPhones (etc.) I've highlighted a few of them below, for your interest and amusement. You have to wonder though, for how many years will other operating systems still be launching features and concepts that Symbian has/had up to a decade before?

04 Jun 09:17

Un fumeur coûte en moyenne 4.600 euros de plus à son employeur qu'un non fumeur

by no-reply@20minutes.fr
SOCIETE - Selon une étude américaine rendue publique mardi...


30 May 09:15

Fairphone, un smartphone estampillé “équitable”

by Laure Renouard

Si l’on vous parle de commerce équitable, vous pensez à du café, du chocolat et autres denrées alimentaires ? Pas seulement, si l’on en croit les concepteurs du Fairphone. Un terminal que l’équipe qualifie de 100% équitable. Une première en son genre.

Fairphone

Un smartphone sérieusement cool qui met en avant des valeurs sociales“. Voilà la punchline retenue par l’équipe à l’origine du Fairphone, une société basée aux Pays-Bas portant le même nom.

L’idée n’est plus ici de créer un smartphone simplement écologique : chaque matériau retenu est issu de zones exemptes de conflits, les sous-traitants ont été choisis pour la transparence de leurs procédés comme pour leur considération de leurs employés, et le prix du terminal a été établi au plus juste. On retiendra, parmi les choix réalisés par Fairphone, un approvisionnement en matériaux en République Démocratique du Congo, dans des mines certifiées pour ne pas alimenter les fonds de forces armées. De plus, même si cet objectif ne peut encore être entièrement tenu, Fairphone vise à long terme un smartphone entièrement recyclable, du terminal à son packaging. On notera également que les Néerlandais ont choisi de verser 3 € par téléphone vendu à l’association Closing the Loop, laquelle finance des projets dans les pays en voie de développement.

 

A quoi ressemble le Fairphone ?

Déjà disponible en précommandes – sur les 5000 nécessaires à la mise en production du smartphone, plus de 3000 ont déjà trouvé preneur à un tarif de 325 € – le Fairphone propose des caractéristiques internes intéressantes, pour ce tarif positionné en milieu de gamme. Equipé d’un écran qHD de 4,3 pouces s’appuyant sur la technologie de verre résistant Dragontail, il tourne sous Android 4.2 (Jelly Bean) propulsé par un processeur quadricoeur Mediatek 6589 cadencé à 1,2 GHz et couplé à 1 Go de RAM. Côté mémoire de stockage, comptez sur 16 Go embarqués, tandis que le Fairphone propose un capteur arrière de 8 mégapixels ainsi qu’une caméra avant de 1,3 million de points, sans oublier le support de deux cartes SIM. Le tout mesure 123 x 64,5 x 9,8 mm pour un poids de 165 grammes. Une batterie de 2000 mAh vient compléter l’ensemble.

Si l’on souhaitait chipoter un peu, on rappellerait tout de même que Fairphone laisse à ses clients le soin d’investir dans leurs accessoires en supplément, puisque chargeur, casque ni écouteurs ne sont inclus au pack commercial. Pour atteindre les 5000 ventes nécessaires à la fabrication de l’androphone, Fairphone s’est laissé jusqu’au 14 juin prochain (sur son site). Au rythme actuel des souscriptions, nul doute que ce score sera rapidement atteint.

L’entreprise néerlandaise aurait pu aller encore plus loin, en choisissant des prestataires de composants “équitables”.

27 May 07:34

Cargo-Culting in JavaScript

by James Padolsey

Cargo-cult programming is what a programmer does when he or she doesn't know a particular language or paradigm well enough, and so ends up writing redundant and possibly harmful code. It rears its head quite often in the land of JavaScript. In this article, I explore the concept of cargo-cult programming and places to watch out for it in JavaScript.

Dogmatic rules surface and spread, until they are considered the norm.

Cargo-culting is sometimes defined as "the extreme adherence to the form instead of content." The form, in programming, being the syntax, paradigms, styles and patterns that we employ. The content being the abstract thing that you are seeking to represent through your code — the very substance of your program. A person with lacking understanding in an area is likely to copy the form of others without truly understanding, and thus their content — their program — can suffer.

Cargo-culting is curiously common in JavaScript, probably because of the general low barrier to entry in the front-end development world. You can whip up an HTML page with a bit of JavaScript in seconds. As a result, there are many people who become sufficiently proficient in these technologies to feel comfortable creating and imposing rules on themselves and others. Eventually, other newcomers copy these rules. Dogmatic rules surface and spread, until they are considered the norm:

  • Always use strict equality operators
  • Never use eval
  • Always use a single var declaration per scope
  • Always use an IIFE – it “protects” you

A rule continues to spread until a programmer is only using a given technique because of its popularity, instead of considering each specific use-case independently.


JavaScript Abuzz with Semicolons

If you've had the opportunity to witness the witty banter and rhetoric of the software developer over the years, you will have spotted a tendency to discuss seemingly tiny things at great lengths. Things like the semicolon, the comma, white-space or the curly brace.

Syntax like semicolons or white-space may seem to purely be elements of form, not of content. But many of these subtle syntax rules can have significant effects in JavaScript. If you don't understand the 'form' then you cannot begin to understand the 'content'.

So in this article, we will identify what areas of form in JavaScript are frequently cargo-culted off of — that is, copied without understanding.

How JavaScript can seem
How JavaScript can seem… an image from Angus Croll’s "The Politics Of JavaScript" presentation

Undefined

Angus Croll, in a recent presentation, titled "The Politics Of JavaScript", highlighted one of the most common pieces of JS dogma that people cargo-cult off of:

if (typeof myObject.foo === 'undefined') {...}

Most of the time, doing such a long-winded check for undefined is pointless. The technique became common because people were copying other people, not because of it's actual value.

Of course, there are times when:

typeof x === 'undefined'

… is preferable to:

x === undefined

But, equally, there are times when the latter is preferred. A quick overview of the options:

// Determine if `x` is undefined:
x === undefined
typeof x == 'undefined'
typeof x === 'undefined'
x === void 0

// Determine if `x` is undefined OR null:
x == null
x == undefined

People started using the typeof approach because they were protecting themselves against:

  • A potentially undeclared variable (non-typeof approaches would throw TypeErrors)
  • Someone overwrote undefined globally or in a parent scope. Some environments allow you to overwrite undefined to something like true. You have to ask yourself: “Is it likely that someone overwrote undefined, and should my script have to pander to such silliness?

But most of the time they're protecting themselves from having to worry. It's a catch-all avoidance of having to know the details. Knowing the details can help you though. Every character of your code should exist with a purpose in mind.

The only time that you should need to use a typeof check for undefined is when you are checking for a variable that may not have been declared, e.g. checking for jQuery in the global scope:

if (typeof jQuery != 'undefined') {
    // ... Use jQuery
}

The thing is, if jQuery does exist, then we can be sure that it's an object – a "truthy" thing. So this would be sufficient:

// or:
if (window.jQuery) {

}

The Great Strict/non-strict Debate

Let's take something very common and generally considered good advice, solely using strict-equality:

a === b

Strict-equality is said to be good because it avoids ambiguity. It checks both the value and the type, meaning that we don't have to worry about implicit coercion. With non-strict equality, we do have to worry about it though:

1 == 1    // true &mdash; okay, that's good
1 == "1"  // true &mdash; hmm
1 == [1]  // true &mdash; wat!?

So it would seem sensible advice to entirely avoid non-strict equality, right? Actually, no. There are many situations where strict-equality creates large amounts of redundancy, and non-strict equality is preferable.

When you know, with 100% certainty, that the types of both operands are the same, you can avoid the need for strict-equality. For example, I always know that the typeof operator returns a string, and my right-hand operand is also a string (e.g. "number"):

// With strict-equals
typeof x === 'number'

// With non-strict-equals:
typeof x == 'number'

They're both effectively identical. I am not necessarily suggesting that we abandon strict-equals in this case — I am suggesting that we remain aware of what we're doing so that we can make the best choices given each situation.

Another quite useful example is when you want to know if a value is either null or undefined. With strict equality, you might do this:

if (value === undefined || value === null) {
    // ...
}

With non-strict equality, it's far simpler:

if (value == null) {
    // ...
}

There is no catch here — it is doing exactly what we want, only, arguably, less visibly. But, if we know the language, then what's the problem? It's right there in the spec:

The comparison x == y, where x and y are values, produces true or false. Such a comparison is performed as follows:

  • If x is null and y is undefined, return true.
  • If x is undefined and y is null, return true.

If you're writing JavaScript with the intention of it being read, if at all, by people that know JavaScript, then I would argue that you shouldn't feel bad taking advantage of implicit language rules, like this.


hasOwnProperty

The hasOwnProperty method is used to determine whether a property is directly owned by an object. Is it commonly found in for..in loops to ensure that you only mess with direct properties and not inherited properties.

for (var i in object) {
    if (object.hasOwnProperty(i)) {
        // We can do stuff with `object[i]`
    }
}

It’s important to note that the for-in statement will only loop through enumarable properties. Native inherited methods, for example, are not enumerable and so you don't need to worry about them anyway.

The hasOwnProperty check is specifically preventing you from touching properties that you or some third-party script has defined, i.e. when your object's prototype has enumerable properties.

If you know that your object's prototype (or its prototype’s prototype etc.) doesn't have any enumerable properties, then you don't have to worry about using hasOwnProperty in your for-in loops. And, if your object is initialized, via ES5's Object.create(null), then you won't even be able to call hasOwnProperty directly on the object (no prototype means no inherited native methods). This means that using hasOwnProperty by default in all of your for-in loops may actually break sometimes.

One potential solution for objects with null prototypes is to use a saved reference to hasOwnProperty, like so:

var hasOwnProperty = Object.prototype.hasOwnProperty;

// Later in your code:
for (var i in someObject) {
    if (hasOwnProperty.call(someObject, i)) {
        // ...
    }
}

That will work even if the object has no prototype (in the case of Object.create(null)). But, of course, we should only do this in the first place if we know we need it. If you're writing a third-party script for a "hostile" environment, then yes, definitely check for enumerable inherited properties. Otherwise, it may not be necessary all the time.

Note: IE9 and Safari 2.0 complicate the matter further when you're trying to identify enumerable properties that are already defined as non-enumerable. It's worth checking out a truly cross-browser forOwn loop implementation.

To conclude: your use of hasOwnProperty should depend on the object being looped over. It depends on what assumptions you can safely make. Blindly protecting yourself using the hasOwnProperty will not suffice in all cases. Be wary of cross-browser differences too.


Over-Parenthesising

Another common redundancy that creeps into JS code is the parenthesis. Within expressions, it is used to force specific grouping of sub-expressions. Without them, you are at the mercy of operator precedences and associativities. For example:

A && B || C
A && (B || C)
(A && B) || C

One of those is not like the other. The parentheses force a specific grouping, and many people prefer the extra clarity. In this case, the logical AND operator has a higher precedence than the logical OR operator, meaning that it is the first and last lines that are equivelant. The second line is an entirely different logical operation.

Higher precedence means that it will occur before other operations in a series of operations.

To avoid this complexity, developers frequently opt for a "parentheses policy" — where you keep adding parentheses until it is abundantly clear which operations are occurring, both for you and potential readers of the code. It can be argued that this verbosity ends up making things less clear though.

It’s tricky for a reader sometimes. One must consider that any given parentheses may have been added because:

  • It was needed to override default precedence/associativity
  • For no functional reason at all, just for "protection" or "clarity"

Take this example:

A && B ? doFoo() : doBaz()

Without knowledge of operator precedence rules, we can see two possible operations here:

(A && B) ? doFoo() : doBaz()
A && (B ? doFoo() : doBaz())

In this case, it's the logical AND that has the higher precedence, meaning that the equivalent parenthesised expression is:

(A && B) ? doFoo() : doBaz()

We should feel no obligation to add these parentheses in our code, though. It happens implicitly. Once we recognize that it happens implicitly, we are free to ignore it and focus on the program itself.

There are, of course, valid arguments to retain the parentheses where implicit grouping is unclear. This really comes down to you and what you're comfortable with. I would, however, implore you to learn the precedences and then you can be fully empowered to take the best route, dependent on the specific code you're dealing with.


Object Keys

It's not rare to see redundant quotes in object literals:

var data = {
  'date': '2011-01-01',
  'id': 3243,
  'action': 'UPDATE',
  'related': { '1253': 2, '3411': 3 }
};

In addition to strings, JavaScript allows you to use valid identifier names and numbers as object literal keys, so the above could be re-written to:

var data = {
  date: '2011-01-01',
  id: 3243,
  action: 'UPDATE',
  related: { 1253: 2, 3411: 3 }
};

Sometimes, you may prefer the added consistency of being able to use quotes, especially if a field-name happens to be a reserved word in JavaScript (like 'class' or 'instanceof'). And that's fine.

Using quotes is not a bad thing. But it is redundant. Knowing that you don't have to use them is half the battle won. It is now your choice to do what you want.


Comma Placement

There is a huge amount of subjective preference, when it comes to punctuation placement in programming. Most recently, the JavaScript world has been abuzz with rhetoric and discontent over the comma.

Initialising an object in traditionally idiomatic JavaScript looks like this:

var obj = {
    a: 1,
    b: 2,
    c: 3
};

There is an alternative approach, which has been gaining momentum though:

var obj = {
      a: 1
    , b: 2
    , c: 3 
};

The supposed benefit of placing the commas before each key-value pair (apart from the first) is that it means you only have to touch one line in order to remove a property. Using the traditional approach, you would need to remove "c: 3" and then the trailing comma on the line above. But with the comma-first approach you're able to just remove ", c: 3". Proponents claim this makes trailing commas less likely and also cleans up source-control diffs.

Opponents, however, say that this approach only achieves getting rid of the trailing-comma "problem" by introducing a new leading-comma problem. Try removing the first line and you're left with a leading comma on the next line. This is actually considered a good thing by comma-first proponents, because a leading comma would immediately throw a SyntaxError. A trailing comma, however, throws nothing, except in IE6 and 7. So if the developer fails to test their JS in those versions of IE, then the trailing commas can often creep into production code, which is never good. A leading comma throws in all environments, so is less likely to be missed.

Of course, you might argue that this entire thing is moot. We should probably be using linters like JSLint or the kinder JSHint. Then we're free to use the punctuation and whitespace placement that makes the most sense to us and our coworkers.

Let's not even get started on the comma-first style in variable declarations..

var a = 1
  , b = 2
  , c = 3
  ;

Thou Shalt Code for Psychopaths?

We should endeavour to learn the languages we use to a good enough level that we're able to avoid cargo-culting and over-protective catch-all coding techniques. And we should trust our coworkers and other developers to do the same.

We’ve also discussed the abandonement of cruft in favor of taking advantage of a language’s idiosyncracies and implicit rules. To some, this creates maintainability issues, especially if someone more junior in their acquisition of a given language approaches the code. For example, what if they don’t know about JavaScript’s weak vs. strict equality?

On the topic of maintainability, we’re reminded by this famous quote:

Always code as if the person who ends up maintaining your code is a violent psychopath who knows where you live.

I don’t know if that is truly good advice. Even taken metaphorically, it suggests a distrust of the fictional maintainer’s competency — and the need to worry about their understanding above everything else. I would rather write code in the knowledge that it will be taken care of by people that know their stuff. So as a possible contradiction or even an addendum to that quote, I offer:

Always code as if the person who ends up maintaing your code is knowledgeable about the language and its constructs and is seeking to gain understanding of the problem domain through reading your code.

While this may not always be true, we should seek for it be so. We should endeavour to ensure that people working on a specific technology have the sufficient understanding to do so. The learned cargo-culter says:

If I forever pander to a lower level of understanding in my code — treading softly — strictly abiding to conventions and style guides and things I see the “experts” do, then I am never able to advance my own understanding, nor take advantage of a language in all its weirdness and beauty. I am happily and blissfully settled in this world of rules and absolutes, but to move forward, I must exit this world and embrace higher understanding.

23 May 07:21

Film Promo AR.Drone 2.0 d’une minute a nécessité plus de 4 mois de préparation !

by cromei@servicesmobiles.fr (cromei)
Benjamin

25 drones pour la vidéo, y a eu de la casse !

Tourné en 4 jours dans un studio de 500 m2 situé en région Parisienne, ce film d’une minute a nécessité plus de 4 mois de préparation ! ci-dessous le Making Of et le film 

Parrot s’est entouré d’une équipe de 40 professionnels (ingénieurs Parrot, pilotes, décorateurs, éclairagistes, responsable effets spéciaux…) emmenée par Ben Elia, réalisateur et producteur et Michel Benjamin, chef opérateur qui a notamment participé à ‘Home 2009’ de Yann Arthus-Bertrand, au ‘Peuple Migrateur’ et ‘Océans’ de Jacques Perrin et Jacques Cluzaud. (25 AR.Drone 2.0 utilisés pendant le tournage)



22 May 08:02

Sphero - 100% compatible plage & soleil

by cromei@servicesmobiles.fr (cromei)
Benjamin

I want one ;-)

14 May 08:13

Conseils, de la compatibilité du costume-cravate à vélo

by Xav

Thierry-Leblond-cycliste-costume-cravateNous avons reçu la semaine dernière un message qui nous a fait bien plaisir. Celui de Thierry, un lecteur de Weelz qui, il me permettra je pense cette petite digression, ne rentre pas tout-à-fait dans la catégorie des cyclistes urbains "normaux". J'entends par là, sans vouloir généraliser, qu'il est de ces cyclistes que vous ne croisez pas nécessairement souvent en ville : les cyclistes en costume-cravate !

Thierry Leblond (ci-contre) nous a donc fait parvenir le texte ci-dessous, des conseils préalablement destinés à l'un de ses amis qui souhaitait également se mettre au déplacement à vélo. Des conseils qu'il a souhaité partager avec vous lecteurs, bien lui en a pris.

Thierry, directeur dans l'administration française, dirigeait le Plan de Vidéoprotection pour Paris jusque fin 2012, et, pour la petite histoire, a toujours refusé la voiture de fonction qu'on lui mettait pourtant gracieusement à disposition...

Thierry : "Le principe général est la simplicité héritée de nos anciens (les "hirondelles" de la police parisienne dans l'entre-deux guerre et jusque dans les années 60). Voici en quelques lignes l'essentiel de mon expérience, huit ans de vélo urbain  :

SPAD-De-Ville-Fulap Contre la pluie et les mauvaises conditions météo, après avoir essayé beaucoup de choses le plus simple est la cape de pluie car le problème avec un vêtement trop couvrant, c'est la transpiration. Avec une cape on est à l'abri de la pluie mais le corps respire.

J'ai découvert il y a quelques mois le modèle FULAP de "Spad de Ville" qui dépasse de loin tout ce que j'avais essayé avant. Pour s'en convaincre, il faut regarder les vidéos ici (étanchéité, respiration, traitement déperlant, élastique englobant le guidon et la selle, visière à grand angle de vision latérale).

Contre les crevaisons, il faut absolument s'équiper de pneus Schwalbe Marathon Plus. Expérience à l'appui, on n'a plus besoin de pompe à vélo ou de kit de réparation (pour ma part : une seule crevaison sur du verre en 7 ans et 20.000 km).

3735000719_52c51870d5_z Contre le vol : je n'ai jamais eu un seul vol bien que que je laisse régulièrement mes vélos garé parfois plusieurs semaines d'affilée l'un à la gare Montparnasse et l'autre à la gare St-Jean grâce au dispositif suivant :

Un antivol en U de chez Abus assez grand pour enserrer le cadre et la roue arrière sur un mobilier urbain. Attention : l'antivol pliable n'est pas très pratique comparativement au U mais il a l'avantage de ne pas pouvoir être forcé par un cric de Mini Austin (la technique de fracturation la plus répandue pour les antivols en U). Moi, je préfère quand même le U qui m'a évité plusieurs vols (traces d'effraction constatées).
Un antivol serpentin de diamètre 8 à 10 mm pour attacher la selle, la roue avant et le cadre sur le mobilier urbain.

Pour les bagages : préférer le classique porte bagage avec un classique sandow. La capacité de transport est colossale (bien plus qu'un coffre de scooter). Mais pour profiter de cette capacité, il faut aussi un sac de voyage adapté. Pour mes voyages hebdomadaires à Paris, j'ai opté pour le sac Patagonia Black Hole Duffel 60L avec des bretelles de sac à dos :

Les avantages sur sac de voyage classique avec une ouverture dans le sens de la longueur (et pas sur le dessus comme pour le sac à dos classique), le confort du sac à dos pour garder les mains libres lorsqu'on sort du train, l'étanchéité complète en cas de mauvais temps (je peux dire que j'ai testé de nombreuses fois le lundi matin entre St Médard et la gare de Bordeaux St Jean).

2600161741_0a5a8a37b2_z Au niveau physique : laisser du temps à son corps pour s'habituer (6 mois pour disposer de la musculation). Au dessous de 2 fois 15 km par jour, je pense qu'il vaut mieux un vélo à propulsion musculaire et éviter le vélo à assistance électrique (au delà, cela devient compétitif surtout s'il y a des montées sur le parcours).

Limiter son effort pour rester au dessous du seuil de transpiration. Aimer cela (si on n'aime pas ce type de transport, il ne faut pas insister car on peut s'en dégoutter).

En hiver et en intersaisons : sous la chemise blanche, il faut un sous-vêtement thermique anti-transpirant de type Odlo (le principe des 3 peaux en montagne). Une veste coupe-vent en Goretex. Le choix de la veste est très important car c'est qui va contribuer au confort : très légère, protège du froid dans le vent relatif et autorise un effort modéré sans transpirer.

J'ai opté depuis 5 ans et après de longs tâtonnements pour la veste Aigle Watertown noire parce que sur un costume sombre elle se fond totalement au style mais elle prend un peu l'eau (voir critique). Il vaut mieux je pense s’orienter sur des produits Patagonia de bien meilleure qualité technique à condition de trouver une veste adaptée au costume et qui ne fait pas trop "perroquet" (c'est le problème chez eux).

Voilà le résumé de ma "science" et j'espère que cela vous donnera envie d'essayer. Pour ma part, c'est devenu une besoin vital : évacuation du stress, forme physique, musculation en douceur, frais de transport négligeables, ponctualité, écologie, LIBERTÉ..."

Crédits photos : Jordan Fisher, WhyamiIKeenan, Jeremy Hughes.

13 May 08:04

Maven and PHP

by Octavia Anghel

Apache Maven is a build automation tool with the purpose of building, reporting, and creating documentation of projects. It builds projects using a Project Object Model (POM) and a set of plugins shared by all projects using Maven, thus providing a uniform build system. Once you familiarize yourself with how one Maven project builds, you automatically know how all Maven projects build. This saves you an immense amount of time from trying to navigate the build process of many different projects.

Through this article you will gain familiarity with Maven for PHP, and how to install and use the PHP-Maven plugin from the command line and in Eclipse.

Install Maven

PHP-Maven uses the power of Maven for building, reporting, and creating documentation of your PHP projects. It adapts the Maven build life cycle to the PHP world while fully supporting PHP 5. PHP-Maven uses PHPUnit for unit testing and phpDocumentor for creating the project documentation.

To install Maven:

  1. Download Maven from http://maven.apache.org/download.cgi. For this article, the version is 3.0.4.
  2. Unpack the archive wherever you would like to store the binaries, and a folder named apache-maven-<version> will be created.
  3. Add its bin folder to your PATH.
  4. Make sure JAVA_HOME is set to the location of your JDK.

After you’ve completed the above steps, to test whether Maven is installed correctly or not you should run mvn --version at a command prompt.

maven-1

Once Maven is successfully installed, go to the settings.xml file (found in ~/.m2 on Unix/Mac OS X and in C:\Documents and Settings\username\.m2 on Windows) and add the PHP for Maven repository. If there is no settings.xml file, you must create it.

Below is a sample settings.xml file:

<settings>
 <profiles>
  <profile>
   <id>profile-php-maven</id>
   <pluginRepositories>
    <pluginRepository>
     <id>release-repo1.php-maven.org</id>
     <name>PHP-Maven 2 Release Repository</name>
     <url>http://repos.php-maven.org/releases</url>
     <releases>
      <enabled>true</enabled>
     </releases>
    </pluginRepository>

    <pluginRepository>
     <id>snapshot-repo1.php-maven.org</id>
     <name>PHP-Maven 2 Snapshot Repository</name>
     <url>http://repos.php-maven.org/snapshots</url>
     <releases>
      <enabled>false</enabled>
     </releases>
     <snapshots>
      <enabled>true</enabled>
     </snapshots>
    </pluginRepository>
   </pluginRepositories>

   <repositories>
    <repository>
     <id>release-repo1.php-maven.org</id>
     <name>PHP-Maven 2 Release Repository</name>
     <url>http://repos.php-maven.org/releases</url>
     <releases>
      <enabled>true</enabled>
     </releases>
    </repository>

    <repository>
     <id>snapshot-repo1.php-maven.org</id>
     <name>PHP-Maven 2 Snapshot Repository</name>
     <url>http://repos.php-maven.org/snapshots</url>
     <releases>
      <enabled>false</enabled>
     </releases>
     <snapshots>
      <enabled>true</enabled>
     </snapshots>
    </repository>
   </repositories>
  </profile>
 </profiles>

 <activeProfiles>
  <activeProfile>profile-php-maven</activeProfile>
 </activeProfiles>
</settings>

Create Your First Project

To create a simple project from the command line I’ll use the Maven Archetype Plugin. The Archetype Plugin allows a user to create a Maven project from an existing template called an archetype. You can run the Maven Archetype plugin with the mvn archetype:generate command to generate a new project from an archetype, in a folder corresponding to its artifact ID.

maven-2

Maven will start downloading all the dependencies needed to your computer. At some point, Maven will ask you to define a value for groupId, artifactId, version and package, as you see here:

maven-3

Notice that at the official Maven Archetype Plugin page you will find all the available parameters along with their description.

After successfully creating your first project, you should find the following in the corresponding folder, in my case Octavia_project:

maven-4

  • src/main/php - contains the project’s source code.
  • src/test/php - contains the project’s test code.
  • src/site – contains the project’s site descriptor.
  • pom.xml - contains the project’s POM description.

The contents of pom.xml looks like this:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" 
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">

 <parent>
  <groupId>org.phpmaven</groupId>
  <artifactId>php-parent-pom</artifactId>
  <version>2.0.2</version>
 </parent>

 <modelVersion>4.0.0</modelVersion>
 <groupId>org.phpsample</groupId>
 <artifactId>Octavia_project</artifactId>
 <packaging>php</packaging>
 <version>1.0-SNAPSHOT</version>
 <build>
  <plugins>
   <plugin>
    <groupId>org.phpmaven</groupId>
    <artifactId>maven-php-plugin</artifactId>
    <extensions>true</extensions>
   </plugin>

   <plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-site-plugin</artifactId>
    <version>3.0</version>
    <configuration>
     <reportPlugins>
      <plugin>
       <groupId>org.phpmaven</groupId>
       <artifactId>maven-php-plugin</artifactId>
       <reportSets>
        <reportSet>
         <reports>
          <report>phpdocumentor</report>
          <report>phpunit-coverage</report>
          <report>phpunit</report>  
         </reports>
        </reportSet>
       </reportSets>
      </plugin>
     </reportPlugins>
    </configuration>
   </plugin>
  </plugins>
 </build>

 <dependencies>
  <!--  phpUnit for PHP 5 -->
  <dependency>
   <groupId>de.phpunit</groupId>
   <artifactId>PHPUnit</artifactId>
   <version>3.6.10</version>
   <type>phar</type>
  </dependency>
 </dependencies>
</project>

The test phase comes after creating your application, and for that you need the PHPUnit dependency. If it’s missing, be sure to add it to your pom.xml as shown above.

The PHPUnit tests should be place into the src/test/php folder and a test should be named SomthingTest.php, that is, the suffix “Test.php” is a must. My test, MyTest.php, is listed below:

<?php
class MyTest extends PHPUnit_Framework_TestCase
{
    public function testBar() {
        include "org/sample/app.php";
        $this->fail("we will fail");
    }	
}

To execute a test you use the command mvn test. In the official documentation has a section How to Ignore Failing Tests, and you can find there some commands that may help you run your test. (The only command that actually worked for me was the one that executed a single test.)

maven-5

To build your newly created Maven project, you run the command mvn:package. You will notice again that Maven automatically starts downloading any dependencies needed for your project.

After downloading all needed dependencies and performing the build actions, you should get the following success message:

maven-6

To create documentation from the project, you’ll need the phpDocumentor 2 PEAR package. In the src/site folder, create the site.xml file with the following contents:

<?xml version="1.0" encoding="ISO-8859-1"?>
<project name="Maven">
 <version position="left" />

 <skin>
  <groupId>org.apache.maven.skins</groupId>
  <artifactId>maven-stylus-skin</artifactId>
  <version>1.0</version>
 </skin>
 <body>
  <links>
   <item name="PHP-Maven" href="http://www.php-maven.org/" />
  </links>

  <menu name="Main">
   <item name="Welcome" href="index.html" />
  </menu>

  <menu ref="reports" />
 </body>
</project>

Next run the mvn site command and you’ll find the results in the target/site folder.

Eclipse Integration

The php-maven plugin supports integration with the Eclipse IDE, but it doesn’t contain the php-maven plugin by default. You need to integrate it manually. To do that, follow these steps:

  1. From the Help menu, choose Install New Software option and then press the “Add…” button.
  2. In the Add Repository window enter the name: “PHPMaven update site” and URL http://www.php-maven.org/eclipse/update.
  3. The PHPMaven update site is listed and you can choose the PHP-Maven option.
  4. Hit Next/Finish to install the plugins.

maven-7

maven-8

After the installation you will find the PHP-Maven project option when you go to create a new project. Select it, and press Next in order to install the plugin.

To create a new project within Eclipse, select File > New > Other (or press the CTRL + N combination) and you should see something like in the image below:

maven-9

After pressing the Next button you will receive a list of different archetypes.

maven-10

Choose your artifact and you will be prompted for the project information, just like earlier on the command prompt.

maven-11

The new project will be added to the Project Explorer tab. The folder structure is mostly similar to the one for the project created from command line.

After you create the project, right click on it and you’ll see the PHP-Maven option at the bottom of the menu, and its children list the most important phases of a PHP-Maven project.

maven-12

Summary

In this article you’ve learned how to install and use the PHP-Maven plugin from the command line and in Eclipse. Maven for PHP is a capable build automation tool for the PHP platform. Using Maven, the user only needs to provide the configuration for the project, while the configurable plugins do the work of compiling the project, running unit tests, generating API documentation and so on. Maven for PHP will quickly become a necessary tool in the PHP developer’s toolbox.

Image via Fotolia

06 May 07:32

Découvrez l’art du Time Lapse avec Vincent Laforet

by Lâm
Benjamin

La magie du time lapse, expliqué par Vincent Laforet

Vous avez toujours eu envie de filmer ces fameux time lapses ? Voici un introduction par M. Laforet himself.

…………………………

Ces ciels qui filent, ces travelings d’une fluidité surréaliste, cette vie qui passe à toute vitesse : depuis leur avènement, les time lapses et leur esthétique si spéciale font un carton parmi les pros comme les amateurs de belles images.

Commissionné par le Canon Digital Learning Center (dont il est l’un des ambassadeurs), le célèbre photographe et vidéaste Vincent Laforet (lire notre interview du personnage par ici) nous livre un guide pour découvrir cette discipline. La première vidéo (en anglais, mais très compréhensible), éclaire sur les concepts globaux.

Pour approfondir les connaissances, notamment au niveau du matériel requis, Laforet a écrit cet article pour vous. Une seconde vidéo sera prochainement publiée, en attendant, appréciez notre sélection de time lapse !

…………………………

+ Retrouvez tous les time lapse présentés sur Lense

+ Notre interview de Vincent Laforet

30 Apr 07:23

Lumiapps: Lytro Camera App “Refocus” lets you choose focus points AFTER taking the picture!

by Jay Montano
Benjamin

ça c'est pratique

MNBwp_ss_20130430_0001

Do you remember when we talked about Lytro, a camera that would allow you to choose your focus points as and when you needed it AFTER you took the shot? It wasn’t something I’d expect coming to a camera phone anytime soon, so colour me surprised when someone made it into an app that actually does work.

You hold the camera still and it ‘records’ several focus points. You can then tap to where you want the focus to be and it will (or should) refocus. You can also press the buttons on the side to change focus points frame by frame. This works as a camera lens app too. I’ve only tested this briefly as I woke up at an inappropriate time this morning (bit ill/feverish) I’ll try and test it out again in the morning. The first image is a stock one.

It’s very quick, taking about a second to take a picture (asking you to hold steady)

MNBwp_ss_20130430_0002

This is my hand and the clock. Tap focus sometimes works well, sometimes you have to rely on the buttons.MNBwp_ss_20130430_0006 MNBwp_ss_20130430_0007

 

The images are maxed at 1280×720.  OK for social sharing I guess.

Basically, I think it uses the fast AF on my 920 to capture several frames at different focus points.

_jpg(2) _jpg(1)

 

Give it a go for free or you can purchase it for just £0.79/$0.99. I’m really liking this app :) .

Name: Refocus

Link: http://www.windowsphone.com/en-us/store/app/refocus/93dddc3e-e895-47bf-bcb2-ff19d7df6533?signin=true

qrcode.13384118

 

Via: WMPU

Cheers Derrek for the tip

17 Apr 08:51

Nokia EOS : CPU quad coeur et capteur PureView ?

Benjamin

Si c'est vrai, il va faire mal

Le futur fleuron des smartphones Nokia, nom de code EOS, se dévoile un peu plus sur la toile. Il est question de processeur quad coeur et d'un APN avec capteur à la résolution singulière.
10 Apr 07:01

Aspect-Oriented Programming in PHP with Go!

by Patkos Csaba

The concept of Aspect-Oriented Programming (AOP) is fairly new to PHP. There’s currently no official AOP support in PHP, but there are some extensions and libraries which implement this feature. In this lesson, we’ll use the Go! PHP library to learn AOP in PHP, and review when it can be helpful.


A Brief History of AOP

Aspect-Oriented programming is like a new gadget for geeks.

The term Aspect-Oriented Programming took shape in the mid-1990s, inside a small group at Xerox Palo Alto Research Center (PARC). AOP was considered controversial in its early days — as is the case with any new and interesting technology — mostly due to its lack of clear definition. The group made the conscious decision to release it in a half-baked form, in order to let the larger community provide feedback. At the heart of the problem was the “Separation of Concerns” concept. AOP was one possible solution to separate concerns.

AOP matured in the late 1990s, when Xerox released AspectJ, and IBM followed suit with their Hyper/J in 2001. Today, AOP is a well-established technology that has been adopted by most common programming languages.


The Basic Vocabulary

At the heart of AOP is the aspect, but before we can define “aspect,” we must discuss two other terms: point-cut and advise. A point-cut represents a moment in our source code, specifying the right moment to run our code. The code that executes at a point-cut is called, advise, and the combination of one or more point-cuts and advises is the aspect.

Typically, each class has one core behavior or concern, but in many situations, a class may exhibit secondary behavior. For example, a class may need to call a logger or notify an observer. Because these functionalities are secondary, their behavior is mostly the same for all the classes that exhibit them. This scenario is called a cross-concern; these can be avoided by using AOP.


The Various AOP Tools for PHP

Chris Peters already discussed the Flow framework for AOP in PHP. Another AOP implementation can be found in the Lithium framework.

Another framework took a different approach, and created a complete PHP extension in C/C++, performing its magic on the same level as the PHP interpreter. It is called the AOP PHP Extension, and I may discuss it in a future article.

But as I noted earlier, for this tutorial, we’ll review the Go! AOP-PHP library.


Installing and Preparing Go!

The Go! library is not an extension; it’s completely written in PHP for PHP 5.4 and higher. Being just a plain PHP library allows for easy deployment, even in restrictive, shared-hosting environments that do not allow you to compile and install your own PHP extensions.

Install Go! with Composer

Composer is the preferred method for installing PHP packages. If you do not have access to Composer, you can always download it from the Go! GitHub repository.

First, add the following lines to your composer.json file.

{
    "require": {
        "lisachenko/go-aop-php": "*"
    }
}

Next, use Composer to install go-aop-php. Run the following command from a terminal:

$ cd /your/project/folder
$ php composer.phar update lisachenko/go-aop-php

Composer will install the required packages and dependencies in just a few seconds. If successful, you should see something similar to the following output:

Loading composer repositories with package information
Updating dependencies
  - Installing doctrine/common (2.3.0)
    Downloading: 100%

  - Installing andrewsville/php-token-reflection (1.3.1)
    Downloading: 100%

  - Installing lisachenko/go-aop-php (0.1.1)
    Downloading: 100%

Writing lock file
Generating autoload files

After the installation has completed, you will find a directory, called vendor, in your source folder. The Go! library and its dependencies are installed there.

$ ls -l ./vendor
total 20
drwxr-xr-x 3 csaba csaba 4096 Feb  2 12:16 andrewsville
-rw-r--r-- 1 csaba csaba  182 Feb  2 12:18 autoload.php
drwxr-xr-x 2 csaba csaba 4096 Feb  2 12:16 composer
drwxr-xr-x 3 csaba csaba 4096 Feb  2 12:16 doctrine
drwxr-xr-x 3 csaba csaba 4096 Feb  2 12:16 lisachenko

$ ls -l ./vendor/lisachenko/
total 4
drwxr-xr-x 5 csaba csaba 4096 Feb  2 12:16 go-aop-php

Integrate Go! Into Our Project

We need to create a call that sits between the routing/entry point of our application. The autoloader then automatically includes the class. Go! refers to this as an Aspect Kernel.

use Go\Core\AspectKernel;
use Go\Core\AspectContainer;

class ApplicationAspectKernel extends AspectKernel {

	protected function configureAop(AspectContainer $container) {

	}

	protected function getApplicationLoaderPath() {

	}

}

Today, AOP is a well-established technology that has been adopted by most common programming languages.

For this example, I’ve created a directory, called Application, and added a new class file, ApplicationAspectKernel.php within it.

Our aspect kernel extends Go!’s abstract AspectKernel class, which provides the basic functionality that the aspect kernel requires to do its job. There are two methods we must implement: configureAop(), which registers our future aspects, and getApplicationLoaderPath(), which provides a string representing the full path to the application’s autoloader.

For now, simply create an empty autoload.php file in your Application directory, and change the getApplicationLoaderPath() method, accordingly.

// [...]
class ApplicationAspectKernel extends AspectKernel {

	// [...]

	protected function getApplicationLoaderPath() {
		return __DIR__ . DIRECTORY_SEPARATOR . 'autoload.php';
	}

}

Don’t worry about autoload.php just yet; we’ll fill in the missing pieces shortly.

When I first installed Go! and reached this point of my process, I felt the need to run some code. So let’s begin building a small application!


Creating A Simple Logger

Our aspect will be a simple logger, but we first need some code to watch before we start with the main portion of our application.

Create A Minimal Application

Our small application will be an electronic broker, capable of buying and selling shares.

class Broker {

	private $name;
	private $id;

	function __construct($name, $id) {
		$this->name = $name;
		$this->id = $id;
	}

	function buy($symbol, $volume, $price) {
		return $volume * $price;
	}

	function sell($symbol, $volume, $price) {
		return $volume * $price;
	}

}

This code is quite simple. The Broker class has two private fields that store the broker’s name and ID.

This class also offers two methods, buy() and sell() for buying and selling shares, respectively. Each of these methods accepts three arguments: the share’s symbol, the number of shares, and the price per share. The sell() method sells the shares and then calculates the total money received. Conversely, the buy() method buys the shares and calculates the total money spent.

Exercise Our Broker

We can easily exercise our Broker by writing a PHPUnit test. Create a directory, called Test inside the Application directory, and, within it, add a new file, BrokerTest.php. Append the following code to that file:

require_once '../Broker.php';

class BrokerTest extends PHPUnit_Framework_TestCase {

	function testBrokerCanBuyShares() {
		$broker = new Broker('John', '1');
		$this->assertEquals(500, $broker->buy('GOOGL', 100, 5));
	}

	function testBrokerCanSellShares() {
		$broker = new Broker('John', '1');
		$this->assertEquals(500, $broker->sell('YAHOO', 50, 10));
	}

}

This test simply checks the return values of the broker’s methods. We can run this test and see that our code is at least syntactically correct.

Add an Auto Loader

Let’s create an autoloader that physically loads the classes that our application needs. This will be a simple loader, based on the PSR-0 autoloader.

ini_set('display_errors', true);

spl_autoload_register(function($originalClassName) {
    $className = ltrim($originalClassName, '\\');
    $fileName  = '';
    $namespace = '';
    if ($lastNsPos = strripos($className, '\\')) {
        $namespace = substr($className, 0, $lastNsPos);
        $className = substr($className, $lastNsPos + 1);
        $fileName  = str_replace('\\', DIRECTORY_SEPARATOR, $namespace) . DIRECTORY_SEPARATOR;
    }
    $fileName .= str_replace('_', DIRECTORY_SEPARATOR, $className) . '.php';

    $resolvedFileName = stream_resolve_include_path($fileName);
    if ($resolvedFileName) {
        require_once $resolvedFileName;
    }
    return (bool) $resolvedFileName;
});

That’s all we need for the autoload.php file. Now, change BrokerTest.php to require the autoloader instead of Broker.php class.

require_once '../autoload.php';

class BrokerTest extends PHPUnit_Framework_TestCase {
	// [...]
}

Running BrokerTest proves that the code still works.

Connecting to Application Aspect Kernel

Our final step is to configure Go!. We need to connect all the components so that they work in harmony. First, create a file, called AspectKernelLoader.php, and add the following code:

include __DIR__ . '/../vendor/lisachenko/go-aop-php/src/Go/Core/AspectKernel.php';
include 'ApplicationAspectKernel.php';

ApplicationAspectKernel::getInstance()->init(array(
    'autoload' => array(
        'Go'               => realpath(__DIR__ . '/../vendor/lisachenko/go-aop-php/src/'),
        'TokenReflection'  => realpath(__DIR__ . '/../vendor/andrewsville/php-token-reflection/'),
        'Doctrine\\Common' => realpath(__DIR__ . '/../vendor/doctrine/common/lib/')
    ),
    'appDir' => __DIR__ . '/../Application',
    'cacheDir' => null,
    'includePaths' => array(),
    'debug' => true
));

We need to connect all the components so that they work in harmony.

This file sits between the front controller and the autoloader. It uses the AOP infrastructure to initialize and call the autoload.php when needed.

In the first line, we explicitly include AspectKernel.php and ApplicationAspectKernel.php. These files must be explicitly included, because, remember, we have no autoloader at this point.

In the following code segment, we call the init() method on the ApplicationAspectKernel object and pass it an array of options:

  • autoload defines the paths to initialize for the AOP library. Adjust the paths according to your directory structure.
  • appDir refers to the application’s directory.
  • cacheDir specifies a cache directory (we’ll ignore this for this tutorial).
  • includePaths represents a filter for the aspects. We want all the specified directories to be watched, so leave this array empty to watch everything.
  • debug provides extra debugging information, which is useful for development, but you should set it to false for deployed applications.

To finalize the connection between the different pieces, find all references to autoload.php in your project and replace them with AspectKernelLoader.php. In our simple example, only the test file requires modification:

require_once '../AspectKernelLoader.php';

class BrokerTest extends PHPUnit_Framework_TestCase {

// [...]

}

For bigger projects, you may find that it’s useful to use bootstrap.php for PHPUnit; the require_once() for autoload.php or our AspectKernelLoader.php should be included there.

Log the Broker’s Methods

Create a file, called BrokerAspect.php, and add the following code:

use Go\Aop\Aspect;
use Go\Aop\Intercept\FieldAccess;
use Go\Aop\Intercept\MethodInvocation;
use Go\Lang\Annotation\After;
use Go\Lang\Annotation\Before;
use Go\Lang\Annotation\Around;
use Go\Lang\Annotation\Pointcut;
use Go\Lang\Annotation\DeclareParents;

class BrokerAspect implements Aspect {

	/**
	 * @param MethodInvocation $invocation Invocation
	 * @Before("execution(public Broker->*(*))") // This is our PointCut
	 */
	public function beforeMethodExecution(MethodInvocation $invocation) {
		echo "Entering method " . $invocation->getMethod()->getName() . "()\n";
	}
}

We begin by specifying several use statements for the AOP infrastructure. Then, we create our aspect class, called BrokerAspect, which must implement Aspect. Next, we specify the matching logic for our aspect:

* @Before("execution(public Broker->*(*))")
  • @Before specifies when to apply the advice. Possibilities are @Before, @After, @Around and @AfterThrowing.
  • "execution(public Broker->*(*))" specifies the matching rule as the execution of any public method on a class, called Broker, with any number of parameters. The syntax is: [operation - execution/access]([method/attribute type - public/protected] [class]->[method/attribute]([params])

Please note that the matching mechanism is admittedly somewhat awkward. You can use only one ‘*‘ (star) in each part of the rule. For example, public Broker-> matches a class, called Broker. public Bro*-> matches any class starting with Bro, and public *ker-> matches any class ending with ker.

public *rok*-> will not match anything; you may not use more than one star for the same match.

The method following the matcher will be called when the event occurs. In our case, the method executes before each call on one of Broker‘s public methods. A parameter, called $invocation (of type MethodInvocation), is automatically passed to our method. This object provides different ways of obtaining information about the called method. In this first example, we use it to obtain the method’s name and print it.

Registering The Aspect

Merely defining an aspect is not enough; we need to register it into the AOP infrastructure. Otherwise, it will not be applied. Edit ApplicationAspectKernel.php and call registerAspect() on the container in the configureAop() method:

use Go\Core\AspectKernel;
use Go\Core\AspectContainer;

class ApplicationAspectKernel extends AspectKernel
{

    protected function getApplicationLoaderPath()
    {
        return __DIR__ . DIRECTORY_SEPARATOR . 'autoload.php';
    }

    protected function configureAop(AspectContainer $container)
    {
        $container->registerAspect(new BrokerAspect());
    }
}

Run the tests and check the output. You should see something similar to the following:

PHPUnit 3.6.11 by Sebastian Bergmann.

.Entering method __construct()
Entering method buy()
.Entering method __construct()
Entering method sell()
Time: 0 seconds, Memory: 5.50Mb

OK (2 tests, 2 assertions)

So we’ve managed to run code whenever something happens on the broker.

Finding Parameters and Matching @After

Let’s add another method to the BrokerAspect.

// [...]
class BrokerAspect implements Aspect {

	// [...]

	/**
	 * @param MethodInvocation $invocation Invocation
	 * @After("execution(public Broker->*(*))")
	 */
	public function afterMethodExecution(MethodInvocation $invocation) {
		echo "Finished executing method " . $invocation->getMethod()->getName() . "()\n";
		echo "with parameters: " . implode(', ', $invocation->getArguments()) . ".\n\n";
	}
}

This method runs after a public method executes (note the @After matcher). We then add another line to output the parameters used to call the method. The output of our test now is:

PHPUnit 3.6.11 by Sebastian Bergmann.

.Entering method __construct()
Finished executing method __construct()
with parameters: John, 1.

Entering method buy()
Finished executing method buy()
with parameters: GOOGL, 100, 5.

.Entering method __construct()
Finished executing method __construct()
with parameters: John, 1.

Entering method sell()
Finished executing method sell()
with parameters: YAHOO, 50, 10.

Time: 0 seconds, Memory: 5.50Mb

OK (2 tests, 2 assertions)

Getting Return Values and Manipulating Execution

So far, we’ve learned how to run extra code before and after a method executes. While this is nice, it’s not overly useful if we can’t see what the methods return. Let’s add another method to the aspect and modify the existing code:

 //[...]
class BrokerAspect implements Aspect {

	/**
	 * @param MethodInvocation $invocation Invocation
	 * @Before("execution(public Broker->*(*))")
	 */
	public function beforeMethodExecution(MethodInvocation $invocation) {
		echo "Entering method " . $invocation->getMethod()->getName() . "()\n";
		echo "with parameters: " . implode(', ', $invocation->getArguments()) . ".\n";
	}

	/**
	 * @param MethodInvocation $invocation Invocation
	 * @After("execution(public Broker->*(*))")
	 */
	public function afterMethodExecution(MethodInvocation $invocation) {
		echo "Finished executing method " . $invocation->getMethod()->getName() . "()\n\n";
	}

	/**
	 * @param MethodInvocation $invocation Invocation
	 * @Around("execution(public Broker->*(*))")
	 */
	public function aroundMethodExecution(MethodInvocation $invocation) {
		$returned = $invocation->proceed();
		echo "method returned: " . $returned . "\n";

		return $returned;
	}

}

Merely defining an aspect is not enough; we need to register it into the AOP infrastructure.

This new code moves the parameter information to the @Before method. We also add another method with the special @Around matcher. This is neat, because the original matched method call is wrapped inside the aroundMethodExecution() function, effectively supressing the original invocation. Inside the advise, we need to call $invocation->proceed(), in order to execute the original call. If you don’t do this, the original call will not occur.

This wrapping also allows us to manipulate the returned value. What we return in our advise is what returns in the original call. In our case, we didn’t change anything, and your output should look like this:

PHPUnit 3.6.11 by Sebastian Bergmann.

.Entering method __construct()
with parameters: John, 1.
method returned:
Finished executing method __construct()

Entering method buy()
with parameters: GOOGL, 100, 5.
method returned: 500
Finished executing method buy()

.Entering method __construct()
with parameters: John, 1.
method returned:
Finished executing method __construct()

Entering method sell()
with parameters: YAHOO, 50, 10.
method returned: 500
Finished executing method sell()

Time: 0 seconds, Memory: 5.75Mb

OK (2 tests, 2 assertions)

Let’s play a little and offer a discount for a specific broker. Return to the test class, and write the following test:

require_once '../AspectKernelLoader.php';

class BrokerTest extends PHPUnit_Framework_TestCase {

	// [...]

	function testBrokerWithId2WillHaveADiscountOnBuyingShares() {
		$broker = new Broker('Finch', '2');
		$this->assertEquals(80, $broker->buy('MS', 10, 10));
	}

}

This will fail with:

Time: 0 seconds, Memory: 6.00Mb

There was 1 failure:

1) BrokerTest::testBrokerWithId2WillHaveADiscountOnBuyingShares
Failed asserting that 100 matches expected 80.

/home/csaba/Personal/Programming/NetTuts/Aspect Oriented Programming in PHP/Source/Application/Test/BrokerTest.php:19
/usr/bin/phpunit:46

FAILURES!
Tests: 3, Assertions: 3, Failures: 1.

Next, we need to modify the broker to provide its ID. Just implement a getId() method, as demonstrated below:

class Broker {

	private $name;
	private $id;

	function __construct($name, $id) {
		$this->name = $name;
		$this->id = $id;
	}

	function getId() {
		return $this->id;
	}

	// [...]

}

Now, modify the aspect to adjust the buying price for a broker with an ID of 2.

 // [...]
class BrokerAspect implements Aspect {

	// [...]

	/**
	 * @param MethodInvocation $invocation Invocation
	 * @Around("execution(public Broker->buy(*))")
	 */
	public function aroundMethodExecution(MethodInvocation $invocation) {
		$returned = $invocation->proceed();
		$broker = $invocation->getThis();

		if ($broker->getId() == 2) return $returned * 0.80;
		return $returned;
	}

}

Instead of adding a new method, just modify the aroundMethodExecution() function. It now only matches methods, called ‘buy‘, and triggers $invocation->getThis(). This effectively returns the original Broker object so that we may execute its code. And so we did! We ask the broker for its ID, and offer a discount if the ID is equal to 2. The test now passes.

PHPUnit 3.6.11 by Sebastian Bergmann.

.Entering method __construct()
with parameters: John, 1.
Finished executing method __construct()

Entering method buy()
with parameters: GOOGL, 100, 5.
Entering method getId()
with parameters: .
Finished executing method getId()

Finished executing method buy()

.Entering method __construct()
with parameters: John, 1.
Finished executing method __construct()

Entering method sell()
with parameters: YAHOO, 50, 10.
Finished executing method sell()

.Entering method __construct()
with parameters: Finch, 2.
Finished executing method __construct()

Entering method buy()
with parameters: MS, 10, 10.
Entering method getId()
with parameters: .
Finished executing method getId()

Finished executing method buy()

Time: 0 seconds, Memory: 5.75Mb

OK (3 tests, 3 assertions)

Matching Exceptions

We can now execute extra code when a method is entered, after it executes and around it. But what if a method throws an exception?

Add a test method to buy a large number of shares:

function testBuyTooMuch() {
	$broker = new Broker('Finch', '2');
	$broker->buy('MS', 10000, 8);
}

Now, create an exception class. We need this because the built-in Exception class cannot be caught by Go! AOP or PHPUnit.

class SpentTooMuchException extends Exception {

	public function __construct($message) {
		parent::__construct($message);
	}

}

Modify the broker to throw an exception for a large value:

class Broker {

	// [...]

	function buy($symbol, $volume, $price) {
		$value = $volume * $price;
		if ($value > 1000)
			throw new SpentTooMuchException(sprintf('You are not allowed to spend that much (%s)', $value));
		return $value;
	}

	// [...]

}

Run the tests and ensure that they fail:

Time: 0 seconds, Memory: 6.00Mb

There was 1 error:

1) BrokerTest::testBuyTooMuch
Exception: You are not allowed to spend that much (80000)

/home/csaba/Personal/Programming/NetTuts/Aspect Oriented Programming in PHP/Source/Application/Broker.php:20
// [...]
/home/csaba/Personal/Programming/NetTuts/Aspect Oriented Programming in PHP/Source/Application/Broker.php:47
/home/csaba/Personal/Programming/NetTuts/Aspect Oriented Programming in PHP/Source/Application/Test/BrokerTest.php:24
/usr/bin/phpunit:46

FAILURES!
Tests: 4, Assertions: 3, Errors: 1.

Now, expect the exception (in the test) and make sure they pass:

class BrokerTest extends PHPUnit_Framework_TestCase {

	// [...]

	/**
     * @expectedException SpentTooMuchException
     */
	function testBuyTooMuch() {
		$broker = new Broker('Finch', '2');
		$broker->buy('MS', 10000, 8);
	}

}

Create a new method in our aspect to match @AfterThrowing, and don’t forget to specify Use Go\Lang\Annotation\AfterThrowing;

 // [...]
Use Go\Lang\Annotation\AfterThrowing;

class BrokerAspect implements Aspect {

	// [...]

	/**
	 * @param MethodInvocation $invocation Invocation
	 * @AfterThrowing("execution(public Broker->buy(*))")
	 */
	public function afterExceptionMethodExecution(MethodInvocation $invocation) {
		echo 'An exception has happened';
	}

}

The @AfterThrowing matcher suppresses the thrown exception and allows you to take your own action. In our code, we simply echo a message, but you may do whatever your application requires.


Final Thoughts

This is why I urge you to use aspects with care.

Aspect oriented programming is like a new gadget for geeks; you can immediately see its great potential. Aspects allows us to introduce extra code in different parts of our system without modifying the original code. This can prove to be immensely helpful, when you need to implement modules that pollute your methods and classes with tightly coupled references and method calls.

This flexibility, however, comes with a price: obscurity. There is no way to tell if an aspect watches a method just by looking at the method or its class. For example, there is no indication in our Broker class that anything happens when its methods execute. This is why I urge you to use aspects with care.

Our use of the aspect to offer a discount for a specific broker is an example of misuse. Refrain from doing that in a real project. A broker discount is related to brokers; so, keep that logic in the Broker class. Aspects should only perform tasks that do not directly relate to the object’s primary behavior.

Have fun with this!

09 Apr 13:06

National Geographic Found : un tumblr pour 125 ans d’archive

by Gaylord
Benjamin

excellent l'histo photo de National Geographic

Sous le nom de Found, National Geographic nous propose un agréable voyage dans le temps à travers la redécouverte de ses archives photos. L’idée est encore à ses balbutiements mais on y retrouve déjà quelques clichés croustillants venus tout droit du passé.

…………………………

Cela fait toujours plaisir de voir une référence du reportage mondial utiliser le numérique pour y répandre son héritage, à travers des photos de qualité d’endroits exotiques, insolites. A retrouver sur National Geographic Found, 125 ans d’archives de  photos, parfois décalées, toujours superbes, via un tumblr entièrement dédié à l’image et à l’échange avec ses utilisateurs. D’où l’objectif secret dévoilé dans la section About : retrouver la date et le lieu de certains clichés sans informations, en comptant sur ses utilisateurs.

Une chance pour nous, des images rares – inédites pour une partie d’entre elles – se sont glissés dans le lot. En voici une sélection ci-dessous :

…………………………

+ National Geographic Found

03 Apr 08:32

Et maintenant, le "choc de sidération"... et que vive Mediapart !

by VIBERT
Benjamin

Faut il vraiment en rajouter, l'article est suffisant !

Après le choc (mou) de la photo de Depardon, après le choc fiscal (glaçant pour l'économie... et vos économies), après le choc de la marinière (ridicule) et même le choc de simplification (pfff...), voici venu le choc de sidération et du mensonge "les yeux dans les yeux" ! Et c'est pour quand l'électrochoc ? 

0000_screencopy_JFV_ 2013-04-02 à 20.07.59

Un évadé fiscal... ministre de la "lutte contre l'évasion ficale" ! Ahah, on ne pouvait pas rêver plus compétant... Il ne manque plus qu'un ministre de l'intérieur, cambrioleur ;-)

Jérôme Cahuzac (blogueur à ses heures) a bien fait d'attendre le 2 avril pour ses aveux (Le Monde), sinon on ne l'aurait peut-être pas cru ;-) Avec des hommes politiques comme ça, la gauche Française n'a vraiment pas besoin d'enemis !

0000_screen_ 2013-04-02 à 21.18.52 copie

D'après-vous ce serait quoi le pire ? Un président de la République complice, qui aurait choisi de couvrir son ministre ? Ou un président totalement naïf, qui se serait laissé berner par un menteur ? C'est obligatoirement l'un des deux... Mais dans les deux cas, les implications sont terribles.

Ce qui risque d'être aussi terrible, ce sera de déterminer l'origine de ce petit million d'Euros qui a transité entre les comptes Suisses et Singapouriens du Ministre.

Enfin, ce qui me fait plaisir ici, c'est que Mediapart (media indépendant), se trouve conforté d'une belle manière. S'il fallait tirer une conclusion de cette lamentable affaire, c'est qu'il est important d'encourager et de soutenir cette nouvelle presse indépendante, dinvestigation. Meilleure garantie de la démocratie...

0000_screencopy_JFV_ 2013-04-02 à 20.28.54

Je vous encourage donc, à défendre vous aussi la liberté de la presse en soutenant Mediapart.fr (surtout vous lecteurs de ce blog, qui êtes photographes ou journalistes). Pour que cette journée serve à quelque chose, testez au moins Mediapart, pour 1 € pendant 15 jours.

 

02 Apr 07:04

How to recover lost data from Nokia N8 or any other smartphone after formatting Memory Card or Mass Storage?

by Admin

Have you ever accidentally formatted your Nokia N8's memory card or mass storage drive? Ever wanted to recover your most important documents, HD videos, high quality pictures, movies which had been removed / formatted by mistake from your Nokia N8 or any other Belle smartphone? We have packed two Windows PC based applications which can help you to recover your lost data from your mobile phone's mass or built in storage and memory card.  Read more »
27 Mar 09:05

Prototyping With Meteor

by Tom Coleman
Benjamin

Great tutos for #Meteor

Meteor is far more than a quick prototyping tool, but it sure is great for prototyping. In this tutorial, we’ll walk through the process of turning a simple HTML wireframe into a functional application in a surprisingly simple number of steps.

We’ll be creating a simple wireframe of a chatroom application. The process we are trying to demonstrate is starting with a pure HTML/CSS wireframe, done in Meteor for convenience, which can then very easily be transformed into a real application, thanks to the ease of Meteor development.

The Meteor Book

Note: This tutorial is adapted from The Meteor Book, an upcoming step by step guide to building Meteor apps from scratch. The book will walk you through building a complete multi-user social news site (think Reddit or Digg), starting from setting up user accounts and user permissions, all the way to managing real-time voting and ranking.


Setting up a More Complex App

A previous Meteor tutorial here on Nettuts+ demonstrated how to install Meteor and build a simple application using the meteor command line tool. In this tutorial, we are going to do things a bit differently, and use Meteorite.

Meteorite is a community created wrapper for Meteor that allows us to use non-core packages created by other members of the Meteor community. Although a built-in third party package system is planned for Meteor itself, as of the time of this writing, there is no support, bar the set of packages that are supported by the Meteor core team. So Meteorite was created to allow us (the community) to work around this limitation, and publish our packages on Atmosphere, the Meteor package repository.

For this tutorial, we are going to use some of those community written packages, so we are going to need to use Meteorite. To begin, let’s get it installed, using npm.

Note: You’ll need to have a copy of Node and npm installed on your system. If you need assistance with this process, Meteorite’s install instructions is a good place to start.

npm install Meteorite -g

If you’re on Windows, setting things up is a bit more complex. We’ve written a detailed tutorial on our site to help you out.

Now that Meteorite is installed, we use the mrt command-line tool (which it installs for us) in place of meteor. So let’s get started! We’ll create an app:

mrt create chat

Packages and Wireframes

To create our wireframe app, we’ll use some basic packages that allow us to develop simple laid out pages quickly and route between them. Let’s add the packages now:

mrt add bootstrap-updated
mrt add font-awesome
mrt add router

Step 1: A Front Page

Now that we’ve picked up some nice styling for our app, we can make a mockup of the landing screen. Delete the initial HTML, CSS and JS files created by Meteor and create the following two files within a client directory (we aren’t doing anything on the server yet).

(Alternatively, follow along with the steps from this repository.)

<head>
  <title>chat</title>
</head>

<body>
  <div class="row">
    {{> rooms}}
    <div class="span6">
      <h1>Welcome to Meteor Chat</h1>
      <p>Please a select a room to chat in, or create a new one</p>
    </div>
  </div>
</body>

<template name="rooms">
  <form name="new_row">
    <table id="rooms" class="table table-striped span6">
      <thead>
        <tr>
          <th>Room Name</th>
          <th>Members online</th>
          <th>Last activity</th>
        </tr>
      </thead>
        <tbody>
        {{#each rooms}}
          <tr>
            <td>{{name}}</td>
            <td>{{members}}</td>
            <td>{{last_activity}}</td>
          </tr>
        {{/each}}
        <tr>
          <td colspan="3">
            <input type="text" name="name" placeholder="Enter your chatroom name"></input>
            <button type="submit" class="btn btn-primary pull-right">
              <i class="icon-plus"></i> Create Room
            </button>
          </td>
        </tr>
      </tbody>
    </table>
  </form>
</template>

client/chat.html

var rooms = [
  {name: 'Meteor Talk', members: 3, last<em>activity: '1 minute ago'},
  {name: 'Meteor Development', members: 2, last</em>activity: '5 minutes ago'},
  {name: 'Meteor Core', members: 0, last_activity: '3 days ago'}
];

Template.rooms.helpers({
  rooms: rooms
});

client/chat.js

After adding this, you should see the following simple (if fake) application, when you browse to http://localhost:3000:

The data in the table of rooms is fixed data that we have manually entered into client/chat.js, but the advantage to this approach is that it allows us to repeat HTML in our wireframe without having to cut and paste (which is almost universally a bad idea).


Step 2: A Chat Room Page

Now, let’s hook up a second page. We are going to use the router to select between two page templates; one with the welcome message, and the other with a message list for the selected room.

Let’s start by adding some simple routes. The Router works by mapping URLs to template names. Our case is fairly simple; here’s what we add:

Meteor.Router.add({
  '/': 'home',
  '/rooms/:id': 'room'
});

client/chat.js

<body>
  <div class="row">
    {{> rooms}}
    {{renderPage}}
  </div>
</body>

<template name="home">
  <div class="span6">
    <h1>Welcome to Meteor Chat</h1>
    <p>Please a select a room to chat in, or create a new one</p>
  </div>
</template>

client/chat.html

We use the {{renderPage}} helper in our HTML file to indicate where we want that selected template to draw, and, just like that, we can browse between the two URLs and see the content on the right-hand side change. By default, we see the 'home' template, which is mapped to the route /, and shows us a nice message.

If we add a template from the 'room' route and add some links to specific rooms, we can now follow links:

<td><a href="/rooms/7">{{name}}</a></td>

client/chat.html ‘rooms’ template

<template name="room">
  <div class="span6">
    <h1>Welcome to a chatroom!</h1>
  </div>
</template>

client/chat.html

This works because the router maps urls, like localhost:3000/rooms/7, to the 'room' template. For now, we won’t look at the id (7, in this case), but we will soon!


Step 3: Putting Some Data in the Chat Room

Now that we’ve routed a URL chatroom, let’s actually draw a chat in the room. Again, we are still mocking up, so we’ll continue to create fake data in our JavaScript file, and draw it with Handlebars:

var rooms = [
  {name: 'Meteor Talk', members: 3, last<em>activity: '1 minute ago',
    messages: [
      {author: 'Tom', text: 'Hi there Sacha!'},
      {author: 'Sacha', text: 'Hey Tom, how are you?'},
      {author: 'Tom', text: 'Good thanks!'},
    ]},
  {name: 'Meteor Development', members: 2, last</em>activity: '5 minutes ago'},
  {name: 'Meteor Core', members: 0, last_activity: '3 days ago'}
];

Template.room.helpers({
  room: rooms[0]
});

client/chat.js

So we’ve added some chat data to the first room, and we’ll simply render it every time (for the moment) on the room template. So:

<template name="room">
  <div class="span6">
    {{#with room}}
      <h1>Welcome to {{name}}</h1></p>
      <table id="chat" class="table table-striped">
        <tbody>
          {{#each messages}}
            <tr>
              <td>{{author}} :</td>
              <td>{{text}}</td>
            </tr>
          {{/each}}
          <tr>
            <td colspan="2">
              <form name="new_message">
                <input type="text" name="text"></input>
                <button type="submit" class="btn btn-primary pull-right">
                  <i class="icon-envelope"></i> Send message
                </button>
              </form>
            </td>
          </tr>
        </tbody>
      </table>
    {{/with}}
  </div>
</template>

client/chat.html

Voila! A working demonstration of our chatroom application:


Step 4: Using Real Data Backed by a Collection

Now comes the fun part; we’ve built a simple wireframe of static data simply enough, but thanks to the power of Meteor Collections, we can make it functional in no time at all.

Remember that a Collection takes care of syncing data between the browser and the server, writing that data to a Mongo database on the server, and distributing it to all other connected clients. This sounds like exactly what we need for a chat room!

First, let’s add a collection on the client and server, and add some simple fixture data to it:

(Note: We’ll put the collections file in the lib/ directory, so that the code is available both on the client and the server.)

var Rooms = new Meteor.Collection('rooms');

if (Meteor.isServer && Rooms.find().count() == 0) {
  var rooms = [
    {name: 'Meteor Talk', members: 3, last<em>activity: '1 minute ago',
      messages: [
        {author: 'Tom', text: 'Hi there Sacha!'},
        {author: 'Sacha', text: 'Hey Tom, how are you?'},
        {author: 'Tom', text: 'Good thanks!'},
      ]},
    {name: 'Meteor Development', members: 2, last</em>activity: '5 minutes ago'},
    {name: 'Meteor Core', members: 0, last_activity: '3 days ago'}
  ];
  _.each(rooms, function(room) {
    Rooms.insert(room);
  });
}  

lib/collections.js

We’ve moved our data into the collection, so we no longer need to manually wire it up within our template helpers. Instead, we can simply grab what we want out of the collection:

Meteor.Router.add({
  '/': 'home',
  '/rooms/:id': function(id) {
    Session.set('currentRoomId', id);
    return 'room'
  }
});

Template.rooms.helpers({
  rooms: function() { return Rooms.find(); }
});

Template.room.helpers({
  room: function() { return Rooms.findOne(Session.get('currentRoomId')); }
})

client/chat.js

We’ve made a couple of changes here; Firstly, we use Rooms.find() to select all rooms to pass into the 'rooms' template. Secondly, in the 'room' template, we just select the single room that we are interested in (Rooms.findOne()), using the session to pass through the correct id.

Hold on! What’s the session? How did we pass the id? The session is Meteor’s global store of application state. The contents of the session should contain all that Meteor needs to know in order to re-draw the application in exactly the same state as it is in right now.

One of the primary purposes of the router is to get the session into such a state when parsing URLs. For this reason, we can provide routing functions as endpoints for URLs; and we use those functions to set session variables based on the content of the URL. In our case, the only state our app requires is which room we are currently in – which we parse out of the URL and store in the 'currentRoomId' session variable. And it works!

Finally, we need to get our links right; so we can do:

<td><a href="/rooms/{{_id}}">{{name}}</a></td>

client/chat.html

Modifying the data

Now that we have a collection holding our room data, we can begin changing it as we see fit. We can add new chats to a room, like so:

Rooms.update(Session.get('currentRoomId'), {$push: {messages: {author: 'Sacha', text: 'Good to hear..'}}});

Or, we can even add a new room:

Rooms.insert({name: 'A New Room', members: 0, last_activity: 'Never'});

The next challenge is to wire up the forms to perform such transformations, which we’ll leave as an exercise to the reader (or perhaps the next tutorial)!

If you’d like to learn more about Meteor, be sure to check out our upcoming book!

26 Mar 07:36

New Qt-based Game Engine for mobile Games – great benefits for Nokia Developers #Symbian #MeeGo

by Jay Montano

Screen Shot 2013-03-25 at 16.59.48We got an email from Austria based Chris and their Qt based cross-engine platform at V-play. More info available at www.v-play.net.

Hi Jay

I am Chris from “V-Play” and a long-term reader of you blog, as I am a Nokia Developer myself.

“V-Play” (a developer-studio from Vienna) just launched a new qt-based game engine, that comes with many benefits for Nokia Developers.
The Game Engine is cross-platform and allows to develop in a declarative way for Symbian and MeeGo as well as all major platforms.
With “V-Play” it is possible to deploy games with just one click on every desired platform and therefore publish it in the app stores.
That makes “V-Play” a great choice for every Nokia-Developer who wants to transfer his mobile game to another platform (e.g. iOS, Androis) easily.

The Game Engine comes with further new features, such as an integreted level-editor that allows developers to simply integrate it into every game and therefore offers every gamer the possibility to create own levels on their devices.

For further information please take a look at the attached press release or visit our homepage: www.v-play.net
I will be happy to assist you with any further questions, requests or suggestions you might have. I will be very pleased about any feedback.
Or maybe you see the possibility to let us write a guest-article, as I think the “V-Play” game engine is a great tool for every Nokia Developer.

 

Best regards from cold Austria :)

 

Christian

 

20 Mar 14:12

Faites le plein de « selfie » à la Saatchi Gallery

by Gaylord
Benjamin

Vive les gros médias, et après y sont pas content que les gens telecharge tout et n'importe quoi, mais ils font pareils (l'UMP s'est aussi fait goler à l'époque de Sarkozy)

Justin Bieber, Obama et Kim Kardashian, le selfie a gagné la sphère people. Jusqu’au 6 septembre, la Saatchi Gallery présente From Selfie To Self-Expression, une exposition historique et participative autour de la nouvelle pratique tendance. Voici un évènement, organisé en partenariat avec Huawei, qui prouve que la cohabitation entre l’art et l’univers technologique fonctionne. (Photo d’ouverture : Jellyfish Selfie © Cinzia Osele Bismarck)

Politiciens participant à un sommet, femmes dans leurs bains, astronautes dans l’espace : tout le monde pratique le selfieFrom Selfie To Self-Expression nous propose un jeu de regards de Parmigianino et Velázquez jusqu’à nos jours. La peinture et le smartphone se rencontrent dès la première salle. De grands chefs d’œuvres sont reproduits sur écran. Devant nos yeux : l’Autoportrait de Vincent Van Gogh réalisé en 1889. Ou plutôt, un écran semblable à l’interface d’Instagram. Nous likons immédiatement.

La star de cette première salle est sans aucun doute l’artiste Mexicaine Frida Kahlo. Oui, ses autoportraits colorés font le buzz. Comment dresser l’historique de la self-expression (ndlr, en français, l’expression de soi) sans aborder les peintres pratiquant l’autoportrait ? Car aucun modèle ne fait le poids face au reflet de l’artiste. Les images des photographes et utilisateurs de smartphones le prouvent.

Big Self-Portrait © Chuck Close, courtesy Pace Gallery
Big Self-Portrait © Chuck Close, courtesy Pace Gallery

Les trois coups de cœur de Lense

Buzz, situations extrêmes ou humour, tous les prétextes sont bons pour s’essayer au selfie. De notre expérience selfie, nous avons retenu le nom de trois photographes.

Chuck Close et son majestueux Big Self-Portrait rétroéclairé a retenu notre attention. Face à nous, un homme à l’air désinvolte, une cigarette au coin de la bouche, nous regarde. 50 ans après, le peintre-photographe parvient toujours à nous interpeller. « Hey, remarquez ma peinture, remarquez-moi », ses mots résonnent encore.

Alison Jackson et ses faux selfie de la famille royale ont déjà fait couler beaucoup d’encre. Pas étonnant. Ses modèles sont de vrais sosies. Petit selfie en famille par la Reine Elisabeth ou l’accouchement immortalisé par le couple princier. Tous les moyens sont bons pour immortaliser le quotidien des célébrités.

En 2014, l’image de Derrek Barlow avait créé le buzz sur la toile. C’est au cours de la Great Bull Run, vers Houston qu’il photographie un homme se faisant poursuivre par un taureau tout en se prenant en selfie. Exploit ? Souvenir indispensable ? Ego surdimensionné ? Le selfie a le mérite de délier les langues.

Un élément est certain, From Selfie To Self-Expression aborde l’histoire de la self-expression de façon très ludique. Une envie de voir et de pratiquer le selfie ? Vous avez jusqu’au 6 novembre pour découvrir From Selfie To Self-Expression.

Trois autres œuvres de l’exposition

Infos pratiques

Saatchi Gallery
Duke of York’s HQ, King’s Rd, Chelsea,
London SW3 4RY, Royaume-Uni
Jusqu’au 6 septembre 2017.

Plus d’informations sur le site Internet de la Saatchi Gallery.

Retrouvez tous les événements sur l’Agenda de Lense

Cet article Faites le plein de « selfie » à la Saatchi Gallery est apparu en premier sur Lense.