ng-blur how to not affect all html element - javascript

I want to be able to click some part of page to not have it call the hideAll function
app.controller('NotificationController', function($scope, $http) {
$scope.visible = true;
$scope.changeStatus = function(){
$scope.visible = !$scope.visible;
};
$scope.hideAll= function(){
$scope.visible=false;
};
});
Here is a link showing this:
Press
I want it so that when press on page this block I don't want to trigger the blur
<div class="notifications js-notifications" ng-init="visible=false" ng-show="visible">
....
</div>
Any idea how I make this work?
EDIT:
Full html:
<li id="notifications" ng-app="notifications" ng-controller="NotificationController as notification">
<a href="#" ng-disabled="checked" ng-click="changeStatus()" ng-blur="hideAll()" class="button-default show-notifications js-show-notifications active">
<i class="fa fa-bell-o" style="font-size: 17px;">
<div class="notifications-count js-count" data-count="<% notys.length %>"><% notys.length %></div>
</i>
</a>
<div class="notifications js-notifications" ng-init="visible=false" ng-show="visible">
<h3>Notifications</h3>
<ul class="notifications-list">
<li class="item no-data">You don't have notifications</li>
<li ng-repeat="x in notys" class="item js-item" data-id="<% x.id %>">
<a href="<% x.project_id %>" class="notification-link">
<div class="details">
<span class="title">New group created: <b> <% x.subject %> </b>. New project assigned to you <b> <% x.body %> </b></span>
<span class="date"><% x.created_at %></span>
</div>
</a>
</li>
</ul>
Show all notifications
</div>
</li>

You might need a custom blur directive to handle events on a separate notification container. Something along these lines:
directive('customBlur', function(){
return {
restrict: 'A',
scope: {
'customBlur': '='
},
link: function(scope, element, attr) {
element.on('click', function(event){
var targetAttr = angular.element(event.target).attr('custom-blur')
if (typeof targetAttr !== 'undefined' && scope.customBlur) {
scope.$apply(function(){
scope.customBlur = false;
});
}
});
}
}});
Here is a working plukner

Description given in W3 specification docs,
blur
The blur event occurs when an element loses focus either via the pointing device or by tabbing navigation. This event is valid for the following elements:
LABEL, INPUT, SELECT, TEXTAREA, and BUTTON.
Bubbles: No
Cancelable: No
Context Info: None
It will give you unpredictable output for other tags. If you have noticed, div tag doesn't capture focus hence no blur event.
But if you want to use event like blur, you can create custom directive which can be combinations of these four events DOMFocusOut, DOMFocusIn, mouseenter or mouseover, mouseleave.

Related

Image Picker isn't calling onchange when selected

My issue is that my image-picker.js doesn't trigger the onchange when selected by clicking the image. https://rvera.github.io/image-picker/
Although, when actually selecting from the dropdown, it does trigger the onchange.
I have the following:
<%= ff.select :image_file_id, options_for_select(#image_files.map { |image| [image.id, {'data-img-src'=>image.image_file_url(:thumb)}]}), {:include_blank => 'Choose None'}, class: "image-picker", id: "tshirt-design" %>
<script>
var images = <%= images_2.to_h.to_json.html_safe %> // this is an array from ruby
document.getElementById("tshirt-design-<%= "#{ff.object.print_location.id}" %>").addEventListener("change", function(){
updateTshirtImage<%= "#{ff.object.print_location.id}" %>(images[this.value]);
}, false);
//image-picker
var imgSetting<%= "#{ff.object.print_location.id}" %> = {
hide_select: false,
show_label: true,
};
$(document).ready(function () {
$(".image-picker-<%= "#{ff.object.print_location.id}" %>").imagepicker(imgSetting<%= "#{ff.object.print_location.id}" %>);
});
</script>
Image picker produces this (this is a visual and when the thumnail is selected, is changes the select field in the select dropdown):
<ul class="thumbnails image_picker_selector">
<li>
<div class="thumbnail selected">
<img class="image_picker_image" src="https://example.s3.amazonaws.com/example">
<p>1</p>
</div>
</li>
<li>
<div class="thumbnail">
<img class="image_picker_image" src="https://example.s3.amazonaws.com/example">
<p>1</p>
</div>
</li>
<li>
<div class="thumbnail">
<img class="image_picker_image" src="https://example.s3.amazonaws.com/example">
<p>1</p>
</div>
</li>
....
</ul>
This is under the select field basically shows the images available for select and when you select them, it changes the select field. Thin on form submit, it does everything correctly as if selected in the drropdown. The issue is that its not triggering the actual select is changes when clicked on the thumbnails. I would like to same change efect trigger to happen when selecting an image from the dropdown and when clicking the thumbnail that changes the select field.
I tried this:
document.getElementsByClassName("thumbnail").addEventListener("select", clickImage);
function clickImage() {
document.getElementById("tshirt-design-<%= "#{ff.object.print_location.id}" %>").addEventListener("change", function(){
updateTshirtImage<%= "#{ff.object.print_location.id}" %>(images[this.value]);
}, false);
};
and this:
document.getElementsByClassName("thumbnail").addEventListener("change", clickImage);
function clickImage() {
document.getElementById("tshirt-design-<%= "#{ff.object.print_location.id}" %>").addEventListener("change", function(){
updateTshirtImage<%= "#{ff.object.print_location.id}" %>(images[this.value]);
}, false);
};
Error:
Event listener is not a function
I've tried a other ways but are not notable.
How can I achieve allowing a trigger when the image is chosen to do the same function as when the image is chosen from the select dropdown?
I need the same event that happens when:
document.getElementById("tshirt-design-<%= "#{ff.obje...
To happen with:
<li>
<div class="thumbnail">
<img class="image_picker_image" src="https://example.s3.amazonaws.com/example">
<p>1</p>
</div>
</li>
With document.getElementsByClassName("thumbnail") you get an Array of HTMLCollection elements that contain all html elements who match with your search you need to iterate on each of them for use each addEventListener of the childs of this array.
Example:
[].forEach.call( document.getElementsByClassName("thumbnail"), function( element ){
element.addEventListener("change", clickImage);
} );

accessing angular HTML from custom controller

OK, I have a custom template I am using where i have several accordions containing lists where the user can click on the option and it becomes active. However I cannot access the parent scope in the controller to change remove the active class from the previously clicked item.
Basically what I want is when a user clicks on a list item, it becomes active and the other items become inactive.
Here is the plunker: http://plnkr.co/edit/d5kHjH?p=preview
Here is the pertinent code:
.run(function(formlyConfig) {
formlyConfig.setType({
name: 'label',
template: `<div ng-init= "active = false">
<a li class="list-group-item small" ng-click="addActive(); active = !active" ng-class="{'active': active === true}"><span class="glyphicon glyphicon-chevron-right"></span> {{to.label}}</li></a>
</div>`,
controller: function($scope) {
$scope.addActive = function() {
$(this).parent().children().removeClass("active");
$(this).addClass("active");
$scope.model.PROC = $scope.to.label;
console.log($scope.model.PROC);
};
}
});
})
I want to be able to add the inactive class to the previously created items, which are being called from an ng-repeat from here in the HTML:
<uib-accordion close-others="true">
<ul class="list-group">
<div uib-accordion-group="" class="panel-primary" ng-repeat="accordion in vm.accordions" active="accordion.active" is-open="isopen">
<uib-accordion-heading ng-click="isopen=!isopen">
<span class="label label-info pull-left">{{accordion.label}}</span>
{{accordion.title}}
</uib-accordion-heading>
<formly-form model="accordion.form.model" fields="accordion.form.fields" form="vm.form" options="accordion.form.options"></formly-form>
</div>
</ul>
</uib-accordion>
The formly-form line is where the template item are being added in on by one

How to prevent button click from collapsing pane

I have a ui-bootstrap pane (header & body) with a button on the header. Clicking the header area should collapse the body. Clicking the button should just activate an alert popup. Unfortunately, clicking that button ALSO collapses the pane. I suspect that the pane behind the button is somehow capturing the click. How can I prevent this?
Here's the plunker:
http://plnkr.co/edit/teCnC7KtvlQtosZurlqD?p=preview
<div class="panel panel-primary">
<div class="panel-heading" ng-click="vm.onClickHeader()">
<span ng-hide="vm.collapsed" style="padding-top: 8px">
<span ng-click="vm.onClickBtn()"><i class="fa fa-chevron-left fa-2x"></i></span>
</span>
</div>
<div class="panel-body" ng-hide="vm.collapsed" style="padding: 2px; padding-right: 4px">
<div>Click the button above to hide me!</div>
</div>
</div>
var app = angular.module('app');
app.directive('myPanel', MyPanel);
function MyPanel() {
return {
templateUrl: 'my-panel.html',
restrict: 'E',
controller: MyController,
controllerAs: 'vm',
scope: true
};
};
function MyController() {
this.collapsed = false;
this.onClickBtn = function onClickBtn() {
alert('click!')
};
this.onClickHeader = function(evt) {
this.collapsed = !this.collapsed;
}
}
The problem is the click event is propagating up the DOM from the <span>. You can add a $event.stopPropagation() to your ng-click directive. (Some people don't like this because they feel it's "dirty" to add such code into a directive so you could always pass $event as a parameter on vm.onClickBtn() and call .stopPropagation() in your controller.)
<span ng-click="vm.onClickBtn(); $event.stopPropagation();"><i class="fa fa-chevron-left fa-2x"></i></span>
On inner ng-click just stop event bubbling by calling stopPropagation on $event object.
<span ng-click="vm.onClickBtn();$event.stopPropagation()">
<i class="fa fa-chevron-left fa-2x"></i>
</span>
Demo here

ng-click not firing $scope.doSomething(), onclick for same function works

The controller I'm using is:
angular.module('app.PostView', [])
.controller('PostViewCtrl', function($scope, $http, Constants) {
$scope.posts = [];
$scope.doSomething = function(){
console.log("in doSomething");
}
$http.get(Constants.POST_URL)
.then(function (response){
console.log(response);
var post = new PostFactory(response.data);
$scope.posts.push(post);
});
})
The view for the controller is
<div ng-repeat="post in posts" >
<div class="home-container">
<div id="details-container">
<!-- using single item Array instead of single iftem to fix linkify bug -->
<div ng-bind="post.desc"></div>
<span class="item-note single-post-details">
<!-- <div class="time-text">{{post.id}}</div> -->
<div class="title" >{{post.title}}</div>
</span>
<a ng-click="doSomething()" href="#" >{{post.name}}</a>
</div>
</div>
</div>
If I replace ng-click with onclick then doSomething is triggered. Currently it is not. The same Controller and html code in other controller/views does work.
When you clicking on the anchor, it change the routing as http://url/#, that listen by the $routeProvider & ng-view loads the default view and template as you are seeing on your side.
Basically you need to remove href="#" from your anchor link or just put href="" blank in that anchor. That would fix your problem.
<a ng-click="doSomething()" href="" >{{post.name}}</a>
Remove href completely
<a ng-click="doSomething()"
style='cursor:pointer' >{{post.name}}</a>

In Angular-Kendo treeview, using a class name to hide/display a span element

I'm using the Angular-Kendo UI treeview widget in conjunction with the k-template directive to display a list of icons to the right of each tree node.
With this way of doing it, my jquery .click() event should hide/show my reptIcons span, but it's only working on the very first tree node at the top.
It should work on every node I click on, but it's reverting to the first node in my tree.
Here's an image to show exactly what I mean:
Here is the html with the kendo-tree-view directive and my custom data-toggle-tree-icons directive:
<div id="" class="reports-tree" kendo-tree-view="nav.treeview"
k-options="nav.treeOptions"
k-data-source="nav.reportsTreeDataSource"
k-on-change="nav.onTreeSelect(dataItem)" >
<span class="tree-node" k-template>
{{dataItem.text}}<data-toggle-tree-icons/>
</span>
and then the javascript to handle the click event:
$('.reports-tree').click(function (e) {
$("span[class$='reptIcons'").hide();
$("#myIcons").closest('span').css("display", "inline");
$("#myIcons").css("margin-left", "5px");
});
The directive code is:
directive('toggleTreeIcons', function ($compile) {
// on Kendo treeview, using the k-template option to embed tree icons
return {
restrict: 'AE',
templateUrl: 'app/shared/include/treeicons-include.html'
}
});
contents of treeicons-include.html
<span id="myIcons" class="reptIcons" style="display: none; width: 50px;">
<a title="add new folder" ng-click="nav.addAfter(nav.selectedItem)"><i class="fa fa-folder-open"></i></a>
<a title="add report here" ng-click="nav.addBelow(nav.selectedItem)"><i class="fa fa-plus"></i></a>
<a title="remove" ng-click="nav.remove(nav.selectedItem)"><i class="fa fa-remove"></i></a>
<a title="rename" onclick="showRename(this);"><i class="fa fa-pencil"></i></a>
</span>
Ideally I'd like to use the tree-node class above, and when a tree node is selected I would use the jQuery .click() to show the myIcons span shown above.
I'm having particular trouble figuring out the best way to wire up that .click() event above. And I know I'm so close to nailing this.
thank you !
Bob
You may be able to do this in your k-on-change="nav.onTreeSelect(dataItem)". I can't see the full implementation, but best guess would suggest you can do something like this, where $(this) ideally is the treeview node selected.
.onTreeSelect = function(dataItem) {
$('.reports-tree .reptIcons').hide();
$(this).closest('.reptIcons').css({'display : inline', 'margin-left' : '5px'})
}
Edit
Per suggestion in the discussion, if the simplistic approach above will not suffice, a custom directive can be crafted to handle this as such
.directive('toggleMe', ['$compile', function ($compile) {
return {
restrict: 'AE',
transclude: true,
template: '<span id="myIcons" class="reptIcons" style="display:inline;width:50px;align:right;">' +
' <a title="add new folder" ng-click="nav.addAfter(nav.selectedItem)"><i class="fa fa-folder-open"></i></a> ' +
'<a title="add report here" ng-click="nav.addBelow(nav.selectedItem)"><i class="fa fa-plus"></i></a> ' +
'<a title="remove" ng-click="nav.remove(nav.selectedItem)"><i class="fa fa-remove"></i></a> ' +
'<a title="rename" onclick="showRename(this);"><i class="fa fa-pencil"></i></a>' +
'</span>',
link: function (scope, elem, attrs) {
}
}
}])
With implementation
<li ng-repeat="item in nav.items">
<span tabindex="-1" ng-click="nav.onItemSelect(item)" ng-blur="nav.selected = null">
<span>{{item}}</span>
<data-toggle-me ng-show="nav.selected === item"></data-toggle-me>
</span>
</li>
.controller('NavBarCtrl',['$scope', function($scope) {
var nav = this;
nav.items = ['Item A', 'Item B', 'Item C'];
nav.onItemSelect = function(item) {
nav.selected = item;
}
}]);
JSFiddle Link

Categories