[AngularJs + Php MYSQL ] Une table Html infinite scroll simple, sur base de donnée

angularjsphp_1_

Introduction


Avec Angularjs 1.6 , on ne télécharge pas tout un modèle de données lorsqu’il est très grand. Par exemple, pour, afficher toute une table de log de 150 MO, évidemment, on ne charge pas toute la table d’un seul coup dans la mémoire vive, ce serait bien trop couteux. Dans d’autres cas, dans le cadre d’une vue spéciale dans une application, on peut envisager de télécharger tout le modèle de données ( Par exemple, 500 utilisateurs)

L’idée de l’infinite Scroll sur base de donnée


L’idée étant d’afficher les 20 premiers enregistrements de la table, puis ensuite, lorsque l’on atteints le bas de la page, charger les 20 suivants, puis ainsi de suite, de cette manière, l’utilisateur a la sensation d’être en temps réel.

Le problème


Le problème vient lorsque l’on commence à utiliser des filtres dans le Back End, en effet, cela complique le système car les enregistrements arrivent alors dans le désordre, et nous verront cela dans une seconde partie.

Petit Rappel de l’architecture MVC de AngularJs 1.6 ( != Angular 5) :


file-page1.jpg

UNE IDEE DE LINFINITE SCROLL EN ACTION :

infitie.jpg

PHASE 1 Le code pour une table auto incrémentale, dont aucun enregistrement n’a jamais été supprimé

LA VUE HTML

On commence à créer la table dans la vue comme ceci :

<table class="table table-hover sttable table-responsive table-bordered ">
   <thead>
      <th>Id</th>
      <th>identifiant principal</th>
      <th>sessionId</th>
      <th>ip</th>
      <th>message</th>
      <th>timestamp</th>
      <th>url</th>
      <th>data</th>
      </tr>
   </thead>
   <tbody>
      <tr ng-repeat="row in logs track by $index">
         <td>{{::row.id}}</td>
         <td>{{::row.identifiantP}}</td>
         <td>{{::row.sessionId}}</td>
         <td>{{::row.ip}}</td>
         <td>{{::row.message}}</td>
         <td>{{::row.timestamp}}</td>
         <td>{{::row.url}}</td>
         <td>{{::row.data}}</td>
      </tr>
   </tbody>
</table>

Notes :

  • Remarquer qu’il faut ajouter ‘track by $index’ au ng-repeat pour que cela fonctionne.
  • Les :: sont utiles pour debinder afin de récupérer de la mémoire, en effet, pas besoin de 2 ways binding dans un simple reporting.

Ensuite , dans mon controleur ANGULARJS 1.6, je tape les instructions suivantes :

var startRowId = 0;
$scope.read_logs = function() {

    $http.post(wsUrl, {
            read_logs: JSON.stringify({
                'startRowId': startRowId
            })
        })
        .then(function(data) {

            if (startRowId == 0) {
                $scope.logs = data.data;
            }

            if (startRowId >= 20) {

                angular.forEach(data.data, function(obj) {
                    $scope.logs.push(obj);
                })

            }

        })

}

$scope.read_logs();

angular.element($window).bind("scroll", function() {
    var windowHeight = "innerHeight" in window ? window.innerHeight : document.documentElement.offsetHeight;
    var body = document.body,
        html = document.documentElement;
    var docHeight = Math.max(body.scrollHeight, body.offsetHeight, html.clientHeight, html.scrollHeight, html.offsetHeight);
    windowBottom = windowHeight + window.pageYOffset;
    if (windowBottom >= docHeight) {
        startRowId += 20;
        $scope.read_logs();
    }
});

Explication :

  • startRowId est la valeur de la première ligne de notre tableau et dans la table SQL simultanément (C’est ‘synchro’).
  • $scope.read_logs() est la fonction qui lit et récupère en AJAX le tableau json habituel, si startRowId est = à 0 alors, il crée tout simplement les données dans la table HTML, par contre, si startRowId >= 20, alors il sait qu’il doit AJOUTER(push) au modèle de données les données qui arrivent, et qui sont forcément les 20 suivantes dans la table logs !.
  • angular.element($window).bind(« scroll », function() est la function qui détecte quand on arrive à la fin de la page, et exécute de nouveau $scope.read_logs() tout en incrémentant startRowId de 20 , de manière à dire au back end : ‘Lit moi les 20 suivants ‘
  • angular.forEach lui ajoute au tableau d’objet JSON $scope.logs les nouveaux objets récupérés.

Le Back End qui traite la requête SQL :

// Le web Service
if(!empty($_POST["read_logs"]) AND $_SESSION['auth']) {

	$json = $_POST["read_logs"];;
	$data = json_decode($json);
	echo json_encode($db->read_logs($data),JSON_NUMERIC_CHECK); // Renvoie le tableau JSON
} 

 //~ La fonction, normalement située dans une Classe PHP, je ne peux pas tout mettre ..
 public function read_logs($data) {
     $sql = " SELECT * FROM Log ";
     if ($data - > startRowId) {
         $sql. = " WHERE id >= ".$data - > startRowId;
     }

     $sql. = " LIMIT 20";

     $responseArray = array();
     if ($result = $this - > conn2 - > query($sql)) {
         while ($obj = $result - > fetch_object()) {
             array_push($responseArray, $obj);
         }
         mysqli_free_result($result); // Free result set
     }
     mysqli_close($this - > conn2);
     return $responseArray;
 }

Explication : Si le back end reçois la variable startRowId, alors il crée la requête SQL en conséquence, à chaque fois donc que l’on atteint la fin de la page…

Conclusion :

Voilà , on a un infinite scroll qui fonctionne seulement sur une table auto incrémentale et ou aucun enregistrement n’aura été supprimé.

Cependant, comment faire si l’on veut ajouter des filtres simultanés dans la requête SQL Back End , ou si on a supprimé des lignes (row) dans notre table SQL, du coup l’id auto increment ne respecte plus le n+1 ? Cela complique bien, puisque les ‘rows’ lignes n’arrivent pas forcément dans l’ordre…
C’est ce que nous allons analyser et voir dans la seconde partie.

PHASE 2 Le code pour une table auto incrémentale, dont des enregistrements ont été supprimés

ON voit que si l’on supprime 3 enregistrements au début de notre table SQL, par exemple eux qui ont respectivement les ids 3,4 et 5 , notre script de la phase 1 ne fonctionne plus correctement, et veut toujout nous afficher le slignes à partir de l’id 20 , puis de l’id 40 puis de l’id 60 etc …. Pourquoi ? et bien c’est à cause du ’20’ statique qui est ajouté à chaque fois dans le WHERE de la requête SQL et qui fausse alors notre résultat, si les 20 premiers résultats ne sont pas une suite en n+1 !

La solution est donc de passer l’id du dernier enregistrement acquis par le front endà notre requête SQL en lieu et place du chiffre statique (20 ou 40 ou 60 etc ..), afin qu’elle ne plante jamais ! Autrement dit, à chaque fois qu’une nouvelle page s’affiche, je récupère l’ID de la dernière ligne affichée, puis l’envoie au back end, qui lui, reconstitue la requête avec le dernièr ID obtenu (PAr exemple 23), puis renvoie les 20 prochaines données !

On modifie le code en conséquence :

Le controleur

var startRowId = 0;
$scope.read_logs = function() {

    $http.post(wsUrl, {
            read_logs: JSON.stringify({
                'startRowId': startRowId
            })
        })
        .then(function(data) {

            if (startRowId == 0) {
                $scope.logs = data.data;
            }

            if (startRowId != 0) {

                angular.forEach(data.data, function(obj) {
                    $scope.logs.push(obj);
                })

            }

        })

}

$scope.read_logs();

angular.element($window).bind("scroll", function() {
    var windowHeight = "innerHeight" in window ? window.innerHeight : document.documentElement.offsetHeight;
    var body = document.body,
        html = document.documentElement;
    var docHeight = Math.max(body.scrollHeight, body.offsetHeight, html.clientHeight, html.scrollHeight, html.offsetHeight);
    windowBottom = windowHeight + window.pageYOffset;
    if (windowBottom >= docHeight) {
       startRowId = $scope.hk_logs[$scope.hk_logs.length - 1].id;
       $scope.read_hk_logs();
    }
});

Explication : On récupère lorsqu’on a scrollé l’id de la dernière ligne affichée dans le tableau, afin de l’envoyer à la requête SQL

Phase 3 : Mais moi je veux utiliser des filtres aussi, quand je fais de l’infinite Scroll !

En fait, maintenant que l’on a résolu le problème de la dernière ligne (Qu’on aurait également pu traiter dans le back end directement), Ajouter des filtres est plutôt facile, il faut ajouter un select dans le front end, contenant les critères de filtres, puis, envoyer le critère au back end qui l’ajoute à la fin de la requête SQL, dans un WHERE :

Ma requête $http.post envoie désormais des filtres (dans le front end):


$http.post(wsUrl, {
read_logs: JSON.stringify({
'startRowId': startRowId,
'start_month_date': $scope.start_month_date,
'start_year_date': $scope.start_year_date,
'kitIdFilter': $scope.kitIdFilter,
'hkmessageFilter':$scope.hkmessageFilter,
'hkIpFilter':$scope.hkIpFilter
})
})

Puis, mon back end crée la requête SQL en conséquence :

 //~ Read LOGS
    public function read_logs($data)

    {
        $sql  = " SELECT * FROM Log WHERE 1=1";

		if($data->startRowId){

			$sql .= " AND id >= ".$data->startRowId ;
		} 

		if ($data->start_month_date) {

            $sql .= " AND MONTH(timestamp) = '" . $data->start_month_date . "'";
        }
        if ($data->start_year_date)  {

            $sql .= " AND YEAR(timestamp) = '" . $data->start_year_date . "'";
        }

		 if ($data->homekitIdFilter)  {

            $sql .= " AND kitId = '" . $data-><span 				data-mce-type="bookmark" 				id="mce_SELREST_start" 				data-mce-style="overflow:hidden;line-height:0" 				style="overflow:hidden;line-height:0" 			></span>kitIdFilter . "'";
        }

         if ($data->hkmessageFilter)  {

            $sql .= " AND message = '" . $data->hkmessageFilter . "'";
        }

        if ($data->hkIpFilter)  {

            $sql .= " AND ip = '" . $data->hkIpFilter . "'";
        }

		$sql.= " LIMIT 20";

        $responseArray = array();
        if ($result = $this->conn2->query($sql)) {
            while ($obj = $result->fetch_object()) {
                array_push($responseArray, $obj);
            }
            mysqli_free_result($result); // Free result set
        }
         mysqli_close($this->conn2);
        return $responseArray;
    }
Publicités

[AngularJs + Php-SQL] Astuce : Copier-Coller des CRUDS pour aller plus vite.

angularjsphp_1_logo-mysql-170x170_400x400

Introduction


Dans les applications informatique, le CRUD revient tout le temps.

Il s’agit de faire de la Creation/Lecture/Mise à jour/Suppression.

L’idée est donc de faire du copié-collé d’un crud standard, puis de changer uniquement le nom du modèle de données, en faisant « controle+h » dans notepad, afin d’aller beaucoup plus vite.

Note : Java Hibernate permettrait de faire cela encore plus simplement( méthode comin’ soon ), sans compter les méthodes de création automatiques des POJO, mais ce n’est pas le sujet de ce post … Là on est sur du back end PHP-MYSQL

Un exemple en temps réel dans une App !


Dans mon application RdvJuristes, j’ai un Crud sur les personnes :

http://nicolash.org/rdvj/index.html#/personnes

crd1.jpg

 

Il est évident que je ne vais pas me retaper tout le code pour créer un CRUD sur les juristes :

http://nicolash.org/rdvj/index.html#/juristes

crd2.jpg

On comprends qu’on a affaire à 2 modèles de données relativement similaires, que l’on peut copier-coller, puis, ensuite adapter à notre convenance.

Lire la suite

[HighCharts] Elaborer une statistique simple avec High Charts dans une application SAAS.

highcharts-logo

Introduction


Dans l’application RdvJuristes, je décide de calculer la somme des notes de frais de tous les rendez vous de la semaine en cours, puis de les afficher dans un graphique High Charts en barres.

Technologie utilisée


  • Highcharts
  • Php-Mysql en technologie PDO pour le back end
  • AngularJs pour le front end

Ordonnancement


  1. Examiner la conception de la base de donnée relationnelle.
  2. Elaborer la requête SQL
  3. Concevoir le Back End
  4. Concevoir le Front End
  5. Tester.

Lire la suite

[Java + AngularJS] Une application de gestion d’élèves partagée avec Eclipse, AngularJs et Java,Jersey,Maven + Mysql en Back end. Un Français Intégral pour ce système CRUD à Services WEB!

maisonSommaire


  • Introduction
  • Une photo de la micro application
  • Le but de l’application
  • Le matériel nécessaire
  • Les liens utiles en Anglais
  • On crée le projet dans Eclipse
  • On construit le Front End
  • On crée notre table SQL  » eleves »
  • On crée notre classe Pojo « eleve »
  • On construit la classe Back End des Web Services CRUD (Lire, Créer, Editer, Supprimer)
  • On construit la classe Back End DAO(Data Access Object) qui actionne MYSQL
  • On construit la classe connexion qui permet la connexion à la base  de données.
  • On teste l’application
  • Points non traités dans cette doc.
  • Conclusion .

Introduction javalogo-mysql-170x170_400x400angularjs


Vous l’attendiez depuis longtemps, voici enfin une micro-application CRUD (Lire, Créer, Editer, Supprimer) totalement exposée, en Français intégral, combinant  Angularjs en Front End, et Java en Back end, le tout pointant sur une base de données relationelle  Mysql.

L’autre nom utilisé pour cette technologie Back end serveur est « Service Web » ou « Web Services » en Anglais.

Elaborée suite à l’analyse de plusieurs forums en Anglais, cette solution entièrement Francophone est simple et robuste et s’ajoute aux solutions Full Stack AngularJs + Php Sql(Le système le plus fiable et clair) ainsi que Angularjs + noSql

Avec cette solution, on bénéficie d’une part de l’organisation très structurée de Java pour le Back End avec les classes, et d’autre part  de la facilité d’AngularJS ( Avec par exemple le Super 2 ways binding et la multitude de librairies Front end de AngularJs pour le front end).

Java étant très utilisé dans l’embarqué, cette technique permet une communication optimisée entre le navigateur et divers matériels (Domotique, robotique etc …)

Ceci nous donne un couple gagnant pour les applications à sgbd relationels. AngularJs étant d’une flexibilité et d’une simplicité extrême. Aucune limitation dans ce système, Jointures SQL, librairiesde type NVD3.js pour les graphes, Bootstrap pour les CSS, Elaboration de Statistiques  et j’en passe !

exp Comme d’habitude, j’utilise les mots les plus simples ainsi que l’état initial des choses pour expliquer le fonctionnement de cette micro application, cependant, les concepts sont ensuite expandables à l’infini pour de grosses applications complexes.

Il faut rappeler qu’un CRUD se doit d’être réduit à sa plus simple expression lorsqu’il est expliqué, ainsi qu’à ses 4 fonctions primaires :

Lire, Créer, Editer, Supprimer.

Une photo de la micro application


 microapp.jpg

Lire la suite

#7f4614, #a65b1a, #bf691e, #d9cfb8, #f0e5cc, #fff, #ffffff

[AngularJs + Php] Organiser un système automatique d’Emailing dans une application.

angularjslogo-php

Introduction


Dans ce post, je décris mes 2 méthodes pour faire de l’EMAILING avec AngularJs en front end et PHP en back end, attention je ne prétends pas que cela soit les solutions les meilleures, néanmoins je les ait testées fonctionnelles.

C’est assez compliqué à expliquer et je ne prétends pas faire une procédure bien structurée, mais juste un pense bête qui peut inspirer …

email-logo.png

L’Emailing permet d’envoyer un email personnalisé à tous les utilisateurs d’une application ;ou à certains groupes d’utilisateurs d’une application, qui auront été filtré sur la base d’un critère au préalable .

Certains systèmes peuvent être très simples, d’autres très complexes au niveau des critères.

Voici un exemple typique du besoin de faire de l’emailing dans les applications WEB modernes :

‘ Mince le prof de maths est absent demain, il faut que j’envoie un Email à tous les élèves du cours de maths pour qu’ils sachent que demain, il ne sera pas là, vite, je vais dans mon application WEB pour le faire !’

Sommaire :


  1. Technologies employées.
  2. La méthode naïve: faire une boucle dans le Front end.
  3. Filtrer les étudiants à emailer en fonction d’un critère …
  4. La méthode sure: faire une boucle  dans le Back End.
  5. Permettre d’ajouter une pièce jointe à l’emailing.

1. Technologies employées :



  • Le framework angularJs 1.5  pour le front end.
  • Php 7.0 pour gérer notre back-end (C’est le langage Serveur).
  • La librairie phpmailer (A télécharger !), qui va permettre à notre serveur d’envoyer les Emails.
  • Les données sont échangées au format JSON entre le front end et le back end, ce sont des tableaux d’objets JSON normalisés ou alors un objet json unique (En l’occurence : Email destinataire (data.email) et contenu du formulaire ($scope.formData) pour l’exemple 2.)
  • Pour commencer, on peut déjà se baser sur ce très bon tuto en Anglais pour envoyer un seul EMAIL avec la technologie AngularJS/Php

Lire la suite

[Théorie] Créer des applications mobiles françaises avec l’Api du WebRtc , utiliser la cam, le micro, le gps etc … Et piloter des robots

IntroductionFDS_371236.jpg


De nos jours, il n’est pas rare de devoir créer des applications françaises mixtes tournant sur des ordis de bureau et sur des machines mobiles (Tablettes, Téléphones tournant sous Android ou AppleIOS).

On peut désormais se servir des APIS HTML 5.0 du WebRtc  pour accéder directement aux mécanismes (DEVICES) des téléphones et tablettes mobiles ! (Voir les exemples)

Sur cette bonne page, on peut voir d’autres exemples utilisant le sensor par exemple.

Du coup, il n’y a plus besoin d’installer la librairie PhoneGap ou Cordova, couteuse en temps de chargement et en taille.

Il est donc possible d’élaborer des applications complexes avec par exemple un codeBar Scanner(Ce que je vais faire ces jours ci), un microphone et de la capture vidéo, sans se farcir la complexité de Java  ( Que je pratique aussi, par gout pour la prog objet et par goût pour UML2.0), c’est  vraiment la fête.

Une autre chose à savoir est que les derniers CSS bootstrap 3.0 ont vraiment de superbes aptitudes à s’auto-adapter sur desktop et mobile(Ils ont poussé le responsive design à fond) .

Note : Il est également possible d’utiliser la librairie ngCordova avec Ionic afin d’accéder à toutes les fonctionnalités des appareils mobile ( Photographie, Microphone, Code Bar scanner, envoi de Sms, Position GPS) avec une syntaxe plus facile en AngularJs… Par contre, une fois que l’application est finalisée, il faut la compiler, et ça, on ne veut pas le faire dans le cas présent, ce n’est pas le sujet du post, nous ce qu’on veut, c’est accéder aux fonctionnalités du mobile directement en HTML5.0 et en Javascript, sans avoir à compiler et faire des trucs qui vont nous faire perdre un peu de temps  .

I9300-Smartphone-telephone-portable-3G-Dual-core-1.0-GHz-MTK6575-Android-4.0-mobile-ecran-tactile-capacitif-4.7-pouces-Dual-sim-et-Dual-camera-007

Sommaire :


  • Les normes du W3c « Media Capture and Streams ».
  • Le WebRTC.
  • Le Mozilla Developper Network .
  • La nouvelle tendance à n’autoriser que le HTTPS .
  • Problèmes de version de MediaDevices.getUserMedia()
    1.  Exemple de code de Géolocalisation mixte Desktop Mobile
    2.  Exemple de prise de photo sur Firefox dans un mobile Samsung 5 pouces Galaxy
    3. Exemple de scan de Code bars en Html 5.0 avec quaggaJS (https://serratus.github.io/quaggaJS/).
    4. Exemple de détection de visage et de mouvements
    5. Piloter un bras robotisé avec Javascript : les pistes.
    6. Que faire avec un lecteur de cartes au format bancaire et js?

 

 

télécharger

Les normes du W3c « Media Capture and Streams ».


Les normes webRtc sont définies et mises à jour sur le site suivant : https://www.w3.org/TR/mediacapture-streams/

 

webrtc-logo-vert-retro-255x305.png

Le WebRtc


Il existe déjà depuis un certains temps … et permet aussi de faire du peer to peer(échange de fichiers d’ordi à ordi) plus facilement avec des libs comme http://peerjs.com.

https://reep.io permet également le transfert d’ordi à ordi.

 

Mozilla_Developer_Network

Le Mozilla Developper Network .


Lié au navigateur Firefox, il décrit l’api et la manière d’accéder aux mécanismes(devices) des mobiles. Il récapitule les instructions dépréciées, c’est pour ça que certains codes ne fonctionnent plus parfois, parce que l’instruction de l’api est dépréciée, il ne faut pas s’affoler pour cela, parce que webRtc est encore en cours d’élaboration, et consulter ce site.

 

La nouvelle tendance à n’autoriser que le HTTPS .

Attention Chrome n’autorise plus que la connexion HTTPS pour bénéficier de la caméra sur les mobiles.

Problèmes de version de MediaDevices.getUserMedia()


C’est le nouveau format de l’instruction d’accès aux mécanismes des mobiles.

Avant, la syntaxe était la suivante: Navigator.getUserMedia()

Firefox est rétro-compatible, mais pas Chrome. On peut voir que l’ancienne syntaxe est dépréciée à cette adresse : https://developer.mozilla.org/en-US/docs/Web/API/Navigator/getUserMedia

De ce fait, il ne faut pas s’étonner que certaines anciennes briques de codes de passent plus dans Chrome, mais dans Firefox.

 

 

 

comment-ne-pas-se-faire-geolocaliser-via-les-applications_5194315

Exemple de code de Géolocalisation mixte Desktop Mobile (Cliquer pour tester)


Ce code a été testé avec succès sur un mobile Samsung Galaxy Grand Plus, sur l’émulateur opéra et sur un ordi de bureau Windows 7.  Cependant attention, dans le samsung galaxy, le code fonctionne encore dans Firefox, mais pas dans Google Chrome, qui est passé sur le nouveau format d’instructions webRtc(ou sur HTTPS forcé).

Index.html : Il va afficher la carte Google Map :

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>Géolocalisation</title>
    <meta name="viewport" content="initial-scale=1, maximum-scale=1, user-scalable=no, width=device-width">

	   <!-- JQUERY ET BOOTSRAP -->
        <script src="bower_components/jquery/dist/jquery.min.js"></script>
        <script src="bower_components/bootstrap/dist/js/bootstrap.min.js"></script>
        	<link rel="stylesheet" type="text/css" href="bower_components/bootstrap/dist/css/bootstrap.min.css">

        <!-- ANGULAR -->
        <script src='bower_components/angular/angular.min.js'></script>
		<script src="js/app.js"></script>

  </head>

	<body ng-app="geo" ng-controller="GeoCtrl">
<div id="map"></div>
</body>
</html>

Le fichier app.js, qui est le controleur de la vue index.html :

angular.module('geo', [])
.controller('GeoCtrl', function($scope) {
	/* GEOLOCALISATION */
	// Detect l'api avant de l'utiliser 
	 
	if (navigator.geolocation) {
	 // Insère la carte dans la div "map"
		var mapElem = document.getElementById("map"),
	 
		// cette fonction en cas de succès dacces à la position récupère la long et la lat puis affiche google map
	 
			successCallback = function(position) {
				var lat = position.coords.latitude,
					long = position.coords.longitude;
	 
				mapElem.innerHTML = '<img src="http://maps.googleapis.com/maps/api/staticmap?markers=' + lat + ',' + long + '&zoom=15&size=300x300&sensor=false" />';
			},
		
		// Cette fonction se lance si l'endroit ne peut pas être localisé
		errorCallback = function() {
				  alert("Désolé, je ne peux pas trouvé vos coordonées GPS.");
			};
	 
		// Start watching the user’s location, updating once per second (1s = 1000ms)
		// and execute the appropriate callback function based on whether the user
		// was successfully located or not
	 
		navigator.geolocation.watchPosition(successCallback, errorCallback, {
			maximumAge: 1000
		});
	}
});

 

 

10893962-Prendre-des-photos-avec-un-t-l-phone-mobile-smartphone-en-mode-appareil-photo-en-ext-rieur-Banque-d'images

Exemple de prise de photo sur Firefox dans un mobile Samsung 5 pouces Galaxy


une fois de plus, ce code marche très bien dans Firefox mobile, mais pas dans Chrome Mobile, on se demande vraiment ce qu’il leur a pris de suprimer la rétro compatibilité chez Chrome(ou de forcer l’accès https).

<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Acquérir le média d'un utilisateur - Photo</title>
</head>
<body>
<button id="take">Prends une photo, jojo</button>

<video id="v"></video>
<canvas id="canvas" style="display:none;"></canvas>
<img src="http://placehold.it/300&text=Your%20image%20here%20..." id="photo" alt="photo">
<script>
    ;(function(){
	<!-- la fonction générique qui est censée s adapter a tous les navigateurs -->
        function userMedia(){
            return navigator.getUserMedia = navigator.getUserMedia ||
            navigator.webkitGetUserMedia ||
            navigator.mozGetUserMedia ||
            navigator.msGetUserMedia || null;

        }

        // Maintenant, on peut l utiliser
        if( userMedia() ){
            var videoPlaying = false;
            var constraints = {
                video: true,
                audio:false
            };
            var video = document.getElementById('v');

            var media = navigator.getUserMedia(constraints, function(stream){

                // L url de l objet est different dans webkit
                var url = window.URL || window.webkitURL;

                // creer l url et set la source de la video
                video.src = url ? url.createObjectURL(stream) : stream;

                // lance la video
                video.play();
                videoPlaying  = true;
            }, function(error){
                console.log("ERROR");
                console.log(error);
            });

            // ecoute l action utilisateur sur le bouton prendre une photo jojo
            document.getElementById('take').addEventListener('click', function(){
                if (videoPlaying){
                    var canvas = document.getElementById('canvas');
                    canvas.width = video.videoWidth;
                    canvas.height = video.videoHeight;
                    canvas.getContext('2d').drawImage(video, 0, 0);
                    var data = canvas.toDataURL('image/webp');
                    document.getElementById('photo').setAttribute('src', data);
                }
            }, false);

        } else {
            console.log("KO");
        }
    })();
</script>
</body>
</html>

Mais… On s’en fout complétement de pouvoir prendre une photo, notre mobile le fait déjà bien!

L’intérêt est que l’on peut penser par exemple à une application commerciale qui permettrait de stocker des photos, ainsi que la localisation GPS à un instant T, qui seraient prises par des commerciaux. De cette façon, on pourrait ensuite réaliser des statistiques basées sur ces photos, leur fréquence etc … De même on peut lier la photo a un système de notation par étoile, le commercial peut par exemple attribuer une note à la devanture d’un magasin. Un autre exemple est le flash photographique lors du passage sous un portique, ne serait-ce que pour la sécurité.

 

 

46769-code-barre-codes-barres

Exemple de scan de Code bars en Html 5.0 avec quaggaJS (https://serratus.github.io/quaggaJS/).


 

Lorsque l’on pense à scanner un code barre, on pense généralement à utiliser une machine comme ceci :

155033_176018255756655_106589586032856_527658_3535967_n

avec une technique Js comme cela, par exemple . De suite, on est frappé par le fait que l’on puisse développer des applications AngularJs en utilisant ce système, AngularJs étant spécialement flexible et structuré, cela est très excitant et peut même sembler facile!

J’ai de ce pas acheté un petit lecteur de codes Barres sur Ebay pour commencer  à m’entrainer à créer des apps.

code128

Cependant, un développeur(génie?) a également développé QuaggaJs qui permet de scanner un code Barre avec l’appareil photo d’un téléphone mobile, ou à partir d’une photo. Reste à savoir le pourcentage de réussite de scans et à s’assurer que cela soit réellement utilisable en condition professionelle.

Je dois avouer que mes premiers tests avec une webcam de base et un téléphone Samsung Galaxy ne sont pas vraiment concluants, j’ai essayé de scanner une bouteille de coca cola, mais visiblement, sur le site Web, cela ne passe pas.

Par contre suite à une prise de photo, l’api semble avoir retrouvé le code barre. Il faut donc que je teste avec du code pour savoir si je récupère un code, avec un console.log();

Je termine l’article ces jours ci….
 

[Théorie] Utiliser des Apis Web pour concevoir plus rapidement des Application Web. ( + »Piquer » des données avec le Web Scrapping, hi hi hi)

Introductionbfs-module-icon-api-letter


Lorsque l’on débute un projet, notre base de données est vide, on a alors souvent besoin de données .

Pour obtenir ses futures données plus rapidement, on peut se connecter à l’aide d’une api à des bases de données WEB reconnues, afin d’alimenter notre application plus rapidement.

Un exemple: J’ai une application de vente et de gestion de poissons d’aquariums, je ne vais pas me taper à la main l’enregistrement de 1000 poissons et la prise de photo des 1000 poissons si les photos nommées existent déjà, triées , dans une base de données accessible sur WEB.
Un autre exemple : Si je veux créer un AutoComplete sur un Champs Input Html répertoriant des noms de villes, je ne vais pas, bien sur, coder à la main chaque nom de ville ! Je vais d’abord chercher si une API ne pourrait pas me fournir ces données automatiquement sans le moindre effort( De plus l’api pourra même me fournir énormément d’informations à propos de telle ou telle ville ).

Pour voir du web scrapping dans une de mes apps c’est ici : http://nicolash.org/truc53/#/dashboard/crud

Cependant attention, il pourrait arriver que certaines API soient supprimées ou discontinuées ou même mises à jour, en ce cas, si notre application reposant dessus ne fonctionne plus, on aura beaucoup de problèmes avec nos clients ! Il faut donc soit plutôt prévoir un système d’import des données ou soit prévoir une solution de secours dans notre application, dans l’idéal, l’intégration de l’api doit être transparente dans notre app, que l’api soit accessible ou pas.

Sommaire :


  1. Mais comment cela fonctionne-t-il sur le web ?
  2. Peux-tu nous faire un schéma ?
  3. A quoi ressemble la réponse du serveur distant ?
  4. Quelles  sont ces merveilleuses apis, alors  ?
  5. Mais …Il n’y a pas d’API et pourtant je voudrais acquérir les données d’un autre site web super bien dans mon application ! Le Web Scrapping.
  6. Et on peut scrapper avec Jquery ou Angular directement ?
  7. Des entreprises sont elles spécialisées dans le Web scrapping ?
  8. Les outils de Web scrapping

Lire la suite