Change display text when focus is lost - javascript

I have the option to delete an entity by clicking DELETE ENTITY. When this is clicked the words DELETE ENTITY are changed to CLICK AGAIN TO CONFIRM. I want the words to change back to DELETE ENTITY if the focus is lost on the button. I tried using ng-blur="resetConfirmDelete", but that didn't work. Any ideas?
HTML
<!--Delete entity-->
<p class="action-link no-outline" ng-click="setConfirmDelete()" ng-show="!confirmDelete" ng-if="permissions.entities.collaborator">DELETE ENTITY</p>
<p id="delete-confirm" class="action-link no-outline" ng-click="delete()" ng-show="confirmDelete" ng-if="permissions.entities.collaborator">CLICK AGAIN TO CONFIRM</p>
</div>
CONTROLLER
$scope.setConfirmDelete = function () {
$scope.confirmDelete = true;
};
$scope.resetConfirmDelete = function () {
$scope.confirmDelete = false;
}

Try using ngBlur for this: https://docs.angularjs.org/api/ng/directive/ngBlur
<p id="delete-confirm" class="action-link no-outline" ng-blur=resetConfirmDelete()">..</p>
UPD
Then you may make use of some directive that detects click anywhere outside of the specific DOM element, for example like this one:
.directive('clickElsewhere', function($parse, $rootScope) {
return {
restrict: 'A',
compile: function($element, attr) {
var fn;
fn = $parse(attr['clickElsewhere']);
return function(scope, element) {
var offEvent;
offEvent = $rootScope.$on('click', function(event, target) {
if (element.find($(target)).length || element.is($(target))) {
return;
}
return scope.$apply(function() {
return fn(scope);
});
});
return scope.$on('$destroy', offEvent);
};
}
};
});
then in the template you can do:
<p id="delete-confirm" class="action-link no-outline"
click-else-where="resetConfirmDelete()" >

You might be running into a problem using ng-blur because the statements appear to be in a div, which is not a :focus-able element by default. Try using a button instead.

Weird that ng-blur="resetConfirmDelete" didnt work, it is the right solution as much as i know.
Maybe the second <p> is not being focused when it appears there for the focuse is never lost and ng-blur is never activated.
Also try adding the ng-blur to the first <p> instead of the second one, assuming it will be focused when the second one appears.

Editted for better answer..
You need to swap the hide/show between elements and focus one at same time.
<!--Delete entity-->
<div
<p class="action-link
no-outline"
ng-click="setConfirmDelete()"
ng-show="!confirmDelete"
ng-if="permissions.facilities.collaborator">DELETE FACILITY</p>
<p id="delete-confirm"
class="action-link no-outline"
ng-click="delete()"
ng-show="confirmDelete"
ng-focus="confirmDelete"
ng-blur="blurDelete()"
ng-if="permissions.facilities.collaborator">CLICK AGAIN TO CONFIRM</p>
</div>
u'll need this lines:
ng-focus="confirmDelete"
ng-blur="blurDelete()"

Related

Angular directive to pass a attribute on one textbox to another div button

I have one textbox which has some attributes.
<input type="text" code=1 add-Me>
And I have one div which is hidden at first.
<div ng-show="hideMe">
<input type="button" onclick="GetElements(code);">
</div>
So my question here is, I want to make a directive on a click of F2(when the focus is on textbox ), I want to open that hidden div and focus on that button inside div and pass the textbox attribute on that button click.
So far I have made an attribute:
app.directive('addMe', function () {
return function (scope, element, attrs) {
element.bind("keydown keypress", function (event) {
// console.log(scope.$parent.data.name);
if (event.which === 113) {
// What to do now??
}
});
};
});
Can someone help me? Thank you.
I've faced a similar scenario while working with a modal. I came up with a solution using $rootScope. You can call a function while a user changes the first input --
<input type="text" code=1 onclick/onchange="setValueToRootScope(code)">
Now, in your GetElements() function, check the value of the $rootScope.ur_variable and perform operation accordingly.
You can do something like this,
In your JS:
app.directive('addMe', function () {
return function (scope, element, attrs) {
element.bind("keydown keypress", function (event) {
// console.log(scope.$parent.data.name);
if (event.which === 113) {
$scope.codeVar=element.getAttribute("code");
$scope.hideMe=true;
}
});
};
});
Your div will be displayed since the variable "hideMe" has been set to true.
And the value of your code attribute as well is stored in the "codeVar" variable in the $scope so that it can be accessed in that particular controller's scope.
In the HTML part:(If your GetElements function is under your controller's scope)
<div ng-show="hideMe">
<input type="button" ng-click="GetElements(codeVar);">
</div>

How to clone ui-sref

I'm looking to write a directive that allows clicks on an outer element to clone the ui-sref of one of its contained elements such that clicking on the outer element behaves the same as clicking on the .cloned element
<div clone-click=".cloned">
...
<a class="cloned" ui-sref="root.a" ng-if="true">example</a>
<a class="cloned" ui-sref="root.b" ng-if="false">example</a>
...
<a ui-sref="root.c">elsewhere</a>
...
</div>
I tried an attribute directive that triggers the click
app.directive('cloneClick', function() {
return {
restrict: 'A',
scope: {
selector: '#cloneClick'
},
link: function(scope, element) {
element.click(function() {
element.find(scope.selector).not(':disabled').first().click();
})
}
};
})
but this causes an infinite loop or something and doesn't work. How can I make it work? Or is there a better way to achieve this?
You aren't taking into consideration event bubbling. As it is now, any click event on the children will already bubble to the parent at which point you are telling it to click same element again ... thus infinite loop if the target you want is clicked
My suggestion would be to prevent propagation of the event on the <a> .
If the <a> itself is clicked, let browser handle the redirect and if any other part of parent is clicked use $location service to redirect using the href value that ui-sref generates.
Something like:
link: function(scope, element) {
var $link = element.find(scope.selector).not(':disabled').first();
// prevent bubbling on target link
$link.click(function(e) {
e.stopImmediatePropagation()
});
element.click(function(e) {
// make sure target link wasn't element clicked
if (e.target !== $link[0]) { // assumes no child tags in `<a>`
$location.url($link.attr('href'));
}
});
}
You may need to adjust a bit depending on whether or not you are using html5mode
EDIT: it occurs to me after writing this that you may be able to trigger the click on the <a> instead of using $location since the event propagation (bubbling) is still prevented
<ANY clone-click=".is-clone-click:not(:disabled):not(.is-disabled)">
<a class="is-clone-click" ui-sref="root.example">example</a>
</ANY>
I got it working like this.
Some pointer disabled elements were able to be clicked thru making their container the e.target so I added .is-no-clone-click on those containers to ignore them.
app.directive('cloneClick', function() {
var angular = require('angular');
var ignore = '[href], [ui-sref], [ng-click], .is-no-clone-click, label, input, textarea, button, select, option, optgroup';
return {
restrict: 'A',
scope: {
selector: '#cloneClick'
},
link: function (scope, element) {
element.click(function(e) {
if (e.isTrigger) {
return;
}
var cloned = element.find(scope.selector).first();
var target = angular.element(e.target);
if (cloned.length && !cloned.is(target) && !target.is(ignore)) {
cloned.click();
}
});
}
};
});
Cursor can also be added via mouseover and a CSS class for that like
element.mouseover(function() {
element.toggleClass('is-pointer', !!element.has(scope.selector).length);
});
But I didn't end up using this directive because I was able to create a CSS link masking solution to actually solve what I was trying to do instead.

How to clean the input search without hiding the keyboard ? (mobile)

I am using Ionic/AngularJS and that's my question, every time I clean up the input, the keyboard disappears and I don't want that
<ion-header-bar ng-show="searchBoxEnabled">
<div>
<input type="search"
ng-model="query">
<div ng-show="query"
ng-click="query=''"> <!--must ONLY clean the input, but is
also disappearing the keyboard-->
</div>
</div>
<!--must clean the input and disappear the keyboard,
this one is working properly-->
<div ng-click="hideSearchBox(); query=''">
|Cancel
</div>
</ion-header-bar>
and in the javascript side I have this couple functions in order to show and hide the input
$scope.showSearchBox = function() {
$scope.searchBoxEnabled = true;
};
$scope.hideSearchBox = function() {
$scope.searchBoxEnabled = false;
};
I agree that it is probably the blur event on the input that causes the keyboard to go away.
You could solve this with a directive on the button that refocuses on the input following a click (although I have no way to verify whether this would cause a flicker with a keyboard).
Here's an illustrative example where you pass the ID of the element that you want to refocus to:
app.directive("refocus", function() {
return {
restrict: "A",
link: function(scope, element, attrs) {
element.on("click", function() {
var id = attrs.refocus;
var el = document.getElementById(id);
el.focus();
});
}
}
});
and the usage is:
<input id="foo" ng-model="newItem">
<button ng-click="doSomething(newItem)" refocus="foo">add</button>
plunker

Apply delay on ng-blur

I am using ng-focus and ng-blur to show/hide a button. on focus of an input, a button is shown and on blur it is hidden. Show/hide is being performed using ng-show. On click of this button a function gets called.
Live Demo
Issue is that ng-blur us being called first and the button is getting hidden before the click event is fired, hence function which is to be called from that button is never getting called.
I have already fixed it by using setTimeout() but later found that it is not really a good solution. Is there any other way to fix this issue?
use ng-mouseover and ng-mouseleave
change your button to
<button ng-click="click()" ng-show="show||mouseover" ng-mouseover="mouseover=true" ng-mouseleave="mouseover=false">Click to change</button>
demo
why don't you change the $scope.show=false; in the click event of the button.
In other words, remove the blur event, and the click event will be like this.
$scope.click = function(){
alert("fuu")
$scope.text = "We changed it";
$scope.show=false;
}
I think using a bool can help you to determine the state if it's needed to hide or show the button. On mouseover of the button change the bool to determine the execution of blur function.
Try this ways :
HTML :
<div ng-app ng-controller="LoginController">
<div>{{ text }}</div>
<input ng-focus="focus()" ng-blur="blur()"></input>
<button ng-click="click()" ng-show="show==true" ng-mouseover="mouseover()">Click to change</button>
</div>
angularjs :
function LoginController($scope) {
$scope.show=false;
$scope.blurAll = true;
$scope.text = "this thing will change on click";
$scope.focus = function(){
console.log("buu");
$scope.show=true;
}
$scope.blur = function(){
if(blurAll){
console.log("baaa");
$scope.show=false;
}
}
$scope.click = function(){
alert("fuu");
$scope.text = "We changed it";
$scope.show = false;
}
$scope.mouseover = function(){
blurAll = false;
};
}
jsFiddle
use a custom directive which introduce a delay
app.directive('ngBlurDelay',['$timeout',function($timeout){
return {
scope:{
ngBlurDelay:'&'
},
link:function(scope, element, attr){
element.bind('blur',function(){
$timeout(scope.ngBlurDelay,200);
});
}
};
}])

Return to text box after click

I have a text box and an options list where options can be added to the current text that is in that box. The problem I'm having is that when I click on an option, and that option is added to the text, I want the cursor to be put back into the text box so the user can continue typing. Any help is much appreciated.
Text field:
input type='text' ng-model='comment.text' ng-change='userList(comment.text)'
JS:
$scope.addUserToComment = function(user) {
$scope.comment.text += user + " ";
$scope.usersShow = false;
};
Avoid modifying the DOM in the controllers.
edit: but to answer your question, ng-focus was me being lazy.
I would create a directive
angular.module('focus-me', []).
.directive('focusMe', function(){
return {
scope: { watch_this: '=' },
link: function(scope, element, attrs){
scope.$watch('watch_this', function(){
$(element).focus();
}
}
}
});
this gives you two options
input type='text' focus-me='comment.text' ng-model='comment.text' ng-change='userList(comment.text)'
or
input type='text' focus-me='some_obj_attr_you_toggle' ng-model='comment.text' ng-change='userList(comment.text)'
1st will call the watcher function more times than necessary, when you are typing as well (not really a big deal).
2nd will only call the watcher function when you toggle the attr in your addUserTo function.
A simpler way (although you are modifying the dom in the controller) would be:
$scope.addUserToComment = function(user, $event) {
$($event.target).find('css selector to navigate to textbox').focus();
$scope.comment.text += user + " ";
$scope.usersShow = false;
};
in your ng-click add another parameter
ng-click='addUserToComment(user, $event)'
PS. Code might not be 100% correct but you get the idea.
$('a').on('click', '#options', function(){
$('input').focus();
});

Categories

Resources