Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

angular-stackables

Package Overview
Dependencies
Maintainers
1
Versions
32
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

angular-stackables - npm Package Compare versions

Comparing version 0.0.5 to 0.0.6

2

bower.json
{
"name": "angular-stackables",
"version": "0.0.5",
"version": "0.0.6",
"description": "AngularJS stackable widgets built on HTML5 dialog.",

@@ -5,0 +5,0 @@ "authors": [

{
"name": "angular-stackables",
"version": "0.0.5",
"version": "0.0.6",
"dependencies": {}
}

@@ -24,2 +24,3 @@ /*!

modal: '=?stackableModal',
persist: '=?persistContent',
disableEscape: '=?stackableDisableEscape',

@@ -35,3 +36,3 @@ closing: '&?stackableClosing',

ng-show="show"> \
<div ng-if="show" class="stackable-content"> \
<div ng-if="show || persist" class="stackable-content"> \
<div ng-transclude></div> \

@@ -127,108 +128,2 @@ </div> \

function stackableDirective() {
return {
scope: {
show: '=stackable',
modal: '=?stackableModal',
disableEscape: '=?stackableDisableEscape',
closing: '&?stackableClosing',
closed: '&?stackableClosed'
},
restrict: 'A',
replace: true,
transclude: true,
template: ' \
<dialog class="stackable" ng-class="{\'stackable-modal\': modal}" \
ng-show="show"> \
<div ng-if="show" class="stackable-content"> \
<div ng-transclude></div> \
</div> \
</dialog>',
controller: ['$scope', Controller],
link: Link
};
function Controller($scope) {
var self = this;
var stackable = $scope.stackable = self;
// close the stackable unless 'closing' callback aborts
self.close = function(err, result) {
var closing = $scope.closing || angular.noop;
var shouldClose = closing.call($scope.$parent, {
err: err,
result: result
});
Promise.resolve(shouldClose).then(function() {
if(shouldClose !== false) {
stackable.error = err;
stackable.result = result;
$scope.show = false;
$scope.$apply();
}
});
};
}
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);
}
dialog.addEventListener('cancel', function(e) {
if(!!scope.disableEscape) {
e.preventDefault();
} else {
scope.stackable.error = 'canceled';
scope.stackable.result = null;
}
});
dialog.addEventListener('close', 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
});
}
});
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;
}
});
}
}
function stackableCancelDirective() {

@@ -260,15 +155,17 @@ return {

template: ' \
<div class="stackable-popover" 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 stackable="state.show"> \
<div class="stackable-popover-content"> \
<div> \
<div stackable="state.show" class="stackable-popover"> \
<div class="stackable-popover-content" style="display:none" \
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> \

@@ -279,120 +176,105 @@ <div ng-transclude></div> \

</div>',
compile: Compile
link: Link
};
function Compile(tElement, tAttrs, transcludeFn) {
var extents = {};
return function(scope, element) {
// measure popover content
transcludeFn(scope.$parent, function(clone) {
var content = angular.element(' \
<div class="stackable-popover-content" style="width:auto"> \
<div ng-if="!hideArrow" class="stackable-arrow"></div> \
</div>');
content.append(clone);
content.css({display: 'none'});
angular.element('body').append(content);
extents.height = content.outerHeight(true);
extents.width = content.outerWidth(true);
// setTimeout hack to ensure content size has settled on chrome
setTimeout(function() {
extents.height = content.outerHeight(true);
extents.width = content.outerWidth(true);
content.remove();
});
function Link(scope, element) {
var doc = angular.element(document);
scope.$watch('state', function(state) {
if(state) {
if(state.show) {
// close when pressing escape anywhere or clicking away
doc.keyup(closeOnEscape).click(closeOnClick);
} else {
doc.off('keyup', closeOnEscape).off('click', closeOnClick);
}
}
// schedule repositioning
setTimeout(function() {
// only reposition if content is shown
var content = element.find('.stackable-popover-content');
if(!content.length) {
return;
}
reposition(content);
});
}, true);
// whenever state changes, reposition popover
scope.$watch('state', function() {
setTimeout(reposition);
}, true);
// clean up any remaining handlers
scope.$on('$destroy', function() {
doc.off('keyup', closeOnEscape).off('click', closeOnClick);
});
// close when pressing escape anywhere or clicking away
angular.element(document)
.on('keyup', closeOnEscape)
.on('click', closeOnClick);
scope.$on('$destroy', function() {
angular.element(document)
.off('keyup', closeOnEscape)
.off('click', closeOnClick);
});
function closeOnClick(e) {
// close if target is not the trigger and is not in the popover
var target = angular.element(e.target);
var trigger = target.data('stackable-state');
if(scope.state !== trigger && target.closest(element).length === 0) {
scope.state.show = false;
scope.$apply();
}
function closeOnClick(e) {
// close if target is not in the popover
var target = angular.element(e.target);
if(target.closest(element).length === 0) {
scope.state.show = false;
scope.$apply();
}
}
function closeOnEscape(e) {
if(scope.enableEscape && e.keyCode === 27) {
e.stopPropagation();
scope.state.show = false;
scope.$apply();
}
function closeOnEscape(e) {
if(scope.enableEscape && e.keyCode === 27) {
e.stopPropagation();
scope.state.show = false;
scope.$apply();
}
}
function reposition() {
// resize popover content
var content = element.find('.stackable-popover-content');
if(!content.length) {
return;
function reposition(content) {
content.css('display', 'none');
var width = content.outerWidth(false);
var height = content.outerHeight(false);
// position popover content
var position = {top: 0, left: 0};
var alignment = scope.alignment || 'center';
var placement = scope.placement || 'top';
if(placement === 'top' || placement === 'bottom') {
// treat invalid 'top' or 'bottom' as 'center'
if(['center', 'top', 'bottom'].indexOf(alignment) !== -1) {
var triggerCenterX = (scope.state.position.left +
scope.state.position.width / 2);
position.left = triggerCenterX - width / 2;
} else if(alignment === 'left') {
position.left = scope.state.position.left;
} else {
// alignment 'right'
position.left = (scope.state.position.left +
scope.state.position.width - width);
}
content.css(extents);
var height = content.outerHeight(true);
var width = content.outerWidth(true);
position.top = scope.state.position.top;
if(placement === 'top') {
position.top -= height;
} else {
position.top += scope.state.position.height;
}
} else {
// else placement is 'left' or 'right'
// position popover
var position = {top: 0, left: 0};
var alignment = scope.alignment || 'center';
var placement = scope.placement || 'top';
if(placement === 'top' || placement === 'bottom') {
// treat invalid 'top' or 'bottom' as 'center'
if(['center', 'top', 'bottom'].indexOf(alignment) !== -1) {
var triggerCenterX = (scope.state.position.left +
scope.state.position.width / 2);
position.left = triggerCenterX - width / 2;
} else if(alignment === 'left') {
position.left = scope.state.position.left;
} else {
// alignment 'right'
position.left = (scope.state.position.left +
scope.state.position.width - width);
}
// treat invalid 'left' or 'right' as 'center'
if(['center', 'left', 'right'].indexOf(alignment) !== -1) {
var triggerCenterY = (scope.state.position.top +
scope.state.position.height / 2);
position.top = triggerCenterY - height / 2;
} else if(alignment === 'top') {
position.top = scope.state.position.top;
if(placement === 'top') {
position.top -= height;
} else {
position.top += scope.state.position.height;
}
} else {
// else placement is 'left' or 'right'
// treat invalid 'left' or 'right' as 'center'
if(['center', 'left', 'right'].indexOf(alignment) !== -1) {
var triggerCenterY = (scope.state.position.top +
scope.state.position.height / 2);
position.top = triggerCenterY - height / 2;
} else if(alignment === 'top') {
position.top = scope.state.position.top;
} else {
// alignment 'bottom'
position.top = (scope.state.position.top +
scope.state.position.height - height);
}
position.left = scope.state.position.left;
if(placement === 'left') {
position.left -= width;
} else {
position.left += scope.state.position.width;
}
// alignment 'bottom'
position.top = (scope.state.position.top +
scope.state.position.height - height);
}
position.top += 'px';
position.left += 'px';
element.css(position);
position.left = scope.state.position.left;
if(placement === 'left') {
position.left -= width;
} else {
position.left += scope.state.position.width;
}
}
};
position.top += 'px';
position.left += 'px';
content.css(position);
content.css('display', '');
}
}

@@ -421,9 +303,23 @@ }

// toggle show on click
element.on('click', function() {
scope.$apply(function() {
var toggleEvent = attrs.stackableToggle || 'click';
if(toggleEvent === 'hover') {
// show on enter, hide on leave
element.hover(function() {
state.show = true;
updateState(state);
scope.$apply();
}, function() {
state.show = false;
updateState(state);
scope.$apply();
});
} else {
// default to click
element.on('click', function(e) {
e.stopPropagation();
state.show = !state.show;
updateState(state);
scope.$apply();
});
});
}

@@ -444,3 +340,2 @@ function resized() {

set(scope, state);
element.data('stackable-state', state);
}

@@ -447,0 +342,0 @@

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc