Append and remove values in a link - javascript

So I am using http://isotope.metafizzy.co to filter out different items on a site. The menu should be a "build up" type where when one category is clicked, it filters to those categories, when the next is clicked it adds those newly clicked categories to the existing filter of categories. When its clicked a second time it should remove that categorie from the filter.
More specifically, I have href with #filter and data-filter=".category-name" I need to have a function that would add ", .another-category" to the end of data-filter value for each of the links with name="filters" (or i can use a class instead of if easier)
<ul>
<li>Kitchens</li>
<li>Bathrooms</li>
<li>Living Rooms</li>
<li>Bedrooms</li>
</ul>
I know this function is wrong and doesnt work but its just some pseudo-code
function addFilter(filter) {
names = document.getElementsByName("filters");
for (var name in names) {
name.data-filter = "existing filter, " + filter; // this should be appended to all data-filters
}
}
so basically when a link is clicked it both filters to that category only (lets say kitchens), but also adds the category to the rest of the data-filters (.bedrooms, .kitchens)
javascript or jquery or anything else i may have not realized could work. the documentation for isotope has the option to filter multiple groups of items, but I need it to filter combinations of individual items. Maybe its possible to modify their combination filters to items instead of groups?

See the following article as placed in this post. It should put you in the right direction.
http://www.queness.com/post/7050/8-jquery-methods-you-need-to-know
Stackoverflow question
jQuery - How to add HTML 5 data attributes into the DOM

Well you tagged jQuery, which makes this easy, but I only see you using JS. Anyway, here's one way and some extra info, hope it helps:
jsFiddle {with replication}
jsFiddle {without}
Script
$('li a[name="filters"]').on("click", function(e) {
e.preventDefault();
$(this).data("filter", $(this).data("filter") + ".another-category");
/* and if i wanted to do it without replicating already existing info:
var f = $(this).data("filter");
if (f.indexOf(".another-category") == -1) f += ".another-category";
$(this).data("filter", f); */
});
HTML
<ul>
<li>Kitchens</li>
<li>Bathrooms</li>
<li>Living Rooms</li>
<li>Bedrooms</li>
</ul>
X-tra NFO
jQuery.data(): Biggest Deference - Returns the value that was set
jQuery's .data(): Biggest Deference - Returns the element that was manipulated

Related

Javascript selectors how to only get first ranking a refs

Hi there I'm fiarly new to coding. and doing some javascipt layouting. but I need to make some variables. and don't know how. I want to make a dropdown menu. for this site. bertconinx.com now in order to do the thing I want to do I need to be albe to select a href without having to change any html. let the browser go to the link and then execute some javascript so what I need to do is find a way how to select the specific a href. I need to select the head menu intem without selecting any submen Items. because they should be dropdowns on a clickevent.
I got as far as this..
a href="http://bertconinx.com/category/portrets/">Portrets</a
a href="http://bertconinx.com/category/weddings/">Weddings</a>
should load first and then should dropdown his submenu clickevents.
but slecting the a href seems trick I've tried.
var MenuEvent = document.getElementsByClassName("menu-item").getElementsByTagName("a");
But it does not work.
Any Ideas on how to select them?
thanks.
The documentNode.getElementsByClassName returns a list of items, so while you can call .getElementsByTagName on each one, you can't call the function on the list directly. What you need to do is something like
// initialize an array to hold the anchors we get, and get all menu items on the document
var firstAnchors = [],
menuItems = document.getElementsByClassName('menu-item');
// iterate through the menu items and their specific anchors, adding only the first one of each menu item to our list
for(var menuItem of menuItems){
firstAnchors.push(menuItem.getElementsByTagName('a')[0]);
}
// now, our anchors should be here
console.log(firstAnchors);
var parentMenus = [],
parentMenueElems = document.getElementById("menu-main-nav").children;
for(var parentMenueElem of parentMenueElems){
if(!parentMenueElem){continue;}
var parentMenue = {
"name": parentMenueElem.firstElementChild.text,
"anchor": parentMenueElem.firstElementChild
};
parentMenus.push(parentMenue);
}
console.log(parentMenus)
OutPut:
[
{"name":"Portrets","anchor":element},
{"name":"Weddings","anchor":element},
{"name":"Wild","anchor":element},
{"name":"Commercial Work","anchor":element},
{"name":"About","anchor":element}
]
Example: element --> Portrets
Now you can perform any event on element
parentMenus[2].anchor.click();

How to hide a row of a table which does not contains a specific icon

I have a table with some items and those items can be selected by adding a tick. Check the image attached:
What I need to achieve is to hide the row which does not contain any ticks to be not visible. This is because in my app I have to generate lists of the items contains only ticks in another view. So when I will press the generate button that row will be hidden.
I just want to say if that row does not contain any 'glyphicon-ok' need to be deleted/hidden when I will generate the view with the list of those items.
I tried something like this:
SveCrf.prototype.hideRowWhereNoTicksForm = function () {
var tr = document.getElementsByTagName('tr');
for (var i = 0; i < tr.length; i++) {
switch (tr.item(i).getElementsByTagName('td').item(0).className) {
case "glyphicon-ok":
tr.item(i).style.display = "none";
break;
}
}
}
This doesn't do anything.
I would like to see an example of being able to resolve this issue.
Correct me if I'm wrong but you don't seem to have provided HTML you want to act upon but just a screenshot and a link to some RoR code in the comments that generates the HTML. Also you don't show how you try to execute SveCrf.prototype.hideRowWhereNoTicksForm, and furthermore I'm not really sure at all what you are trying to do with switch/case (I also don't understand what item is supposed to be; this is where providing us with actual HTML might have helped).
In addition, as I've alluded to in some comments of mine, you are really trying to do two things. I don't know if you've seen this Stackoverflow page yet about creating "a Minimal, Complete, and Verifiable example" but I think reviewing that will help improve your StackOverflow experience moving forward (and also for me it validated my suggestion of "divide and conquer").
All of which I think made it hard for you to get the help you desired. In any case below I'm providing some sample HTML with a table containing four rows total, two with a cell that contains the class foo, and two that don't. Beneath that is my non-jQuery code selecting the rows with no cells containing the class foo, and then hiding them; furthermore there is a demo of the same functionality using jQuery at https://repl.it/#dexygen/HideRowsWithNoCellsWithClass
<table border="1">
<tr><td class='foo'>foo</td><td></td><td></td></tr>
<tr><td></td><td>bar</td><td></td></tr>
<tr><td></td><td></td><td>baz</td></tr>
<tr><td class="foo">foo</td><td>bar</td><td>baz</td></tr>
</table>
/*
We cannot call `filter` directly on an HTMLCollection such as returned by
"document.getElementsByTagName('tr')" as it is not a bona fide array, so we use
"[].filter.call()", and we return only those rows that *fail* the test
"row.querySelector('td.foo')", then we loop over these with `forEach` and hide them
*/
[].filter.call(document.getElementsByTagName('tr'), function(row) {
return !row.querySelector('td.foo');
}).forEach(function(row) {row.style.display = 'none'});

How to dynamically get the dynamically created ID in a li

I've been trying to learn js (and a tad of jquery) and I have run into two difficulties when trying to find a way to combine solutions that I find.
Just a little warning that this code is a mix of a few tutorials that I have recently done. I am very new to js.
So I start with a basic html with a few li.
<body>
<ol id="liste">
<li class="active">
</li>
<li>
</li>
<li>
</li>
</ol>
<div id="main_ima">
</div>
<script src="js/main.js"></script>
</body>
I want to create ids for each "li" so in my main.js I add this:
var idVar = $("#liste").find("li").each(function(index){
$(this).attr("id","num-li-"+index);
});
This works great so far. Everytime I add a new li, it gets a new id. I also put it into a var because I will need to use it later.
In th console, If I type idVar, it gives me the whole list of li. If I type idVar[3]. it only gives me the li associated to the [3]. Perfect.
Now I want to get something to appear when one of the li is clicked. For example, I will use the [3]. So I add this to my main.js
var imaContainer = document.getElementById('main_ima')
var listed = document.getElementById('liste');
idVar[3].addEventListener("click", appar);
function appar(){
$(idVar[3]).addClass("active").siblings().removeClass("active");
var imaSel = new XMLHttpRequest();
imaSel.open('GET', 'https://domain.link.to.file.json');
imaSel.onload = function() {
var imaLo = JSON.parse(imaSel.responseText);
renderHTML(imaLo);
};
imaSel.send();
};
function renderHTML(data) {
var htmlS = "";
for (i = 0; i < data.length; i++) {
htmlS += "<p>" + data[i].name + " is a " + data[i].species + ".</p>";
}
imaContainer.insertAdjacentHTML('beforeend', htmlS);
}
Just a side note, I added the add/remove "active" class for CSS.
So when I click the li[3], it works almost as expected. The only thing is when I reclick [3] it produces the result a 2nd time. And again, if I click it a 3rd time, it produces the result a 3rd time, without remove the past results. (which is not totally what I want. Just the 1st result would be better.)
But that is not the main problem I am facing.
I would like the [number] to be dynamically detected, based on the id of the clicked li. I could, in a very ugly way, copy and past this code for every [number] I have. and it would work. But then, what if I want to add more li elements, I would need to add more copy and paste of the above code, giving me possibly huge files for nothing. This is surely not the best way, although it would work.
I'm sure this can be done dynamically.. but that is mostly why I am here. :)
Afterwards, once the dynamic has been added to the clicked li, I would also like the link to be changed dynamically based on the li id. For example, instead of :
imaSel.open('GET', 'https://domain.link.to.file.json');
something like:
imaSel.open('GET', "https://domain.link.to.file" + var +".json");
the var being equal to the [3] number of the clicked li.
In this case, when I try to add a var with a for loop, I always get the "var = max.length" instead of the "var = [id of clicked item]".
So there you have it. Do you need more details?
This is my first JS and/or Jquery try. I've been playing with it for a few days but when I search for answers, when I implement the "solutions" it alwas gives me some new problem. So I am showing you the code that is the closest, IMO, to what I am looking for.
Hopefully, I am not too far away of somehting that works and is not as big as my solutions. :)
Thanks for your time and all help is appreciated.
Here are some suggestions:
You don't need to assign id attributes to your li. You actually never need that id. This will work just as well (note also the > in the selector which makes the find call unnecessary):
var $li = $("#liste > li");
Already now you can address each of the li as $li[3], although that is not the "best practise". Better is $li.get(3). I also like the convention to start the variable with $ when it is the result of a jQuery selection. It gives a clue that you can apply jQuery methods to it.
You don't need to assign a click handler to each li separately. With jQuery on (instead of the native addEventListener) you can assign one event handler for all of them at once.
$li.on('click', apar)
The callback you define for on will have this set to the particular li element that has been clicked, so you can do:
$(this).addClass("active").siblings().removeClass("active");
... without any array lookup.
jQuery offers easy functions for several types of HTTP requests, so you don't need to use XMLHttpRequest. In fact, there is one specifically for getting JSON, so you don't even have to parse the response:
$.getJSON('https://domain.link.to.file.json', renderHTML);
The jQuery index() method can give you the sequence number of that li:
$.getJSON('https://domain.link.to.file' + $(this).index() + '.json', renderHTML);
To replace the inner HTML of a certain element, the jQuery html method can be used:
$('#main_ima').html(htmlS);
Note also how you don't need the DOM native getElementById method, jQuery can look that up for you with the short $('#main_ima').
Example
Here is a working example with a fake JSON serving server:
$("#liste > li").on('click', apar);
function apar() {
$(this).addClass("active").siblings().removeClass("active");
$.getJSON('https://jsonplaceholder.typicode.com/posts/'
+ (1+$(this).index()), renderHTML);
}
function renderHTML(data) {
// This particular JSON request returns an object with body property
var htmlS = data.body;
$('#main_ima').html(htmlS);
}
// On page load, click on the first `li` to automatically load the data for it
$('#liste > li:first').click();
#liste { width: 40px }
.active { background: yellow }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ol id="liste">
<li class="active">load 1</li>
<li>load 2</li>
<li>load 3</li>
</ol>
<div id="main_ima"></div>
The following answers your main concern, how to dynamically get the ID with jquery:
$('.listen-to-me').click(function() { //Add event listener to class
var elementId = $(this).attr('id'); //Get the 'id' attribute of the element clicked
var idNumber = elementId.substring(elementId.indexOf("-") +1); //Get the index of the "-" in the string, and then cut everything prior
alert(idNumber); //The final result
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul>
<li id="test-1" class="listen-to-me">1</li>
<li id="test-2" class="listen-to-me">2</li>
<li id="test-3" class="listen-to-me">3</li>
<li id="test-4" class="listen-to-me">4</li>
<li id="test-5" class="listen-to-me">5</li>
</ul>

Change Text of Array Of links in jQuery

For my school's website they have a dropdown list of courses that you're currently enrolled in on the home page. However, if you see it, it is cluttered full of letters that many people might not want to see.
I already know how I'm going to do this. I'm going to use jQuery to select each list item:
var links = $(".d2l-datalist li .d2l-course-selector-item .d2l-left .vui-link");
This returns an array of <a> elements in text form.
Using links.text("Boo!"); I can set the text of all of them to "Boo!", but I want to change each one individually, using a for/in loop to itterate through each <a> and change the text depending on what the value of the href is.
However, whenever I do this, since the items in the array are strings, I cannot do anything to them with jQuery.
Any help with this is appreciated :)
Here's my code so far (running from a $.getScript() from a JS bookmarklet):
var links = $(".d2l-datalist li .d2l-course-selector-item .d2l-left .vui-link");
//links.text("Boo!");
var count = 1;
for (var link in links) {
link.text("Boo #" + count);
count += 1;
}
Relevant markup: http://hastebin.com/ulijefiqaz.scala
You can use the jQuery .each iterator function.
var links = $(".d2l-datalist li .d2l-course-selector-item .d2l-left .vui-link");
var count = 1;
links.each(function() {
$(this).text("Boo #" + count++);
});

save JSON in HTML list item

I have a javascript where I can create list items in HTML. At the moment I can drag and remove the items with another script. Now I would like to store some information within every list item created, for an example a JSON-object. Then afterwards I save the data in the right order in the database.
Is it possible, or should I go another way?
As Nikhita says you can add values as data-values attributes to the list items. For example if you want to store the id and name atributes you can do as follow, and recover the values with jquery:
<li data-id="1" data-name="name" class="listItemClick"> List item </li>;
$(".listItemClick").click(function(){
var id= $(this).attr("data-id");
var name = $(this).attr("data-name");
//TODO
});
#Javier's answer works if you are using jQuery.
Those attributes can be accessed through regular Javascript as well.
// Make sure you have a valid reference
var el = getElementBySomeMeans();
// Set the value
el.setAttribute("data-test-this", "10");
// Get the value
var v = el.getAttribute("data-test-this");
console.log(v);
// Clear the attribute
el.removeAttribute("data-test-this");
I should mention, for completeness, that there is an HTML5 dataset method that also works on the data attributes, but I personally don't use it since we have to support older browsers at work.
IF you have the luxury, might be worth looking into.
1 - save data in html in any hidden div
2- add data in any unique attribute
<li data-name="' + data-value + '"> List item </li>;
This should do the trick. Append whatever data value and data name you see fit.

Categories