hg-repeat scoping

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'
                    ]
				}
            ]
        }
    ]"/>
    
    <b>Persistant search</b>
    <div
        class="popover"
        ng-repeat="p in popovers" 
        >
        <p>Lab: {{p.displayName}}</p>
        <br/>
        <div
            ng-repeat="t in p.tabs" 
            class="tab"
            ng-class="currentTab==t.name?'selected':''"
            ng-click="$parent.currentTab=t.name; openPage(t.page)"
            >
                {{t.displayName}}
        </div>
        <div 
            ng-repeat="t in p.tabs" 
            ng-class="currentTab==t.name?'selected':''"
            class="tabContent vScrollable" 
            >
                <div ng-view></div>
         </div>
    </div>
</div>

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"></select><br/>Skins: <span ng-repeat="s in skins" ng-click="config.skin = s"> <b ng-class="{selected: config.skin == s}"> {{s}} </b> | </span><br/>'})
  .when('/search',	{controller:'myCtrl', template:'search: <input type="search" ng-model="searchKeyword"/>'})
  .otherwise({redirectTo:'/home'});
});

app.controller('myCtrl', function ($scope, $location, $http, Config, Search) {
    
    if (!$scope.searchKeyword) $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,...