thesharpieone / angular-off-click Goto Github PK
View Code? Open in Web Editor NEWIts like click, but when you don't click on your element.
License: MIT License
Its like click, but when you don't click on your element.
License: MIT License
Hello,
Thanks for the work, it's a great idea and really helpful.
I tried to use your plugin, but I couldn't make it work in a way it's viable for production.
When I click outside of the element, it takes at least 1scd+ to hide the element.
I believe that's due to the angular and digest lifecycle and I was wondering if you think you could find a workaround (I couldn't fix it).
Best regards.
Without adding off-click-if
the directive does not work.
Edit: plunker showing issues can be found at http://plnkr.co/edit/tqw4WoS74Q0ah2rcP6ND - if you remove off-click-if
the off-click-filter
will not work anymore.
This issue occurred when trying to remove an element that was dynamically added. This plunkr demonstrates the issue. For demonstration sake (as seen in #48), the off-click expression on the <p>
element has been emptied.
Flow:
Click the 'Add Menu button'
Click the button to 'Toggle menu visible'
Click the 'Remove' button in the menu.
Error shows up as 'TypeError: Cannot read property 'length' of undefined' on line 132:
if (OffClickFilterCache[filter].length > 1) {
Think the problem with off-click-filter and ng-repeat is back, at least in my use-case. I believe it has to do with the es6 revision of angular-off-click not using the document query selector anymore. I don't have a codepen or plunkr to demonstrate, but here's my setup code and the console output I've seen from debugging:
I have a custom directive <toolbar-separator>
that I pass in a name to ("document" in this case) and inside the directive the id of the div gets set to that (via <div id={{ctrl.name}}>
). So the end result in the html is:
<toolbar-separator>
<div id="#document"> ... </div>
</toolbar-separator>
<ul off-click-filter="'#document'">
<li ng-repeat=""> ... </li>
</ul>
So, the html is generated correctly.
The goal is for the toolbar-separator to be a modular toggle that expands a toolbar, and the <ul>
below it is an associated area that has controls visible when the toollbar is expanded. Thus, clicking on the <ul>
area should not deactivate the toolbar.
In the console however, I see this:
As you can see, the target is correct (when clicking on the <ul>
), but the currentElem is wrong - it's using the element without the ng-repeated items inside of it and so it doesn't match.
If there's anything else I can do to clarify or assist, don't hesitate to let me know.
This is a great directive. Right now I've downloaded the source file for inclusion in my angular app, but I'd love to just have it via npm. I don't use bower (and neither do many frontend devs these days) so that doesn't work for me.
Thanks for this!
Create tests and hook up to Travis CI
Nice ! Currently using this on a UL / LI combination, works great.
I wonder if its possible to use this on a standard SELECT loading via ng-options.
I can't detect when the select opens and closes. The ng-blur only fires when you click away from the select.
Probably not supported ? But thought I would ask.
The listener's callback isn't triggered immediately, only after another user action.
Using $rootScope.$apply
instead of $rootScope.$evalAsync
worked for me.
Awesome work man! any chance you could get this registered on bower?
Memory leak caused by event listeners not being removed.
I have created a PR fixing the issue:
#52
Can't apply on element that already asks for isolated scope.
Functions can be extracted with $parse
. See http://luxiyalu.com/angular-directive-click-elsewhere/
The latest tag on github is 0.0.2, resulting in bower to install the previous (0.0.2) release. Could you please push the latest tag on github?
Off-click fires when touch device user ends target element drag. I suggest you add a touchmove event handler
document.addEventListener("touchmove", touchMoveHandler, true);
and variable
var touchDrag = false;
Then add
function touchMoveHandler(event) {
touchDrag = true;
}
And at the beginning of offClickEventHandler
if( touchDrag ) {
touchDrag = false;
return;
}
This would prevent off-click from firing when user was dragging target element.
Hey,
Thanks for this directive, it is very handy. Although I have an issue with the off-click-filter
:
This is my element that contain an ng-repeat of item (it's a popup menu) :
<div id="fs-create-menu" off-click="fs.closePanel()" off-click-filter="'#fs-file-creator-launcher'"></div>
Which open using a button like :
<button id="fs-file-creator-launcher"><span>Some text</span></button>
Just for matter of testing as you can see, I have set the id of the button in the off-click-filter
, so it shouldn't trigger the off-click
if I click on the button.
But then it does.
I debugged your source code and tried to understand what went wrong, I can see my filter properly store in the OffClickFilterCache
as an object :
{ "#fs-file-creator-launcher": [ { "jQuery224087994817664495642": { "$appsMenuController": {} }, "$$hashKey": "object:856", "$$ngAnimateParentKey": 1 } ] }
So far so good.
And then I come across here https://github.com/TheSharpieOne/angular-off-click/blob/master/dist/angular-off-click.js#L50
What does OffClickFilterCache['*']
should return you ? Because in my case it's undefined
. I assume it should return the list of filter passed to off-click-filter
, but here I have nothing..
As you could guess, the filters var is []
.
Is there something wrong with my logic ? or is there something wrong with the package ?
Also another thing is that you only compare the target
element, but then if you want to filter an entire DOM element, you would need to filter ALL the ids and class ?
Safari Mobile has a bug described here which is preventing offclick from seeing the click event on the document object.
Hi There,
Looks like there is a minor error on line 41 of offClick.js
It currently says attrs.$observe
instead of attr.$observe
Thank.
Took me a while to figure out what module caused the issue.. I got this error:
Error: [$parse:syntax] Syntax Error: Token '.' not a primary expression at column 1 of the expression [.nxt-drop-menu] starting at [.nxt-drop-menu].
http://errors.angularjs.org/1.2.28/$parse/syntax?p0=.&p1=not%20a%20primary%20expression&p2=1&p3=.nxt-drop-menu%20a&p4=.nxt-drop-menu
at VALIDITY_STATE_PROPERTY (lib.js?version=0.1.0-SNAPSHOT:17583)
at Parser.throwError (lib.js?version=0.1.0-SNAPSHOT:28106)
at Parser.primary (lib.js?version=0.1.0-SNAPSHOT:28081)
at Parser.unary (lib.js?version=0.1.0-SNAPSHOT:28329)
at Parser.multiplicative (lib.js?version=0.1.0-SNAPSHOT:28312)
at Parser.additive (lib.js?version=0.1.0-SNAPSHOT:28303)
at Parser.relational (lib.js?version=0.1.0-SNAPSHOT:28294)
at Parser.equality (lib.js?version=0.1.0-SNAPSHOT:28285)
at Parser.logicalAND (lib.js?version=0.1.0-SNAPSHOT:28276)
at Parser.logicalOR (lib.js?version=0.1.0-SNAPSHOT:28264)
.. maybe when there are breaking changes you should update the version to something different.. like 0.1.0 instead of 0.0.5 ;)
Great module anyway ๐
filter doesn't work if elements to filter are loaded after this directive
I have a use-case in my Angular Material application where I use mdDialog and mdMenu, which inserts html into the dom in document root by default instead of in the tree where they're in the html code at. I would like to propose an off-click-ignore attribute that doesn't trigger the off-click function no matter what, as if it was an off-click-filter except it filters everything.
Consider the following:
<table>
<tr ng-repeat-start="item in list" ng-click="show = true" off-click="show = false"
off-click-filter="'.no-trigger'">{{item}}</tr>
<tr ng-repeat-end class="no-trigger" ng-show="show">I don't want to trigger off-click</tr>
</table>
Clicking on text "I don't want to trigger off-click" does trigger off-click. Maybe it has to do with ng-repeat and table semantics, because the issue is similar to having content inside table element without proper tr and td elements within, which also triggers off-click regardless of table selector.
I want to bring in this commit, with a simple gulp task to transpile, plus serve a minified version.
@TheSharpieOne Is this ok?
at line 96 of the compiled file angular-off-click.js
I'm getting a scope is not defined
console error.
return $parse(attrs.offClickIf)(scope);
from
if (attrs.offClickIf) {
removeWatcher = $rootScope.$watch(function () {
return $parse(attrs.offClickIf)(scope);
}, function (newVal) {
newVal && on() || !newVal && off();
});
} else on();
Within the src offClick.js
file that line is also 96
removeWatcher = $rootScope.$watch(() => $parse(attrs.offClickIf)(scope), (newVal) => {
from
if (attrs.offClickIf) {
removeWatcher = $rootScope.$watch(() => $parse(attrs.offClickIf)(scope), (newVal) => {
newVal && on() || !newVal && off()
});
} else on();
My HTML
<sidebar ng-class="{
'state--open': mainVM.states.sidebar.open
}"
off-click="mainVM.closeSidebar()"
off-click-if="mainVM.states.sidebar.open"></sidebar>
Looks like the recent commit that rewrote the js as ES6 might have a few bugs. For now I've reverted to an older version and everything is working fine.
Ran into this problem in the other issue I submitted, but since the problem in that issue was resolved I felt it better to open this up as a separate issue.
In the scope.$on destroy, setting element = null
is causing a problem with removing filters from the cache. Here's a plunkr demonstrating the issue: https://plnkr.co/edit/SJbU08nQUHcD4yUT3y60?p=preview
Clicking outside of the boxes causes the menus to not be shown and triggers their $destroy functions and throws the aforementioned error. By removing element = null
things seemed to work as intended.
I tried multiple sectors but the off-click still goes through.
Could you consider adding a license to this code? At the moment even though the code is online, it's still assumed to be fully copyrighted and not able to be used in other projects.
The optional off-click-filter attribute is a comma separated list of selectors that will not trigger off-click when they are clicked.
I have the following attribute: off-click-filter=".modal-dialog"
However, I get the following error here
Error: [$parse:syntax] Syntax Error: Token '.' not a primary expression at column 1 of the expression [.modal-dialog] starting at [.modal-dialog].
I would love to be able to install this using npm, and subsequently webpack. A package.json file in the repo would make the process much easier.
I made a change in code.where I make changes.It is as follows:
.directive('offClick', ['$rootScope', '$parse', '$timeout', function ($rootScope, $parse, $timeout) {
$rootScope.$evalAsync(function () {
listener.cb(listener.scope, {
$event: event
});
$timeout(function () { listener.scope.$apply() })
});
If you want to make changes in the code. I'll also use the current version
On scope destroy, the handler and watcher should be deregistered.
We are currently executing specs which validate angular-off-click works correctly on our pages. In the specs we use placeholder divs which have no dimensions. When we simulate a click event it will have a pageX and pageY of 0.
It could also be that on a real page a button is on the upper left and the user clicks on (0, 0). What do you think?
Could we simply remove the following line? https://github.com/TheSharpieOne/angular-off-click/blob/master/offClick.js#L17
I have a couple of directives in my UI that use angular interpolation for setting an element's id. For some reason, when adding a new element the off click doesn't function properly. This plunkr (using 1.0.7) shows the issue.
Flow:
Click the 'Add Menu button'
Click the button to 'Toggle menu visible'
At this point, clicking on either the upper 'menu' row (the green border one with the visible button) or the blue bordered div where the menu shows up at should not hide the menu. While clicking on the green-bordered element works as intended, clicking in the blue-bordered element closes the menu, which is unintended.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.