How should I edit strings across many instances of the same html? - javascript

I've got this code below, with different data, repeated over 10 times on the page I am working on:
HTML:
<div class="kpaGraph">
<p>Target: 43%</p>
<div class="progress">
<div class="bar"></div>
</div>
</div>
<div class="kpaBottom">
<div class="strong">
<p>311</p>
</div>
<div class="weak">
<p>number of teachers trained</p>
</div>
</div>
I want to alter the number in div.strong p (311) based on the number in div.kpaGraph p (43%) in the same manner across all instances of this code with Javascript/ jQuery. What is the cleanest way to do this? Should I select all $('div.kpaGraph p') and then use each() Or should I create a function and run it on all of them?
Thanks!

You can use the following to find the proper element in conjuntion with an .each() on $('div.kpaGraph p'):
$(this).parent().next('div.kpaBottom').find('div.strong p')
For example, using the following will take the value in the kpaGraph p node and append it to the p node in the following kpaBottom node:
$('div.kpaGraph p').each(function () {
$(this).parent().next('div.kpaBottom').find('div.strong p').html('foo');
});
jsFiddle example

There are a few ways.
You can use "next".
$('.kpaGraph').each(function(){
var $kpaStrong = $(this).next('.kpaBottom .strong p');//this is the elm that has 311
});
Or you have to somehow create a relation between them so you know they go together, like a common parent.
<div class="kpaWr">
<div class="kpaGraph">
<p>Target: 43%</p>
<div class="progress">
<div class="bar"></div>
</div>
</div>
<div class="kpaBottom">
<div class="strong">
<p>311</p>
</div>
<div class="weak">
<p>number of teachers trained</p>
</div>
</div>
</div>
Then with jQuery you can select it like so:
$('.kpaGraph').each(function(){
var $kpaStrong = $(this).closest('.kpaWr').find('.kpaBottom .strong p');//this is the elm that has 311
});

Something like this might be pretty clean too:
$("div.strong p").text(function(index, text){
return $(this).closest("div.kpaBottom").prev("div.kpaGraph").find("p").text();
});
That would change the text to Target: 43% in your example.

Related

Link simillary name classes so that when one is clicked the other is given a class

Basically, I'm asking for a way to optimize this code. I'd like to cut it down to a few lines because it does the same thing for every click bind.
$("#arch-of-triumph-button").click(function(){
$("#arch-of-triumph-info").addClass("active-info")
});
$("#romanian-athenaeum-button").click(function(){
$("#romanian-athenaeum-info").addClass("active-info")
});
$("#palace-of-parliament-button").click(function(){
$("#palace-of-parliament-info").addClass("active-info")
});
Is there a way to maybe store "arch-of-triumph", "romanian-athenaeum", "palace-of-parliament" into an array and pull them out into a click bind? I'm thinking some concatenation maybe?
$("+landmarkName+-button").click(function(){
$("+landmarkName+-info").addClass("active-info")
});
Is something like this even possible?
Thanks in advance for all your answers.
EDIT: Here's the full HTML.
<div class="landmark-wrapper">
<div class="page-content landmark">
<div class="heading span-after">
<span>Arch of Triumph</span>
</div>
<div class="landmark-button" id="arch-of-triumph-button"></div>
</div>
</div>
<div class="landmark-wrapper">
<div class="page-content landmark">
<div class="heading span-after">
<span>Romanian Athenaeum</span>
</div>
<div class="landmark-button" id="romanian-athenaeum-button"></div>
</div>
</div>
----------------------------------------------------------
<div class="landmarks-info-wrapper">
<div class="landmark-info" id="arch-of-triumph-info">
<div class="info-landmark section">
<span class="landmark-title">Arch of Triumph</span>
<span class="landmark-coord">44°28′1.99″N 26°4′41.06″E</span>
</div>
</div>
<div class="landmark-info" id="romanian-athenaeum-info">
<div class="info-landmark section">
<span class="landmark-title">The Romanian Athenaeum</span>
<span class="landmark-coord">44.4413°N 26.0973°E</span>
</div>
</div>
Assuming you're not able to modify your HTML markup (in which case with use of CSS classes would be cleaner), a solution to your question would be as shown below:
// Assign same click handler to all buttons
$("#arch-of-triumph-button, #romanian-athenaeum-button, #palace-of-parliament-button")
.click(function() {
// Extract id of clicked button
const id = $(this).attr("id");
// Obtain corresponding info selector from clicked button id by replacing
// last occurrence of "button" pattern with info.
const infoSelector = "#" + id.replace(/button$/gi, "info");
// Add active-info class to selected info element
$(infoSelector).addClass("active-info");
});
Because each .landmark-button looks to be in the same order as its related .landmark-info, you can put both collections into an array, and then when one is clicked, just find the element with the same index in the other array:
const buttons = [...$('.landmark-button')];
const infos = [...$('.landmark-info')];
$(".landmark-button").click(function() {
const i = buttons.indexOf(this);
$(infos[i]).addClass('active-info');
});
This does not rely on IDs at all - feel free to completely remove those from your HTML to declutter, because they don't serve any purpose now that they aren't being used as selectors.
Live snippet:
const buttons = [...$('.landmark-button')];
const infos = [...$('.landmark-info')];
$(".landmark-button").click(function() {
const i = buttons.indexOf(this);
$(infos[i]).addClass('active-info');
});
.active-info {
background-color: yellow;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="landmark-wrapper">
<div class="page-content landmark">
<div class="heading span-after">
<span>Arch of Triumph</span>
</div>
<div class="landmark-button" id="arch-of-triumph-button">click</div>
</div>
</div>
<div class="landmark-wrapper">
<div class="page-content landmark">
<div class="heading span-after">
<span>Romanian Athenaeum</span>
</div>
<div class="landmark-button" id="romanian-athenaeum-button">click</div>
</div>
</div>
----------------------------------------------------------
<div class="landmarks-info-wrapper">
<div class="landmark-info" id="arch-of-triumph-info">
<div class="info-landmark section">
<span class="landmark-title">Arch of Triumph</span>
<span class="landmark-coord">44°28′1.99″N 26°4′41.06″E</span>
</div>
</div>
<div class="landmark-info" id="romanian-athenaeum-info">
<div class="info-landmark section">
<span class="landmark-title">The Romanian Athenaeum</span>
<span class="landmark-coord">44.4413°N 26.0973°E</span>
</div>
</div>
Older answer, without knowing the HTML: You can extract the ID of the clicked button, slice off the button part of it, and then select it concatenated with -info:
$(".landmark-button").click(function() {
const infoSel = this.id.slice(0, this.id.length - 6) + 'info';
$(infoSel).addClass('active-info');
});
A much more elegant solution would probably be possible given the HTML, though.

Removing div's and keep content

I'm trying to remove the following DIV's:
<div class="whatever_name">
<div class="whatever_name">
<h2>subtitle</h2>
<p>content<p>
</div>
</div>
and need the following output:
<h2>subtitle</h2>
<p>content<p>
Using jQuery, I can not use remove() because it clear the content too. With pure javascript, happens the same.
I have no idea how to accomplish this issue.
Any idea?
EDIT:
Not always the structure is the same. It can vary, i.e.:
<div class="whatever_name">
<div class="whatever_name">
<div class="whatever_name">
<h2>subtitle</h2>
<p>content<p>
</div>
</div>
</div>
Just need an iterator that can handle such task.
Use unwrap() method twice on the children element.
$('.content .post-12')
// get children elements, or use contents()
.children()
// use unwrap twice to unwrap two parents
.unwrap().unwrap()
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="content">
<div class="post-12">
<h2>subtitle</h2>
<p>content</p>
</div>
</div>
UPDATE : With the updated content you just need to change the selector with your requirement.
$('div > div > h2,div > div > p').unwrap().unwrap()
// or use
// $('div > div:has(h2):has(p) > *')
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="whatever_name">
<div class="whatever_name">
<div class="whatever_name">
<h2>subtitle</h2>
<p>content
<p>
</div>
</div>
</div>

re-applying jquery to cloned objects

What is the proper way to re-apply jquery to objects which are cloned??
I have an example I rigged up in jsfiddle here: http://jsfiddle.net/49o6arLu/16/
<div class="hidden element-holder">
<div class="element">
<div class="button">Button</div>
<div class="green-square"></div>
</div>
</div>
<div class="element">
<div class="button">Button</div>
<div class="green-square"></div>
</div>
<div class="clear"></div>
<div class="add-element">Add Element</div>
$('div.button').click(function(event) {
if($(this).parent().children('.green-square').is(':visible')) {
$(this).parent().children('.green-square').hide();
}else{
$(this).parent().children('.green-square').show();
}
});
$('div.add-element').click(function(event) {
$('div.element-holder').children('div').clone().insertAfter($('div.element-holder'));
});
As you can see, the initial displayed box and button work just fine. However, When you add another element the new element button does not work anymore.
I understand why I have this problem, however I don't know the proper way I should go about re-applying the Jquery to the new elements which are cloned.
Can someone provide a solution to the jquery and provide some explanation as to what you did?
Thanks!
You can save the need to re-apply the handler to all the appended elements by having a single delegated click handler on a common parent element.
First of all amend your HTML to include the container, in this case #element-container:
<div class="hidden element-holder">
<div class="element">
<div class="button">Button</div>
<div class="green-square"></div>
</div>
</div>
<div id="element-container">
<div class="element">
<div class="button">Button</div>
<div class="green-square"></div>
</div>
<div class="clear"></div>
</div>
<div class="add-element">Add Element</div>
Then you can amend the Add Element button to append to that container:
$('div.add-element').click(function (event) {
$('div.element-holder').children('div').clone().appendTo('#element-container');
});
Finally you can add the delegated event handler to the new #element-container. Note that I also shortened the logic using toggle() and siblings():
$('#element-container').on('click', 'div.button', function (event) {
$(this).siblings('.green-square').toggle()
});
Example fiddle
In order to copy event handlers you should send true in the clone method:
$('div.add-element').click(function(event) {
$('div.element-holder').children('div').clone(true).insertAfter($('div.element-holder'));});

Change div order based on operating system

I would like to change div order based on operating system.
For example on windows
<div class="first"> </div>
<div class="second"> </div>
<div class="third"> </div>
on Mac
<div class="third"> </div>
<div class="first"> </div>
<div class="second"> </div>
I have some this js to show and hide a div which is okay if I use a parent div but I would rather reorder.
if (navigator.appVersion.indexOf("Mac") > -1) {
$('#windows').hide();
$('#mac').show();
}
Here is one way:
if (navigator.appVersion.indexOf("Mac") > -1) {
$('.third').insertBefore('.first');
}
There is also .insertAfter() that you can use. I would use these methods for basic reordering like that seen in your example. If there is a lot of re-ordering required, I think a different approach may be better, like #Daniel's example
For a more general solution, you could store the order for each platform in an array and then go through the array and re-add the element to the container using $.appendTo().
Demo
HTML
<div id="container">
<div class="first">1</div>
<div class="second">2</div>
<div class="third">3</div>
</div>
JS
var macOrder = [".third", ".first", ".second"];
$(function () {
var container = $('#container');
for (var i = 0; i < macOrder.length; i++) {
$(macOrder[i]).appendTo(container);
}
});

Append a div to a new div

i am using IPB and i am going to put each category into a new tab the category div is something like this:
<div id='category_100'>
<div id='category_104'>
<div id='category_102'>
<div id='category_101'>
and my tabs content is like this:
<div class="content">
<div id="content-1" class="content-1">
</div>
</div>
and the categories divs is already showing but i want it to be moved to the content-1 div without duplicate so i want it to move from its div to this div with jjava script how?
<script>
document.getElementById('content-1').appendChild(
document.getElementById('category_100')
);
</script>
this worked for me but how can i add more than id to category_100
i want it to be like this in one script code so i would not repeart the scrip code four times:
<div class="content">
<div id="content-1" class="content-1">
<div id='category_100'>
<div id='category_104'>
<div id='category_102'>
<div id='category_101'>
</div>
</div>
using my two lines the suggested things here is not working!
Try this code :
$('div[id^="category_"]').appendTo('#content-1')
Have a look to this fiddle : http://jsfiddle.net/lulu3030/sjEPx/2/
"using my two lines the suggested things here is not working!"
You just get a single element with an ID and trying to append it...
Live Demo
If you want to append multiple elements, there are many ways...
Wrap those elements and then append...
<div id="categories">
<div id='category_100'></div>
<div id='category_104'></div>
<!-- etc. -->
</div>
document.getElementById('content-1').appendChild(document.getElementById('categories'));
or add same class to all elements that you want to append...
<div id='category_100' class="myClass"></div>
<div id='category_104' class="myClass"></div>
[].forEach.call(document.getElementsByClassName("myClass"), function (value, index, array) {
document.getElementById("content-1").appendChild(value);
});
or get elements with query selector that match some pattern...
[].forEach.call(document.querySelectorAll("div[id^='category_']"), function (value, index, array) {
document.getElementById("content-1").appendChild(value);
});
and etc.

Categories

Resources