Skip to content

Instantly share code, notes, and snippets.

@billyriantono
Created August 21, 2014 03:53
Show Gist options
  • Save billyriantono/f3c3d87250f318202039 to your computer and use it in GitHub Desktop.
Save billyriantono/f3c3d87250f318202039 to your computer and use it in GitHub Desktop.
AngularJS Floating Menu based on http://codepen.io/m-e-conroy/pen/cFKkG
/***** Draggable Library *****/
angular.module('itsADrag',['ngSanitize'])
/**
Possible element attributes:
1. template
2. id
3. options - json of jquery ui draggable options
4. group
5. placeholder
**/
.directive('draggable',[function(){
return {
restrict : 'AE',
transclude : true,
replace : true,
// terminal : true, // make last directive to execute
scope : {},
templateUrl : function(el,attrs){
return (angular.isDefined(attrs.template)) ? attrs.template : '/tmpls/draggable-default';
},
link : function(scope,el,attrs){
// draggable object properties
scope.obj = {
id : null,
content : '',
group : null
};
scope.placeholder = false;
scope.obj.content = el.html();
if(angular.isDefined(attrs.id))
scope.obj.id = attrs.id;
if(angular.isDefined(attrs.placeholder))
scope.placeholder = scope.$eval(attrs.placeholder);
// options for jQuery UI's draggable method
var opts = (angular.isDefined(attrs.options)) ? scope.$eval(attrs.options) : {};
if(angular.isDefined(attrs.group)){
scope.obj.group = attrs.group;
opts.stack = '.' + attrs.group;
}
// event handlers
var evts = {
start : function(evt,ui){
if(scope.placeholder) // ui.helper is jQuery object
ui.helper.wrap('<div class="dragging"></div>');
scope.$apply(function(){ // emit event in angular context
scope.$emit('draggable.started',{obj: scope.obj});
}); // end $apply
}, // end start
drag : function(evt){
scope.$apply(function(){ // emit event in angular context
scope.$emit('draggable.dragging');
}); // end $apply
}, // end drag
stop : function(evt,ui){
if(scope.placeholder)
ui.helper.unwrap();
scope.$apply(function(){ // emit event in angular context
scope.$emit('draggable.stopped');
}); // end $apply
} // end stop
}; // end evts
// combine options and events
var options = angular.extend({},opts,evts);
el.draggable(options); // make element draggable
} // end link
}; // end return
}]) // end draggable
.run(['$templateCache',function($templateCache){
$templateCache.put('/tmpls/draggable-default','<div ng-transclude></div>');
}]); // end itsADrag.run
/***** Application *****/
angular.module('adminMenu',['ngSanitize','itsADrag','ui.bootstrap'])
.controller('aMenuCtrl',['$scope',function($scope){
$scope.onAtATime = true;
}]) // end aMenuCtrl
.run(['$templateCache',function($templateCache){
$templateCache.put('/tmpls/floatingMenu','<div class="container"><div class="row"><div class="col-md-4"><div class="panel panel-primary"><div class="panel-heading cursor-move"><span class="pull-right"><a type="button" id="menuMinimize" class="btn btn-primary btn-xs" ng-init="minimized = false" ng-click="minimized = !minimized" data-toggle="collapse" href="#menuBody"><span class="glyphicon" ng-class="{false: \'glyphicon-chevron-up\',true: \'glyphicon-chevron-down\'}[minimized]"></span></a></span><span><big>Administrative Menu</big></span></div><div id="menuBody" class="panel-collapse collapse in"><div class="panel-body" ng-transclude></div><div class="panel-footer"><small>&nbsp;</small><span class="pull-right text-muted"><small>&copy; 2014 Michael Conroy</small></span></div></div></div></div></div></div>');
}]); // end adminMenu.run
<html ng-app="adminMenu">
<head>
<!-- jQuery -->
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js" type="text/javascript"></script>
<script src="//ajax.googleapis.com/ajax/libs/jqueryui/1.10.4/jquery-ui.min.js" type="text/javascript"></script>
<!-- Angular -->
<script src="//code.angularjs.org/1.2.12/angular.min.js" type="text/javascript"></script>
<script src="//code.angularjs.org/1.2.12/angular-sanitize.min.js" type="text/javascript"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/angular-ui-bootstrap/0.10.0/ui-bootstrap-tpls.min.js" type="text/javascript"></script>
<!-- Bootstrap -->
<script src="//netdna.bootstrapcdn.com/bootstrap/3.1.1/js/bootstrap.min.js"></script>
</head>
<body ng-controller="aMenuCtrl">
<div class="container">
<div class="row">
<div class="col-md-12">
<h1>Floating Menu</h1>
</div>
</div>
<div class="row">
<div class="col-md-12 text-muted">
<p><strong>You can drag the menu by clicking the "window" or panel's heading bar.</strong></p>
<p>An administrative floating, draggable menu for a custom CMS. The javascript is a bit heavy as I'm using jQuery, jQuery-UI, AngularJS & Angular-UI-Bootstrap. I'll investigate removing the jQuery & jQuery-UI in the future for just AngularJS as well as removing Bootstrap's transition.js for AngularJS' ng-animate directive.</p>
<h3>The Transclusion Test</h3>
<p>This was more or less a test to see if the Angular-UI-Bootstrap directive for accordion would be transcluded correctly into the directive I created for making draggable elements.</p>
<h3>Future Enhancements & To Dos</h3>
<ul>
<li>Settings dropdown options for the floating menu.</li>
<li>Resizeable. <span class="text-success"><span class="glyphicon glyphicon-check"></span> Done, check other pen with AngularJS Windows.</span></li>
<li>Restrict vertical size so it doesn't fall off the window's page. This may mean the menu inside needs to be scrollable. <span class="text-success"><span class="glyphicon glyphicon-check"></span> Done, made window body content scrollable, check pen AngularJS Windows.</span></li>
<li>Test draggable elements within the menu. <span class="text-success"><span class="glyphicon glyphicon-check"></span> Done.</span></li>
</ul>
</div>
</div>
</div>
<draggable template="/tmpls/floatingMenu" id="adminFloatingMenu" options="{addClasses: false, cancel: '.panel-body', opacity: 0.35}">
<accordion close-others="onAtATime">
<accordion-group heading="Manage Users">
<ul class="list-group">
<li class="list-group-item">Mike</li>
<li class="list-group-item">Mary</li>
<li class="list-group-item">Doug</li>
<li class="list-group-item">Catherine</li>
<li class="list-group-item">Jake</li>
<li class="list-group-item">Nareen</li>
</ul>
</accordion-group>
<accordion-group heading="Manage Departments">
<ul class="list-group">
<li class="list-group-item">Marketing</li>
<li class="list-group-item">Communications</li>
<li class="list-group-item">Education</li>
<li class="list-group-item">Graduate</li>
<li class="list-group-item">Undergraduate</li>
<li class="list-group-item">Admissions</li>
</ul>
</accordion-group>
<accordion-group heading="Sites">
<ul class="list-group">
<li class="list-group-item">Web Services</li>
<li class="list-group-item">Admissions</li>
<li class="list-group-item">Undergraduate Catalog</li>
<li class="list-group-item">Advising</li>
</ul>
</accordion-group>
<accordion-group heading="Data Sets">
<ul class="list-group">
<li class="list-group-item">Marketing</li>
<li class="list-group-item">Catalog</li>
<li class="list-group-item">Advising</li>
<li class="list-group-item">Admissions</li>
</ul>
</accordion-group>
<accordion-group heading="Templates">
<ul class="list-group">
<li class="list-group-item">Generic</li>
<li class="list-group-item">Marketing</li>
<li class="list-group-item">Catalog</li>
<li class="list-group-item">Admissions</li>
</ul>
</accordion-group>
</accordion>
</draggable>
</body>
</html>
accordion .panel-heading a { cursor: pointer; }
.cursor-move { cursor: move; }
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment