How to make links added from JSON clickable? - javascript

I am trying to append links from a JSON file but their onClick is not working.
HTML:
<li class="nav-item dropdown" id = "views">
<a class="nav-link dropdown-toggle" id="view-type" data-toggle="dropdown" data-selected="high_level" aria-haspopup="true" aria-expanded="false">High Level View</a>
<div class="dropdown-menu" aria-labelledby="view-type" style="height: 35vh; overflow: auto;">
<h7 class="dropdown-header">View Type</h7>
<a class="dropdown-item filter-option active" href="javascript:void(0);" id="high_level">High Level View</a>
</div>
</li>
Javascript:
d3.json(theURL, function(error, data) {
if (error) throw error;
var unique = [];
data.forEach(function(e){
if(unique.indexOf(e.segment) == -1){
unique.push(e.segment);
}
});
unique.forEach(d =>
$('#views .dropdown-menu').append(`<a class="dropdown-item filter-option ecodes" href="javascript:void(0);" id="${d.substring(0, 4)}">${d}</a>`)
)
if($('#all').hasClass('active') == true) {
$('.ecodes').remove();
}
});
$('.filter-option').on('click', function() {
let text = $(this).text();
let selected = $(this).prop('id');
$(this).parent().parent().children('a').text(text);
$(this).parent().parent().children('a').data().selected = selected;
filters[$(this).parent().parent().children('a').prop('id').replace('-','_')] = selected;
$.each($(this).parent().children('a'), function(i,d)
$(d).removeClass('active'); });
$(this).addClass('active');
});
Is there something wrong with my code? I cant seem to figure out why my links aren't working. I need onClick for them to have the class active.

You should use the static element as a starter then delegating the dynamic node(child node) inside the on method
$('dropdown-menu').on('click','.filter-option', function() {
let text = $(this).text();
let selected = $(this).prop('id');
$(this).parent().parent().children('a').text(text);
$(this).parent().parent().children('a').data().selected = selected;
filters[$(this).parent().parent().children('a').prop('id').replace('-','_')] = selected;
$.each($(this).parent().children('a'), function(i,d)
$(d).removeClass('active'); });
$(this).addClass('active');
});

You have to delegate the click to the parent element that exists in the page before you inject new links.
jQuery's on method accepts a selector as the second argument so you can update the following line:
$('.dropdown-menu').on('click', '.filter-option', function() {
let text = $(this).text();
let selected = $(this).prop('id');
$(this).parent().parent().children('a').text(text);
$(this).parent().parent().children('a').data().selected = selected;
filters[$(this).parent().parent().children('a').prop('id').replace('-','_')] = selected;
$.each($(this).parent().children('a'), function(i,d)
$(d).removeClass('active'); });
$(this).addClass('active');
});
Read more: http://api.jquery.com/on/#direct-and-delegated-events

Related

Knockoutjs binds correctly however href on a tag doesn't redirect to the page

I have this html:
<ul class="nav nav-tabs ilia-cat-nav" data-toggle="dropdown" data-bind="foreach : Items" style="margin-top:-30px">
<li role="presentation" data-bind="attr : {'data-id' : ID , 'data-childCount' : Children().length}" style="padding-left: 20px; padding-right: 20px; text-align: center; color: white" class="active-li">
<label id="menu1" data-toggle="dropdown" data-bind="text: Name"></label>
<ul class="dropdown-menu" data-bind="foreach: Children" role="menu" aria-labelledby="menu1">
<li role="presentation"><a role="menuitem" data-bind="text: Name, attr: { 'href': Url} "></a></li>
</ul>
</li>
</ul>
That creates my menu on top using knockoutjs, it works perfectly and href attribute on a tag is filled correctly like href="/site/models#{"catId": "76b4a8ed-1350-46af-8184-3b68029cbd22"}" however when i click on the item, it doesn't redirect to new page. my first thought was maybe its because of hash but it wasn't, so i tried to use target attribute for any of the _self and all others it doesn't work. so my next guess was that there is a javascript method overriding this, so far i haven't found anything. so my question is why doesn't it work?
KnockOut ViewModel:
landing.dataModels.Category = function (_id, _categoryTypeId, _name, _description, _parentId, _children) {
var self = this;
this.ID = ko.observable(_id);
this.CategoryTypeId = ko.observable(_categoryTypeId);
this.Name = ko.observable(_name);
this.Description = ko.observable(_description);
this.ParentId = ko.observable(_parentId);
this.Url = ko.computed(function () {
return '/site/models#{"catId": "' + self.ID() + '"}';
});
this.Children = ko.observableArray([]);
this.getChildren = ko.computed(function () {
return self.Children();
});
_.each(_children, function (item) {
self.Children.push(new landing.dataModels.Category(item.ID, item.categoryTypeId, item.Name, item.Description, item.ParentId, item.Children));
});
};
Update
I have to say that when i right-click on the item and open in new window it does work and shows the page, but its not working on direct left click.
Probably the problem is in the quotes in the generated URL:
href="/site/models#{"catId": "76b4a8ed-1350-46af-8184-3b68029cbd22"}"
The value for href is actually "/site/models#{" leaving the rest of the URL as invalid HTML.
You could try to bind to the escaped URL:
this.Url = ko.computed(function () {
return encodeURI('/site/models#{"catId": "' + self.ID() + '"}');
});
Finally i got tired and i just went with a simple jquery click to make it work:
$(document).ready(function () {
setTimeout(function () {
$(document).on("click", ".ilia-catLink", function () {
var a = $(this).attr("href");
window.location = a;
});
}, 100);
It works this way, but i still wonder why wouldn't that href work on itself.

jQuery target next() html item

hi I have a list of items which is generated like so:
<li class="panel-title">Item 1<i class="fa pull-right fa-plus"></i></li>
<ul class="panel-body">...</ul>
<li class="panel-title">Item 2<i class="fa pull-right fa-plus"></i></li>
<ul class="panel-body">...</ul>
<li class="panel-title">Item 3<i class="fa pull-right fa-plus"></i></li>
<ul class="panel-body">...</ul>
Upon clicking an 'li' item I need only the next 'ul' to expand. Unsure how to solve this & whether next() is the right action
Heres my code
$('li.panel-title > .fa').on("click",function() {
var $currIcon = $(this);
var $contents = $('ul.panel-body');
if($currIcon.hasClass('fa-plus')) {
$currIcon.$contents.next().slideDown();
$currIcon.removeClass('fa-plus');
$currIcon.addClass('fa-minus');
} else if($currIcon.hasClass('fa-minus')) {
$currIcon.$contents.next().slideUp();
$currIcon.removeClass('fa-minus');
$currIcon.addClass('fa-plus');
}
});
Try this
$('li.panel-title > .fa').on("click",function() {
var $currIcon = $(this);
var $contents = $('ul.panel-body');
if($currIcon.hasClass('fa-plus')) {
$currIcon.parent().next().slideDown();
$currIcon.removeClass('fa-plus');
$currIcon.addClass('fa-minus');
} else if($currIcon.hasClass('fa-minus')) {
$currIcon.parent().next().slideUp();
$currIcon.removeClass('fa-minus');
$currIcon.addClass('fa-plus');
}
});
Below is jQuery Code:
$('li.panel-title > .fa').on("click", function() {
var $currIcon = $(this);
var $contents = $($(this).closest('li').next().children('ul'));
if ($currIcon.hasClass('fa-plus')) {
$contents.slideDown();
$currIcon.removeClass('fa-plus');
$currIcon.addClass('fa-minus');
} else if ($currIcon.hasClass('fa-minus')) {
$contents.slideUp();
$currIcon.removeClass('fa-minus');
$currIcon.addClass('fa-plus');
}
});
I appended a codepen. I modified HTML markup a little bit, since ul is directly beneath its parent node ul.
http://codepen.io/wooljs/pen/pEgbkB

bind multiple id using on()

<a id="abc">First</a>
<a id="xyz">Second</a>
$('body').on('click','#a,#b',function(){
btn = $(this).attr('id');
if(btn == "abc"){ //do something };
});
Why my above code worked when I click abc id but not the later button? Did I bind it wrongly?
Your selectors are not correct and do not match your IDs:
$('body').on('click','#abc,#xyz',function(){
var btn = $(this).attr('id');
alert(btn);
if(btn === "abc") {
// Do something
}
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<a id="abc">First</a>
<a id="xyz">Second</a>

How to get which link has been clicked in jquery

Good day...
I have multiple links as below:
<li>Save</li>
<li>Save As</li>
<li>Save And Exit</li>
I wanna know which link has been clicked
I tried something like this:
if ($("#mmSaveForm").click() == "true") {
//do something
}
else if ($("mmSaveAs").click() == "true") {
//Do something
}
else if ($("#mmSaveExit").click() == "true") {
//Do something
}
I tried these links, questions & answers but they are not helping:
How can I get the button that caused the submit from the form submit event?
jQuery: how to get which button was clicked upon form submission?
how to detect which button is clicked using jQuery
jQuery - how to determine which link was clicked
I've been trying this the whole night, please help...
Thank you in advanced...
Why don't you target the class instead, grab the id and then use a switch statement.
$('.itemDisabled').on('click', function () {
var id = this.id;
switch(id) {
case 'mmSaveForm':
// code
break;
case 'mmSaveAs':
// code
break;
case 'mmSaveExit':
// code
break;
}
});
Try to use .is(selector) to identify the element which has been clicked,
$('a.noTxtSelect1').click(function(e){
e.preventDefault();
if($(this).is("#mmSaveForm")){
} else if($(this).is("#mmSaveAs")) {
} else if($(this).is("#mmSaveExit")) {
}
});
If your links have id attributes all starting with 'mm' you could use:
$('a[id^=mm]').on('click', function(){
console.log(this.id);
});
Or on one or more classes:
$('a.itemDisabled').on('click', function(){
-or-
$('a.itemDisabled.noTxtSelect1').on('click', function(){
In the click event, you can use switch to determine the link clicked, which you can fetch using this or $(this)
e.g.:
Demo Fiddle
$('a[id^=mm]').on('click', function () {
switch (this.id) {
case "mmSaveForm":
alert(this.id);
break;
case "mmSaveAs":
alert(this.id);
break;
case "mmSaveExit":
alert(this.id);
break;
}
});
You can use the [attr^="value"] ["starts with"] selector:
$('[id^="mmSave"]').click(function(event){
event.preventDefault();
var action = this.id;
// do your business
});
You're thinking about this the wrong way. In your
$(document).ready(function() {})
you register for click events. So something like
$(document).ready(function() {
$("#mmSaveForm").click(function() {
// handle the click
});
});
may be you can try this
$(function(){
$('.linkclass').click(function(){
var link_text = $(this).text();
alert('the clicked link text is '+ link_text);
});
});
Use common class like a itemDisabled for click event and get id ,
$(".itemDisabled").click(function (e) {
e.preventDefault();
var id = this.id;
if (id === "mmSaveForm") {
} else if (id === "mmSaveExit") {
} else {}
});
No need jquery please look this code
<!DOCTYPE html >
<html >
<head>
<script>
function clickbtn(t)
{
alert(t.id);
/*if(t.id==...)
{
dosomething();
}
else
{
dootherthing();
}
*/
}
</script>
</head>
<ul>
<li>Save</li>
<li>Save As</li>
<li>Save And Exit</li>
</ul>
<body>
</body>
</html>
It work ok .
Hope this help!
This is my html page (Django template):
<div class="col">
{% for blog in blogs %}
<div class="post">
<h3>{{ blog.title }}</h3>
<div class="date">
<p>Created: {{blog.date_created|date:'d M Y'}}</p>
</div>
<p>{{ blog.brief|safe }}</p>
<ul class="nav justify-content-end">
<li class="nav-item">
<a class="nav-link active" href="{% url 'blog:edit' pk=blog.pk %}">Edit</a>
</li>
<li class="nav-item">
<a class="nav-link" id="publish" href="{{blog.pk}}">Publish</a>
</li>
<li class="nav-item">
<a class="btn btn-danger" id="remove" href="{{blog.pk}}">Remove</a>
</li>
</ul>
<br>
</div>
{% endfor %}
</div>
In my javascript file, this is what have and it works.
$(document).ready(function() {
console.log("document is ready!!!")
$('#id_bloglist').on("click", 'a#publish,a#remove', function(e) {
e.preventDefault()
var pk = $(this).attr("href")
if ($(this)[0].id == 'remove'){
console.log("remove link clicked, calling deleteBlog with pk = " + pk)
}
else if ($(this)[0].id == 'publish'){
console.log("publish link clicked, calling publishBlog with pk = " + pk)
}
return false;
});
});

push replaces the old value in the array

Maybe its because I have been working all day and I can't see the problem. But in the following code the alert only shows the last added value and doesn't push the value in the array. :(
window.sortControl = {
sortControlPanel: $('div.sortControl'),
simpleSortCriteriaList: $('div.sortControl .simple'),
advancedSortCriteriaList: $('div.sortControl .advanced'),
dropDownExpander: $('div.sortControl .dropDownExpand.primary'),
dropDownContent: $('div.sortControl .dropdownContent.primary'),
simpleSortCriteria: $('div.sortControl .sortcriteria.simple a'),
simpleSortCheckboxes: $('.simple .checkbox'),
openAdvancedButton: $('.openAdvanced'),
backtoSimpleButton: $('.backtoSimple'),
advancedDropdownContent: $('div.sortControl .advanced .dropdownContent'),
advancedDropdownExpander: $('div.sortControl .advanced .dropDownExpand')
};
$.each(sortControl.advancedDropdownContent.parent(), function () {
var dropdownContent = $(this).find('.dropdownContent');
var input = $(this).find('input');
$(this).find('.dropDownExpand').live('click', function (event) {
sortControl.advancedDropdownContent.not(dropdownContent).hide('fast');
dropdownContent.toggle('fast');
event.preventDefault();
});
var currentSelectedGroups = [];
$(this).find('li a').bind('click', function (event) {
var criteria = $(this).text();
//if (!currentSelectedGroups.inArray($(this).attr('class'), true)) {
input.attr('value', criteria);
currentSelectedGroups.push($(this).attr('class'));
//}
dropdownContent.toggle('fast');
event.preventDefault();
alert(currentSelectedGroups);
});
});
Some of the html:
<div class='sortcriteria advanced'>
<label>Sort by: </label>
<div class='controlWrapper'>
<input type="text" placeholder='Any' value='Any' class='dropDownExpand'>
<span class='icon dropDownExpand' title='Select property type'></span>
<ul class='dropdownContent'>
<li><a href='#' class='price'>Price ascending</a></li>
<li><a href='#' class='price'>Price descending</a></li>
<li><a href='#' class='party'>Party size ascending</a></li>
<li><a href='#' class='party'>Party size descending</a></li>
<li><a href='#' class='bedrooms'>Number of bedrooms ascending</a></li>
<li><a href='#' class='bedrooms'>Number of bedrooms descending</a></li>
<li><a href='#' class='star'>Star rating ascending</a></li>
<li><a href='#' class='star'>Star rating descending</a></li>
</ul>
</div> ...
There are no JavaScript errors.
Content and this script get loaded via ajax
All other statements do what they are supposed to
You need to move var currentSelectedGroups = []; outside the each loop. You declare it once for every instance - they all work on their own version of the variable because it lives in the local scope of the each function.
Remember in javascript functions = scope
As I asked you (and suspected) in my earlier comment, you need to move:
var currentSelectedGroups = [];
outside the .each() loop. As it is you are re-initializing it to an empty array in each iteration of the loop so it never has more than one value in it. You can do that like this:
var currentSelectedGroups = [];
$.each(sortControl.advancedDropdownContent.parent(), function () {
var dropdownContent = $(this).find('.dropdownContent');
var input = $(this).find('input');
$(this).find('.dropDownExpand').live('click', function (event) {
sortControl.advancedDropdownContent.not(dropdownContent).hide('fast');
dropdownContent.toggle('fast');
event.preventDefault();
});
$(this).find('li a').bind('click', function (event) {
var criteria = $(this).text();
//if (!currentSelectedGroups.inArray($(this).attr('class'), true)) {
input.attr('value', criteria);
currentSelectedGroups.push($(this).attr('class'));
//}
dropdownContent.toggle('fast');
event.preventDefault();
alert(currentSelectedGroups);
});
});

Categories