I have a directive that displays a tree of folders. The directive is recursive to display subfolders.
<div ng-click="toggleOpen()" class="action">
<span ng-if="folder.opened"><img class="icon" src="assets/img/load.png"/></span>
<span ng-if="!folder.opened"><img class="icon" src="assets/img/closed.png"/></span>
{{folder.name}}
{{folder.opened}}
<ul ng-if="folder.children.folder" class="folder">
<li ng-if="folder.opened" ng-repeat="fol in folder.children.folder">
<my-folder folder="fol"></my-folder>
</li>
</ul>
<ul ng-if="folder.children.query" class="folder">
<li ng-if="folder.opened" ng-repeat="query in folder.children.query">
<img class="icon" src="assets/img/copy.png"/>
{{query.name}}
</li>
</ul>
</div>
Each folder has a property opened. When I click on the element I call a function to toggle the opened state:
$scope.toggleOpen = function(){
this.opened = !this.opened;
}
However, whenever I click this the folders aren't closed. When I put a breakpoint on toggleOpen I see that the value of this.opened is always true. Even if it has just been changed to false.
Can anyone help out?
It could be that this isn't referencing what you think it is. Try doing:
var self = this;
$scope.toggleOpen = function(){
self.opened = !self.opened;
}
Related
So essentially I want to keep this as simple as possible, meaning no jquery or bootstrap etc... just straight javascript, HTML and CSS. This is what I have so far
Javscript:
var menuOptions= document.getElementsByClassName("nav");
var hamburger= document.getElementById("nav-btn");
function myFunction() {
hamburger.onclick= menuOptions.style.visibility= 'visible';
}
HTML:
<HTML>
<button onclick="myFunction()">
<span id="nav-btn">
<image src="Menugreen.png" alt="collapsable menu"/>
</span>
</button>
<div class="nav">
<ul>
<li id="Programs"> Programs </li>
<li> T-Shirts </li>
<li id="About"> About </li>
</ul>
</div>
</HTML>
CSS:
.nav {
visibility: hidden;
}
Besides just giving me a solution I would highly appreciate it if you could explain why my current method does not work and why yours does. Thanks in advance!
Two problems:
getElementsByClassName() returns a list, not a single element (though the list may contain just a single element), and that list doesn't have a .style property. You can use menuOptions[0] to access the first (and in this case only) element in the list.
You don't want to say hamburger.onclick= inside your function, because that would be assigning a new onclick handler but your function is already being called from the onclick attribute of your button. (Also, if you were trying to assign a new click handler you'd want hamburger.onclick = function() { /* something */ }.)
So the minimum change to your existing code to get it to work would be to change this line:
hamburger.onclick= menuOptions.style.visibility= 'visible';
...to this:
menuOptions[0].style.visibility = 'visible';
In context:
var menuOptions= document.getElementsByClassName("nav");
var hamburger= document.getElementById("nav-btn");
function myFunction() {
menuOptions[0].style.visibility = 'visible';
}
.nav {
visibility: hidden;
}
<HTML>
<button onclick="myFunction()">
<span id="nav-btn">
<image src="Menugreen.png" alt="collapsable menu"/>
</span>
</button>
<div class="nav">
<ul>
<li id="Programs"> Programs </li>
<li> T-Shirts </li>
<li id="About"> About </li>
</ul>
</div>
</HTML>
If you want repeated clicks on the button to toggle the menu display on and off then you can test the current visibility:
menuOptions[0].style.visibility =
menuOptions[0].style.visibility === 'visible' ? '' : 'visible';
Expand the following to see that working:
var menuOptions= document.getElementsByClassName("nav");
var hamburger= document.getElementById("nav-btn");
function myFunction() {
menuOptions[0].style.visibility =
menuOptions[0].style.visibility === 'visible' ? '' : 'visible';
}
.nav {
visibility: hidden;
}
<HTML>
<button onclick="myFunction()">
<span id="nav-btn">
<image src="Menugreen.png" alt="collapsable menu"/>
</span>
</button>
<div class="nav">
<ul>
<li id="Programs"> Programs </li>
<li> T-Shirts </li>
<li id="About"> About </li>
</ul>
</div>
</HTML>
There are a few reasons why your current setup does not function:
Document#getElementsByClassName returns a collection, and you are treating the result like a DOM element. You need to access an index like [0] to get an actual element.
Your toggle button only works one way, because visibility is set to visible but never set back to none when clicked again.
In myFunction, hamburger.onclick should not be assigned to the expression you chose. I am not sure why you tried to assign another click handler, but in order to make that work you would have needed to set it to a function () { ... }.
Now for my advice:
Use CSS classes to control whether the menu is hidden or not, rather than messing around with the style property in your JS. You can use the classList property of DOM elements to .add(), .remove(), and .toggle() a specific class when myFunction is run. I have chosen to use toggle because I think that most suits your use case.
Use element.addEventListener instead of HTML attributes like onclick.
Snippet:
var menuOptions = document.getElementsByClassName("nav")[0]
var hamburger = document.getElementById("nav-btn")
hamburger.parentNode.addEventListener('click', function myFunction() {
menuOptions.classList.toggle('hidden')
})
.nav.hidden {
visibility: hidden;
}
<button>
<span id="nav-btn">
<img src="Menugreen.png" alt="collapsable menu"/>
</span>
</button>
<div class="nav hidden">
<ul>
<li id="Programs"> Programs </li>
<li> T-Shirts </li>
<li id="About"> About </li>
</ul>
</div>
I have three <ul>s that expand when their buttons are clicked. Not all three <ul>s will show up - only when there is a notification to show. I hard-coded the values for now, but I can instantiate them on an as-needed basis.
Right now, they cover each other when they expand. I would like the others to move when a list is expanded so they don't cover each other. I was thinking of getting the index of the one whose button is clicked and then resetting the bottom style of the others. I need to get the index of the <ul> parent of the button that was clicked, probably using jQuery but straight JavaScript is fine as well. Can anyone help?
Here is my code:
<div id="NotificationDiv">
<ul id="noticeLead" class="notification_base notification_Lead"><button id="notification_button">Lead Notice</button>
<div>
<li id="urlLead" class="notification_urlNotice notification_notice">
<a target="_blank" >Check Lead #1</a>
</li>
<li id="urlLead" class="notification_urlNotice notification_notice">
<a target="_blank" >Check Lead #2</a>
</li>
</div>
</ul>
<ul id="noticeTask" class="notification_base notification_Task"><button id="notification_button">Task Notice</button>
<div>
<li id="urlTask" class="notification_urlNotice notification_notice">
<a target="_blank" >Check Task #5</a>
</li>
<li id="urlTask" class="notification_urlNotice notification_notice">
<a target="_blank" >Check Task #6</a>
</li>
<div>
</ul>
<ul id="noticePolicy" class="notification_base notification_Policy"><button id="notification_button">Policy Notice</button>
<div>
<li id="urlPolicy" class="notification_urlNotice notification_notice">
<a target="_blank" >Check Policy #3</a>
</li>
<li id="urlPolicy" class="notification_urlNotice notification_notice">
<a target="_blank" >Check Policy #4</a>
</li>
</div>
</ul>
</div>
And in the $(document).ready, I have:
$('.notification_base').on('click', 'button', function(){
$(this).closest('.notification_base').find('.notification_urlNotice').slideToggle();
});
Try this:
var myParentId; //Here you'll store the id of the clicked element
$('.notification_base').on('click', 'button', function(){
$(this).closest('.notification_base').find('.notification_urlNotice').slideToggle();
myParentId = $(this).attr("id");
});
Thank you everyone for your input. I changed my structure to a table assigning .parent class to the header row and .child class to the data row and put this code in the jQuery ready function and it works great.
function getChildren($row) {
var children = [];
while($row.next().hasClass('child')) {
children.push($row.next());
$row = $row.next();
}
return children;
}
$('.parent').on('click', function() {
var children = getChildren($(this));
$.each(children, function() {
$(this).toggle();
})
});
I have a banner which is something like this:
<ul id="carousel">
<li id="item1">
<div onclick="window.open('mylinkhere.com,'_blank')" style="cursor:pointer;margin-left:-436px;width:996px;height:100%">
</div>
</li>
<li id="item2">
<div onclick="window.open('myotherlinkhere.com,'_blank')" style="cursor:pointer;margin-left:-436px;width:996px;height:100%">
</div>
</li>
</ul>
I need to access the links written in onclick attribute i.e. mylinkhere.com
I tried
var banners = $($("#carousel")[0]).children().filter("li");
var b_items = $(banners[0]).children().filter("div");
attr_val = $(".b_items")[0].attr("onclick");
But i couldn't. By the way i don't know from the start that which item will be in the carousel because it's randomized by another function. So i cannot access them with item1 item2 ect.
Thanks.
You can set the url in a data attribute and read easily like this:
<ul id="carousel">
<li id="item1">
<div data-url="mylinkhere.com" onclick="window.open($(this).data('url'),'_blank')" style="cursor:pointer;margin-left:-436px;width:996px;height:100%">
</div>
</li>
<li id="item2">
<div data-url="myotherlinkhere.com" onclick="window.open($(this).data('url'),'_blank')" style="cursor:pointer;margin-left:-436px;width:996px;height:100%">
</div>
</li>
</ul>
To read:
var b_items = $(banners[0]).children().filter("div");
var link = $(b_items).data('url');
See this fiddle:
http://jsfiddle.net/Pontual/pugytfwu/
For me, the following code works as expected (Chrome 44, jQuery 2.1.3):
var s = jQuery('#carousel li div');
s.each(function(i,node) {
alert(jQuery(node).attr('onclick'));
});
http://jsfiddle.net/aavf1450/
Possible problem is that in your code, you do not wrap the element into $(...), so .attr() is not a valid function, as using indexers on a jQuery object returns raw HTML elements.
here is my html, I'm trying to grab the value of 'link'
<li class="nav-parent nav-expanded">
<a>
<i class="licon-layers" aria-hidden="true"></i>
<span>Virtual Servers</span>
</a>
<ul id="vms" class="nav nav-children" style="">
<li value="0">
<a link="i-2-20-VM">puppet-srv2</a>
</li>
<li value="0">
<a link="i-2-18-VM">puppet-srv1</a>
</li>
<li value="0">
<a link="i-2-24-VM">testing</a>
</li>
</ul>
Here Is what I have tried so far, but it isn't working:
$("#vms").on("click", "li", function() {
var href = $(this).children('a').find('link').attr();
console.log(href);
});
I'm not sure what I'm doing wrong, your help is highly appreciated
You trying to find attribute link using .find('link') code. Since the child element already founded, then just capture it attribute using .attr(). Instead of that, try following code:
Change this:
var href = $(this).children('a').find('link').attr();
into
var href = $(this).children('a').attr('link');
or you can use code below also:
$("#vms").on("click", "li", function() {
var href = $(this).find('a').attr('link');
console.log(href);
});
AND i read your comment that sound :
I'm using that just to hold value of VM name
If so, you can add data attribute for user defined attribute like below :
<a data-link="i-2-20-VM">puppet-srv2</a>
Then to get it value, just use the .data() function like below:
var href = $(this).find('a').data('link');
I create a menu with ajax load. I have 4 zones and each zone have states. What i want is on hover on zone, i need to display all states in that zone. I write following code
HTML
<ul class="zoneLevel">
<li id="1" onmouseover="get_states_list(this.id);">East Zone
<span id="stateContainer" style="display:none;">States</span>
</li>
<li id="2">West Zone</li>
<li id="3">North Zone</li>
<li id="4">South Zone</li>
</ul>
JAVASCRIPT
<script>
function get_states_list(zone_id) {
//alert(zone_id);
var last_slug_a1 = $(".homeLeftContainer .single:last").attr("id");
$('span#stateContainer').html('<img src="img/loader.gif">');
$.post("modules/frontend/ajax/load_state.php?action=get&zone_id="+zone_id,
function(data){
if (data != "") {
$("span#stateContainer").html(data);
}
});
$(".stateContainer").css("display", "block");
$(".stateHederMenu").css("display", "block");
}
</script>
everything's good.
Problem started when i mouse hover to state (which i get with ajax file), it again call get_states_list(this.id) function. Can you please point the error.
It's because again you are hovering the li, the actual span is inside the li and hence the function is triggered again. So just use another tag maybe <a>,<p>,<span> or anything after li and close the word. so it wont trigger again unless you mouse over to the word.
<ul class="zoneLevel">
<li id="1" >
<a onmouseover="get_states_list(this.id);">East Zone</a>
<span id="stateContainer" style="display:none;">
States
</span>
</li>
<li id="2">West Zone</li>
<li id="3">North Zone</li>
<li id="4">South Zone</li>
</ul>
Example with jQuery
$('.zoneLevel li').one('mouseover',function (){
get_states_list($(this).attr('id'));
})
And fiddle for this situation fiddle