Angularjs: local scope and multiple controller

by Stephane de Luca

HTML

<script src="https://code.angularjs.org/1.2.7/angular.js"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/angular.js/1.3.0-beta.3/angular-sanitize.min.js"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/angular.js/1.3.0-beta.3/angular-touch.js"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/angular.js/1.3.0-beta.3/angular-route.js"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/angular.js/1.3.0-beta.3/angular-cookies.js"></script>
<div ng-controller="myCtrl" ng-class="{true: 'skin' + config.skin}[true]">
    <div ng-model="currentTab" ng-init="currentTab='Partial1'"/>
    <div ng-init="popovers = [	
		{	name: 'Popover1',	
            displayName: 'Pick a page',
			tabs: [
				{	name: 'Partial1',		
                    displayName: 'On-the-fly searching',
                    page: '/home',
					description: [
                        'The home page'
                    ]
				},
				{	name: 'Partial2',		
                    displayName: 'Search page',
                    page: '/search',
					description: [
                        'The search page'
                    ]
				}
            ]
        }
    ]"/>
    <div ng-init="
	descriptions = {
		floraison: { 
			photos: [
				{file:'1-PaniculeSansPollen',						description:'Panicule sans pollen'},
				{file:'2-DebutEmissionPollenSurLeBrinPrincipal',	description:'Début émission pollen sur le brin principal'},
				{file:'3-SacsPolliniques',							description:'Sacs polliniques'},
				{file:'8-GrainsDePollen',							description:'Grains de pollen''},
				{file:'4-DebutDeSortieDesSoies',					description:'Début de sortie des soies'},
				{file:'5-1Soie=1OvuleAFeconder',					description:'1 soie = 1 ovule = 1 grain'},
				{file:'6-1Soie=1OvuleAFeconderGrosPlan',			description:'1 soie = 1 ovule = 1 grain (gros plan)'},
				{file:'7-EmissionDePollen',							description:'Pollen sur les soie'}
			],
			description: '
				<p>Besoins en somme de température : 825 à 1.050 dj du...

CSS

* {
	// prevent callout when holding tap on links (the native dialog that comes up)
	-webkit-touch-callout: none;

	// prevent webkit from resizing text to fit
	-webkit-text-size-adjust: none;

	// make transparent link selection, adjust last value opacity 0 to 1.0
	-webkit-tap-highlight-color: rgba(0,0,0,0);

	// prevent copy paste, to allow, change 'none' to 'text'
	-webkit-user-select: none; 

	//font-family: HelveticaNeue;
	font-family: "AvenirNextCondensed-Regular" sans-serif;
	//box-sizing: border-box; 

    -webkit-box-sizing: border-box;   
}


.popover {
    border: solid 3px lightgray;
    width:  400px;
    height: 500px;
    padding: 20px;
    margin:  20px;
}

.skinGray .popover {
    background-color: lightgray;
}

.skinBlue .popover {
    background-color: lightblue;
}

.skinGreen .popover {
    background-color: lightgreen;
}
.popover .tab {
    display: inline-block; 
    background-color: gray;
    border: solid 1px gray;
    border-top-right-radius: 10px;
    border-left: none;
    border-bottom: none;
    width:auto;
    padding: 8px;
    font-size: 14pt;
    box-shadow: 0 0 4px rgba(0,0,0,.2);
    color: black;
}

.popover .tab.selected {
    background-color: lightgray;
    color: white;
    font-weight: bold;
}

.popover .tabContent {
    display: none;
    height: calc(100% - 80px);
    background-color: rgb(200, 200, 255);
    padding: 10px;
}

.popover .tabContent.selected {
    display: block;
}

.withPadding {
    padding: 8px;
}

/* -------
    Scroller stuff below
   --------
*/

/* vertical scroller */

.vScrollable {
    -webkit-overflow-scrolling: touch;
    overflow-x: hidden;
    overflow-y: scroll;
}

/* Horizontal scrolling */

.hScrollable {
    -webkit-overflow-scrolling: touch;
    overflow-x: scroll;
    overflow-y: hidden;
    white-space:nowrap;
    height: auto;
}
.scroller {
    background-color: lightgray;
    margin: 0;
    padding: 4px;
}

.scroller>div {
    width:  100px;
    height: 100px;
    display:...

JavaScript

var app = angular.module('myApp', ['ngSanitize', 'ngTouch', 'ngRoute', 'ngCookies']);


app.factory("Search",function(){
	console.log("Factory Search…");
	return {
		// global search
    	searchKeyword: "Couleur blanche"
	};
});

app.factory("Config",function($cookies){
	console.log("Factory Config…");
	return {
		config: {
			skin: "Gray"
		},
		save: function(s) {
			console.log("Config.save() ");
			this.config = s; 
			$cookies.config = JSON.stringify(this.config);
		},
		load: function() {
			if ($cookies.config) {
				try {
					this.config = JSON.parse($cookies.config);
					console.log("App controller: read config from cookies as: ");
					for (var i in this.config) {
						console.log ("— "+i+" = "+this.config[i]);
					}
				} catch(e) {
					config = null;
				}
			}
			if (!this.config) {
				this.config = {"skin": "Gray"};
				console.log("App controller: init config from controler ("+this.config+")");
			}
			return this;
		}
	};
});


app.config(function($routeProvider) {
  $routeProvider
  .when('/home', 	{controller:'myCtrl', template:'home: <input type="search" ng-model="searchKeyword"/><br/> Skin: <select ng-options="s for s in skins" ng-model="config.skin"><option >'})
  .when('/search',	{controller:'myCtrl', template:'search: <input type="search" ng-model="searchKeyword"/>'})
  .otherwise({redirectTo:'/home'});
});

app.controller('myCtrl', function ($scope, $location, $http, Config, Search) {
    
    $scope.searchKeyword = Search.searchKeyword;

    if (!$scope.config) $scope.config = Config.load().config;
    
    $scope.skins = ["Gray", "Blue", "Green"];
    
    $scope.$watch('config.skin', function (newValue, oldValue) {
		console.log("$scope.config.skin changed from "+oldValue+" to "+newValue);
		Config.save($scope.config);
	});
    
    console.log("Running controller, searchKeyword is '"+$scope.searchKeyword+"'");
    
    if (!$scope.searchKeyword) {
        console.log("Inited searchKeyword from controller");
       ...