Created
May 28, 2013 13:18
-
-
Save bennadel/5662684 to your computer and use it in GitHub Desktop.
My Approach To Building AngularJS Directives That Bind To JavaScript Events
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!doctype html> | |
<html ng-app="Demo" ng-controller="AppController"> | |
<head> | |
<meta charset="utf-8" /> | |
<title> | |
My Approach To Building AngularJS Directives | |
</title> | |
<style type="text/css"> | |
div.viewport { | |
border: 1px dashed #FF9999 ; | |
bottom: 10px ; | |
left: 9px ; | |
padding: 10px 10px 3px 10px ; | |
position: fixed ; | |
top: 113px ; | |
} | |
ul.friends { | |
list-style-type: none ; | |
margin: 0px 0px 0px 0px ; | |
padding: 0px 0px 0px 0px ; | |
width: 400px ; | |
} | |
ul.friends li { | |
border: 1px solid #CCCCCC ; | |
margin: 0px 0px 7px 0px ; | |
padding: 10px 10px 10px 10px ; | |
position: relative ; | |
} | |
ul.friends a { | |
color: #CCCCCC ; | |
right: 10px ; | |
position: absolute ; | |
} | |
ul.friends a:hover { | |
color: #CC0000 ; | |
} | |
div.teaser { | |
color: #999999 ; | |
font-style: italic ; | |
margin: 12px 0px 7px 0px ; | |
} | |
</style> | |
</head> | |
<body> | |
<h1> | |
My Approach To Building AngularJS Directives | |
</h1> | |
<!-- BEGIN: New Friend Form. --> | |
<form ng-submit="addFriend()"> | |
<p> | |
<input type="text" ng-model="newFriendName" size="30" /> | |
<input type="submit" value="Add Friend" /> | |
</p> | |
</form> | |
<!-- END: New Friend Form. --> | |
<!-- BEGIN: Friend List. --> | |
<div bn-viewport class="viewport"> | |
<ul class="friends"> | |
<li ng-repeat="friend in visibleFriends"> | |
{{ friend.name }} | |
<a ng-click="removeFriend( friend )">Remove</a> | |
</li> | |
</ul> | |
<div ng-show="hiddenFriends.length" class="teaser"> | |
... and {{ hiddenFriends.length }} friend(s) not shown. | |
</div> | |
</div> | |
<!-- END: Friend List. --> | |
<!-- Load jQuery and AngularJS from the CDN. --> | |
<script | |
type="text/javascript" | |
src="//code.jquery.com/jquery-2.0.0.min.js"> | |
</script> | |
<script | |
type="text/javascript" | |
src="//ajax.googleapis.com/ajax/libs/angularjs/1.0.4/angular.min.js"> | |
</script> | |
<script type="text/javascript"> | |
// Create an application module for our demo. | |
var app = angular.module( "Demo", [] ); | |
// -------------------------------------------------- // | |
// -------------------------------------------------- // | |
// Define the root-level controller for the application. | |
app.controller( | |
"AppController", | |
function( $scope ) { | |
// I am the model for new friends. | |
$scope.newFriendName = ""; | |
// Start off with a small set of default friends. | |
$scope.friends = [ | |
{ | |
id: 1, | |
name: "Tricia" | |
} | |
]; | |
// I am the collection of visible friends, based on | |
// the current collection and the capacity of the | |
// current interface. | |
$scope.visibleFriends = []; | |
// I am the collection of hidden friends, not shown | |
// because they exceed the capacity of the current | |
// interface. | |
$scope.hiddenFriends = []; | |
// I define the number of friends that should be | |
// visible in the current state of the interface. | |
var friendCapacity = 3; | |
// Divide the friends up into the hidden / visible | |
// breakdown based on the currently-hard-coded | |
// render capacity. | |
applyFriendCapacity(); | |
// -- | |
// PUBLIC METHODS. | |
// -- | |
// I add a new friend to the collection. | |
$scope.addFriend = function() { | |
if ( ! $scope.newFriendName ) { | |
return; | |
} | |
$scope.friends.push({ | |
id: ( new Date() ).getTime(), | |
name: $scope.newFriendName | |
}); | |
$scope.newFriendName = ""; | |
// Whenever the collection changes, we have to | |
// update the visible / hidden breakdown. | |
applyFriendCapacity(); | |
}; | |
// I remove the given friend from the collection. | |
$scope.removeFriend = function( friend ) { | |
var index = $scope.friends.indexOf( friend ); | |
if ( index === -1 ) { | |
return; | |
} | |
$scope.friends.splice( index, 1 ); | |
// Whenever the collection changes, we have to | |
// update the visible / hidden breakdown. | |
applyFriendCapacity(); | |
}; | |
// I set the capacity of the current interface. | |
$scope.setFriendCapacity = function( newCapacity ) { | |
friendCapacity = newCapacity; | |
// Apply the new capacity to the collections. | |
applyFriendCapacity(); | |
}; | |
// -- | |
// PRIVATE METHODS. | |
// -- | |
// I apply the current capacity to the friends to | |
// update the visible/hidden breakdown. | |
function applyFriendCapacity() { | |
// If the current interface capacity can hold | |
// of the current friends, simply funnel them all | |
// into the visible friends. | |
if ( friendCapacity >= $scope.friends.length ) { | |
$scope.visibleFriends = $scope.friends; | |
$scope.hiddenFriends = []; | |
// If we have more friends that the interface can | |
// hold, funnel the overflow into the hidden | |
// friends collection. | |
} else { | |
$scope.visibleFriends = $scope.friends.slice( 0, friendCapacity ); | |
$scope.hiddenFriends = $scope.friends.slice( friendCapacity ); | |
} | |
} | |
} | |
); | |
// -------------------------------------------------- // | |
// -------------------------------------------------- // | |
// I pipe the changes in window size into the parent controller. | |
app.directive( | |
"bnViewport", | |
function() { | |
// I link the DOM events to the current scope. | |
function link( $scope, element, attributes ) { | |
// I detect the UI interface capacity and tell the | |
// parent controller about the dynamic value. | |
function updateFriendCapacity() { | |
// For the sake of the demo, the height of | |
// the items and the teaser are hard-coded | |
// and are not calculated on the fly. | |
var itemHeight = 46; | |
var teaserHeight = 36; | |
// Get the inner height of the viewport. | |
var viewportHeight = element.height(); | |
// Again, for the sake of the demo, we'll just | |
// say that the available viewport is always | |
// taking the "teaser" into account, even if | |
// it is not going to be rendered. | |
var availableHeight = ( viewportHeight - teaserHeight ); | |
// Add back the amount of "margin collapse" | |
// height that will take place between the | |
// list and the teaser. | |
availableHeight += 5; | |
// Then, the capacity is simply the number of | |
// items that will fit in the available height. | |
var capacity = Math.floor( availableHeight / itemHeight ); | |
// Let the parent controller know about the | |
// new capacity of the viewport interface. | |
$scope.setFriendCapacity( capacity ); | |
} | |
// Update the capacity of the interface. | |
updateFriendCapacity(); | |
// NOTE: Since we are in the link function | |
// execution, we do not need to call the $apply() | |
// method - we are already in the middle of a | |
// monitored lifecycle. | |
// When the window resizes, the viewport will also | |
// be resized and capacity of the interface may be | |
// changed. | |
$( window ).on( | |
"resize.bnViewport", | |
function( event ) { | |
$scope.$apply( updateFriendCapacity ); | |
} | |
); | |
// When the scope is destroyed, be sure to unbind | |
// event handler can cause issues. | |
$scope.$on( | |
"$destroy", | |
function() { | |
$( window ).off( "resize.bnViewport" ); | |
} | |
); | |
} | |
// Return the directive configuration. | |
return({ | |
link: link, | |
restrict: "A" | |
}); | |
} | |
); | |
</script> | |
</body> | |
</html> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!doctype html> | |
<html ng-app="Demo" ng-controller="AppController"> | |
<head> | |
<meta charset="utf-8" /> | |
<title> | |
My Approach To Building AngularJS Directives | |
</title> | |
<style type="text/css"> | |
div.viewport { | |
border: 1px dashed #FF9999 ; | |
left: 9px ; | |
padding: 10px 10px 3px 10px ; | |
position: fixed ; | |
top: 113px ; | |
} | |
ul.friends { | |
list-style-type: none ; | |
margin: 0px 0px 0px 0px ; | |
padding: 0px 0px 0px 0px ; | |
width: 400px ; | |
} | |
ul.friends li { | |
border: 1px solid #CCCCCC ; | |
margin: 0px 0px 7px 0px ; | |
padding: 10px 10px 10px 10px ; | |
position: relative ; | |
} | |
ul.friends a { | |
color: #CCCCCC ; | |
right: 10px ; | |
position: absolute ; | |
} | |
ul.friends a:hover { | |
color: #CC0000 ; | |
} | |
div.teaser { | |
color: #999999 ; | |
font-style: italic ; | |
margin: 12px 0px 7px 0px ; | |
} | |
</style> | |
</head> | |
<body> | |
<h1> | |
My Approach To Building AngularJS Directives | |
</h1> | |
<!-- BEGIN: New Friend Form. --> | |
<form ng-submit="addFriend()"> | |
<p> | |
<input type="text" ng-model="newFriendName" size="30" /> | |
<input type="submit" value="Add Friend" /> | |
</p> | |
</form> | |
<!-- END: New Friend Form. --> | |
<!-- BEGIN: Friend List. --> | |
<div class="viewport"> | |
<ul class="friends"> | |
<li ng-repeat="friend in visibleFriends"> | |
{{ friend.name }} | |
<a ng-click="removeFriend( friend )">Remove</a> | |
</li> | |
</ul> | |
<div ng-show="hiddenFriends.length" class="teaser"> | |
... and {{ hiddenFriends.length }} friend(s) not shown. | |
</div> | |
</div> | |
<!-- END: Friend List. --> | |
<!-- Load jQuery and AngularJS from the CDN. --> | |
<script | |
type="text/javascript" | |
src="//code.jquery.com/jquery-2.0.0.min.js"> | |
</script> | |
<script | |
type="text/javascript" | |
src="//ajax.googleapis.com/ajax/libs/angularjs/1.0.4/angular.min.js"> | |
</script> | |
<script type="text/javascript"> | |
// Create an application module for our demo. | |
var app = angular.module( "Demo", [] ); | |
// -------------------------------------------------- // | |
// -------------------------------------------------- // | |
// Define the root-level controller for the application. | |
app.controller( | |
"AppController", | |
function( $scope ) { | |
// I am the model for new friends. | |
$scope.newFriendName = ""; | |
// Start off with a small set of default friends. | |
$scope.friends = [ | |
{ | |
id: 1, | |
name: "Tricia" | |
} | |
]; | |
// I am the collection of visible friends, based on | |
// the current collection and the capacity of the | |
// current interface. | |
$scope.visibleFriends = []; | |
// I am the collection of hidden friends, not shown | |
// because they exceed the capacity of the current | |
// interface. | |
$scope.hiddenFriends = []; | |
// I define the number of friends that should be | |
// visible in the current state of the interface. | |
var friendCapacity = 3; | |
// Divide the friends up into the hidden / visible | |
// breakdown based on the currently-hard-coded | |
// render capacity. | |
applyFriendCapacity(); | |
// -- | |
// PUBLIC METHODS. | |
// -- | |
// I add a new friend to the collection. | |
$scope.addFriend = function() { | |
if ( ! $scope.newFriendName ) { | |
return; | |
} | |
$scope.friends.push({ | |
id: ( new Date() ).getTime(), | |
name: $scope.newFriendName | |
}); | |
$scope.newFriendName = ""; | |
// Whenever the collection changes, we have to | |
// update the visible / hidden breakdown. | |
applyFriendCapacity(); | |
}; | |
// I remove the given friend from the collection. | |
$scope.removeFriend = function( friend ) { | |
var index = $scope.friends.indexOf( friend ); | |
if ( index === -1 ) { | |
return; | |
} | |
$scope.friends.splice( index, 1 ); | |
// Whenever the collection changes, we have to | |
// update the visible / hidden breakdown. | |
applyFriendCapacity(); | |
}; | |
// I set the capacity of the current interface. | |
$scope.setFriendCapacity = function( newCapacity ) { | |
friendCapacity = newCapacity; | |
// Apply the new capacity to the collections. | |
applyFriendCapacity(); | |
}; | |
// -- | |
// PRIVATE METHODS. | |
// -- | |
// I apply the current capacity to the friends to | |
// update the visible/hidden breakdown. | |
function applyFriendCapacity() { | |
// If the current interface capacity can hold | |
// of the current friends, simply funnel them all | |
// into the visible friends. | |
if ( friendCapacity >= $scope.friends.length ) { | |
$scope.visibleFriends = $scope.friends; | |
$scope.hiddenFriends = []; | |
// If we have more friends that the interface can | |
// hold, funnel the overflow into the hidden | |
// friends collection. | |
} else { | |
$scope.visibleFriends = $scope.friends.slice( 0, friendCapacity ); | |
$scope.hiddenFriends = $scope.friends.slice( friendCapacity ); | |
} | |
} | |
} | |
); | |
</script> | |
</body> | |
</html> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!doctype html> | |
<html ng-app="Demo" ng-controller="AppController"> | |
<head> | |
<meta charset="utf-8" /> | |
<title> | |
My Approach To Building AngularJS Directives | |
</title> | |
<style type="text/css"> | |
ul.friends { | |
list-style-type: none ; | |
margin: 0px 0px 0px 0px ; | |
padding: 0px 0px 0px 0px ; | |
width: 400px ; | |
} | |
ul.friends li { | |
border: 1px solid #CCCCCC ; | |
margin: 0px 0px 7px 0px ; | |
padding: 10px 10px 10px 10px ; | |
position: relative ; | |
} | |
ul.friends a { | |
color: #CCCCCC ; | |
right: 10px ; | |
position: absolute ; | |
} | |
ul.friends a:hover { | |
color: #CC0000 ; | |
} | |
</style> | |
</head> | |
<body> | |
<h1> | |
My Approach To Building AngularJS Directives | |
</h1> | |
<!-- BEGIN: New Friend Form. --> | |
<form ng-submit="addFriend()"> | |
<p> | |
<input type="text" ng-model="newFriendName" size="30" /> | |
<input type="submit" value="Add Friend" /> | |
</p> | |
</form> | |
<!-- END: New Friend Form. --> | |
<!-- BEGIN: Friend List. --> | |
<ul class="friends"> | |
<li ng-repeat="friend in friends"> | |
{{ friend.name }} | |
<a ng-click="removeFriend( friend )">Remove</a> | |
</li> | |
</ul> | |
<!-- END: Friend List. --> | |
<!-- Load jQuery and AngularJS from the CDN. --> | |
<script | |
type="text/javascript" | |
src="//code.jquery.com/jquery-2.0.0.min.js"> | |
</script> | |
<script | |
type="text/javascript" | |
src="//ajax.googleapis.com/ajax/libs/angularjs/1.0.4/angular.min.js"> | |
</script> | |
<script type="text/javascript"> | |
// Create an application module for our demo. | |
var app = angular.module( "Demo", [] ); | |
// -------------------------------------------------- // | |
// -------------------------------------------------- // | |
// Define the root-level controller for the application. | |
app.controller( | |
"AppController", | |
function( $scope ) { | |
// I am the model for new friends. | |
$scope.newFriendName = ""; | |
// Start off with a small set of default friends. | |
$scope.friends = [ | |
{ | |
id: 1, | |
name: "Tricia" | |
} | |
]; | |
// -- | |
// PUBLIC METHODS. | |
// -- | |
// I add a new friend to the collection. | |
$scope.addFriend = function() { | |
if ( ! $scope.newFriendName ) { | |
return; | |
} | |
$scope.friends.push({ | |
id: ( new Date() ).getTime(), | |
name: $scope.newFriendName | |
}); | |
$scope.newFriendName = ""; | |
}; | |
// I remove the given friend from the collection. | |
$scope.removeFriend = function( friend ) { | |
var index = $scope.friends.indexOf( friend ); | |
if ( index === -1 ) { | |
return; | |
} | |
$scope.friends.splice( index, 1 ); | |
}; | |
} | |
); | |
</script> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment