angular-stackables
Advanced tools
Comparing version 0.0.16 to 0.0.17
{ | ||
"name": "angular-stackables", | ||
"version": "0.0.16", | ||
"version": "0.0.17", | ||
"description": "AngularJS stackable widgets built on HTML5 dialog.", | ||
@@ -5,0 +5,0 @@ "authors": [ |
{ | ||
"name": "angular-stackables", | ||
"version": "0.0.16", | ||
"version": "0.0.17", | ||
"dependencies": {} | ||
} |
@@ -12,4 +12,3 @@ angular-stackables | ||
<div ng-controller="TestController as test"> | ||
<div stackable="test.isOpen" | ||
stackable-modal="true" | ||
<stackable-modal stackable="test.isOpen" | ||
stackable-disable-escape="false" | ||
@@ -23,3 +22,3 @@ stackable-closing="test.modalClosing(err, result)" | ||
</div> | ||
</div> | ||
</stackable-modal> | ||
</div> | ||
@@ -69,3 +68,3 @@ ``` | ||
<div stackable-popover="test.popoverState" | ||
<stackable-popover stackable="test.popoverState" | ||
stackable-placement="bottom" | ||
@@ -78,3 +77,3 @@ stackable-alignment="center" | ||
</div> | ||
</div> | ||
</stackable-popover> | ||
</div> | ||
@@ -91,3 +90,3 @@ ``` | ||
<div stackable-popover="test.menuState" | ||
<stackable-popover stackable="test.menuState" | ||
stackable-hide-arrow="true" | ||
@@ -102,4 +101,4 @@ stackable-placement="bottom" | ||
</ul> | ||
</div> | ||
</stackable-popover> | ||
</div> | ||
``` |
@@ -16,2 +16,3 @@ /*! | ||
module.directive({stackableCancel: stackableCancelDirective}); | ||
module.directive({stackableModal: stackableModalDirective}); | ||
module.directive({stackablePopover: stackablePopoverDirective}); | ||
@@ -22,34 +23,88 @@ module.directive({stackableTrigger: ['$parse', stackableTriggerDirective]}); | ||
return { | ||
scope: { | ||
show: '=stackable', | ||
modal: '=?stackableModal', | ||
persist: '=?persistContent', | ||
disableEscape: '=?stackableDisableEscape', | ||
closing: '&?stackableClosing', | ||
closed: '&?stackableClosed' | ||
}, | ||
restrict: 'A', | ||
replace: true, | ||
transclude: true, | ||
template: ' \ | ||
<dialog class="stackable stackable-fadein stackable-fadeout" \ | ||
ng-class="{\'stackable-modal\': modal}" \ | ||
ng-show="show"> \ | ||
<div class="stackable-content stackable-fadein stackable-fadeout" \ | ||
ng-if="show || persist"> \ | ||
<div ng-transclude></div> \ | ||
</div> \ | ||
</dialog>', | ||
controller: ['$scope', Controller], | ||
link: Link | ||
controller: Controller | ||
}; | ||
function Controller($scope) { | ||
function Controller() { | ||
var self = this; | ||
var stackable = $scope.stackable = self; | ||
// link the dialog element | ||
self.link = function(scope, element) { | ||
self.scope = scope; | ||
scope.stackable = self; | ||
var open = false; | ||
var body = angular.element('body'); | ||
var dialog = element[0]; | ||
// move dialog to body to simpify z-indexing | ||
body.append(dialog); | ||
// use polyfill if necessary | ||
if(!dialog.showModal && typeof dialogPolyfill !== 'undefined') { | ||
dialogPolyfill.registerDialog(dialog); | ||
} | ||
var cancelListener = function(e) { | ||
if(!!scope.disableEscape) { | ||
e.preventDefault(); | ||
} else { | ||
scope.stackable.error = 'canceled'; | ||
scope.stackable.result = null; | ||
} | ||
}; | ||
dialog.addEventListener('cancel', cancelListener); | ||
var closeListener = function(e) { | ||
e.stopPropagation(); | ||
scope.show = open = false; | ||
var count = body.data('stackables') - 1; | ||
body.data('stackables', count); | ||
if(count === 0) { | ||
body.removeClass('stackable-modal-open'); | ||
} | ||
scope.$apply(); | ||
if(scope.closed) { | ||
scope.closed.call(scope.$parent, { | ||
err: scope.stackable.error, | ||
result: scope.stackable.result | ||
}); | ||
} | ||
}; | ||
dialog.addEventListener('close', closeListener); | ||
scope.$watch('show', function(value) { | ||
if(value) { | ||
if(!open) { | ||
if(!!scope.modal) { | ||
dialog.showModal(); | ||
body.addClass('stackable-modal-open'); | ||
} else { | ||
dialog.show(); | ||
} | ||
open = true; | ||
scope.stackable.error = scope.stackable.result = undefined; | ||
var count = body.data('stackables') || 0; | ||
body.data('stackables', count + 1); | ||
} | ||
} else if(open) { | ||
// schedule dialog close to avoid $digest already in progress | ||
// as 'close' event handler may be called from here or externally | ||
setTimeout(function() { | ||
dialog.close(); | ||
}); | ||
open = false; | ||
} | ||
}); | ||
scope.$on('$destroy', function() { | ||
dialog.removeEventListener(cancelListener); | ||
dialog.removeEventListener(closeListener); | ||
}); | ||
}; | ||
// close the stackable unless 'closing' callback aborts | ||
self.close = function(err, result) { | ||
var closing = $scope.closing || angular.noop; | ||
var shouldClose = closing.call($scope.$parent, { | ||
var closing = self.scope.closing || angular.noop; | ||
var shouldClose = closing.call(self.scope.$parent, { | ||
err: err, | ||
@@ -60,6 +115,6 @@ result: result | ||
if(shouldClose !== false) { | ||
stackable.error = err; | ||
stackable.result = result; | ||
$scope.show = false; | ||
$scope.$apply(); | ||
self.error = err; | ||
self.result = result; | ||
self.scope.show = false; | ||
self.scope.$apply(); | ||
} | ||
@@ -69,69 +124,2 @@ }); | ||
} | ||
function Link(scope, element) { | ||
var open = false; | ||
var body = angular.element('body'); | ||
var dialog = element[0]; | ||
// use polyfill if necessary | ||
if(!dialog.showModal && typeof dialogPolyfill !== 'undefined') { | ||
dialogPolyfill.registerDialog(dialog); | ||
} | ||
var cancelListener = function(e) { | ||
if(!!scope.disableEscape) { | ||
e.preventDefault(); | ||
} else { | ||
scope.stackable.error = 'canceled'; | ||
scope.stackable.result = null; | ||
} | ||
}; | ||
dialog.addEventListener('cancel', cancelListener); | ||
var closeListener = function(e) { | ||
e.stopPropagation(); | ||
scope.show = open = false; | ||
var count = body.data('stackables') - 1; | ||
body.data('stackables', count); | ||
if(count === 0) { | ||
body.removeClass('stackable-modal-open'); | ||
} | ||
scope.$apply(); | ||
if(scope.closed) { | ||
scope.closed.call(scope.$parent, { | ||
err: scope.stackable.error, | ||
result: scope.stackable.result | ||
}); | ||
} | ||
}; | ||
dialog.addEventListener('close', closeListener); | ||
scope.$watch('show', function(value) { | ||
if(value) { | ||
if(!open) { | ||
if(!!scope.modal) { | ||
dialog.showModal(); | ||
body.addClass('stackable-modal-open'); | ||
} else { | ||
dialog.show(); | ||
} | ||
open = true; | ||
scope.stackable.error = scope.stackable.result = undefined; | ||
var count = body.data('stackables') || 0; | ||
body.data('stackables', count + 1); | ||
} | ||
} else if(open) { | ||
// schedule dialog close to avoid $digest already in progress | ||
// as 'close' event handler may be called from here or externally | ||
setTimeout(function() { | ||
dialog.close(); | ||
}); | ||
open = false; | ||
} | ||
}); | ||
scope.$on('$destroy', function() { | ||
dialog.removeEventListener(cancelListener); | ||
dialog.removeEventListener(closeListener); | ||
}); | ||
} | ||
} | ||
@@ -159,39 +147,77 @@ | ||
function stackableModalDirective() { | ||
return { | ||
require: 'stackable', | ||
scope: { | ||
closed: '&?stackableClosed', | ||
closing: '&?stackableClosing', | ||
disableEscape: '=?stackableDisableEscape', | ||
persist: '=?persistContent', | ||
show: '=stackable' | ||
}, | ||
restrict: 'E', | ||
replace: true, | ||
transclude: true, | ||
template: ' \ | ||
<dialog class="stackable stackable-modal \ | ||
stackable-fadein stackable-fadeout" ng-show="show"> \ | ||
<div class="stackable-content stackable-fadein stackable-fadeout" \ | ||
ng-if="show || persist"> \ | ||
<div ng-transclude></div> \ | ||
</div> \ | ||
</dialog>', | ||
link: function(scope, element, attrs, ctrl) { | ||
// link stackable dialog | ||
ctrl.link(scope, element); | ||
scope.modal = true; | ||
} | ||
}; | ||
} | ||
function stackablePopoverDirective() { | ||
return { | ||
require: 'stackable', | ||
scope: { | ||
state: '=stackablePopover', | ||
alignment: '@?stackableAlignment', | ||
disableBlurClose: '=?stackableDisableBlurClose', | ||
disableEscape: '=?stackableDisableEscape', | ||
hideArrow: '=?stackableHideArrow', | ||
alignment: '@?stackableAlignment', | ||
persist: '=?persistContent', | ||
placement: '@?stackablePlacement', | ||
disableEscape: '=?stackableDisableEscape', | ||
disableBlurClose: '=?stackableDisableBlurClose' | ||
state: '=stackable' | ||
}, | ||
restrict: 'A', | ||
restrict: 'E', | ||
replace: true, | ||
transclude: true, | ||
template: ' \ | ||
<div><div stackable="state.show" class="stackable-popover"> \ | ||
<div class="stackable-popover-content stackable-fadein" \ | ||
style="display: none; opacity: 0" \ | ||
ng-class="{ \ | ||
\'stackable-place-top\': !placement || placement == \'top\', \ | ||
\'stackable-place-right\': placement == \'right\', \ | ||
\'stackable-place-bottom\': placement == \'bottom\', \ | ||
\'stackable-place-left\': placement == \'left\', \ | ||
\'stackable-align-center\': !alignment || \ | ||
alignment == \'center\', \ | ||
\'stackable-align-top\': alignment == \'top\', \ | ||
\'stackable-align-right\': alignment == \'right\', \ | ||
\'stackable-align-bottom\': alignment == \'bottom\', \ | ||
\'stackable-align-left\': alignment == \'left\', \ | ||
\'stackable-no-arrow\': hideArrow}"> \ | ||
<div ng-if="!hideArrow" class="stackable-arrow"></div> \ | ||
<div ng-transclude></div> \ | ||
<dialog class="stackable stackable-popover \ | ||
stackable-fadein stackable-fadeout" ng-show="show"> \ | ||
<div class="stackable-content stackable-fadein stackable-fadeout" \ | ||
ng-if="show || persist"> \ | ||
<div class="stackable-popover-content stackable-fadein" \ | ||
style="display: none; opacity: 0" \ | ||
ng-class="{ \ | ||
\'stackable-place-top\': !placement || placement == \'top\', \ | ||
\'stackable-place-right\': placement == \'right\', \ | ||
\'stackable-place-bottom\': placement == \'bottom\', \ | ||
\'stackable-place-left\': placement == \'left\', \ | ||
\'stackable-align-center\': !alignment || \ | ||
alignment == \'center\', \ | ||
\'stackable-align-top\': alignment == \'top\', \ | ||
\'stackable-align-right\': alignment == \'right\', \ | ||
\'stackable-align-bottom\': alignment == \'bottom\', \ | ||
\'stackable-align-left\': alignment == \'left\', \ | ||
\'stackable-no-arrow\': hideArrow}"> \ | ||
<div ng-if="!hideArrow" class="stackable-arrow"></div> \ | ||
<div ng-transclude></div> \ | ||
</div> \ | ||
</div> \ | ||
</div></div>', | ||
</dialog>', | ||
link: Link | ||
}; | ||
function Link(scope, element) { | ||
function Link(scope, element, attrs, ctrl) { | ||
// link stackable dialog | ||
ctrl.link(scope, element); | ||
// popover not positioned yet | ||
@@ -203,2 +229,3 @@ var positioned = false; | ||
if(state) { | ||
scope.show = state.show; | ||
if(state.show) { | ||
@@ -205,0 +232,0 @@ // close when pressing escape anywhere or clicking away |
25479
725
99