Angular & jQuery Bubble Plugin

by Zuhaib Siddiqui

HTML

<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.0-rc.2/angular.min.js"></script>
<div ng-app="Demo" class="bg">
<ul bn-demo="">		
</ul>
</div>

CSS

.bg{
  background:#fff;
  border:1px solid #000;
  padding:10px;
  width:100%;
  height:100vh;
}
ul {
	bottom: 0px ;
	left: 0px ;
	list-style-type: none ;
	margin: 0px ;
	padding: 0px ;
	position: fixed ;
	right: 0px ;
	top: 0px ;
}

ul li {
	background-color: #FAFAFA ;
	border: 1px solid #AAAAAA ;
	border-radius: 50px 50px 50px 50px ;
	height: 48px ;
	margin: 0px ;
	padding: 0px ;
	position: absolute ;
	transition: all 1s ease ;
		-moz-transition: all 1s ease ;
		-webkit-transition: all 1s ease ;
	width: 48px ;
}

ul li:hover {
	background-color: #FFEAEA ;
}

ul li.selected {
	border-color: #FF00CC ;
	border-width: 4px 4px 4px 4px ;
	height: 46px ;
	margin-left: -20px ;
	margin-top: -20px ;
	width: 46px ;
	z-index: 2 ;
}
.block{
	width:300px;
	height:300px;
	border:2px solid #000;
	padding:20px;
	background-color:#fff;
}

JavaScript

// Create an application module for our demo.
		var app = angular.module( "Demo", [] );
		
		// I add an element to the point of a click and then randomly select one of the
		// existing elements in the lsit.
		app.directive("bnDemo",function() {

				// Create a jQuery plugin to help with the demo. Since we are including
				// jQuery in our application, "angular.element" is a reference to the 
				// jQuery object, which means we can define plugins off the "element".
				angular.element.fn.random = function() {

					return( this.eq( Math.floor( this.length * Math.random() ) ) );

				};

				// Create a jQuery plugin to help set the position of the elements in 
				// the collection based on a pixel-based X/Y coordinates and an optional
				// offset that is added to both the coordinate values.
				angular.element.fn.xyo = function( x, y, offset ) {

					this.css({
						left: ( ( x + ( offset || 0 ) ) + "px" ),
						top: ( ( y + ( offset || 0 ) ) + "px" )
					});

					return( this );

				};

				// Return the directive configuration.
				return({
					link: link,
					restrict: "A"
				});


				// ---
				// PUBLIC METHODS.
				// ---


				// I bind the JavaScript events to the local scope.
				function link( scope, element, attributes ) {

					element.on("click",function handleClickEvent(event){

							// If the user clicked on an existing LI, then don't change 
							// the contents of the container, just select the target.
							if (angular.element( event.target ).is( "li" )){

								// Select the target element.
								element.children()
									.removeClass( "selected" )
									.filter( event.target )
										.addClass( "selected" )
								;
								
								return;

							}

							// Create a new element at the click position.
							angular.element( "<li></li>" )
								.xyo( event.pageX, event.pageY, -25 )
								.appendTo( element )
							;

							// Select a random element in the...