Referencing HTML elements - javascript

I am looking that if certain element could be referenced so, If I make any change to the one it also makes change in the other. For example,
<div id="trigger" data-referencedID="meter voltmeter ammeter vmeter">Trigger</div>
...
...
<div id="meter">
<!-- Its children goes here -->
</div>
...
...
<div id="voltmeter">
<!-- Its children goes here -->
</div>
...
...
<div id="ammeter">
<!-- Its children goes here -->
</div>
...
...
<div id="vmeter">
<!-- Its children goes here -->
</div>
Now in jQuery or JS:
$("#trigger").click( function() {
$(this).addClass("animated"); // The same class will be also added to the elements defined in attribute.
});
I could do it like this:
$("#trigger").click( function() {
var a = $(this).data("referenced").split(" ");
for(var i = 0; i < a.length; i++) {
$("#"+a).addClass("animated");
}
$(this).addClass("animated");
});
But it is not good looking and convenient plus I can have more main elements with referenced attribute.
How can I easily add referencing in my document?

You can use a class for all referenced elements like:
<div id="trigger" data-reference="reference_1">Trigger</div>
<div id="meter" class="reference_1"></div>
<div id="voltmeter" class="reference_1"></div>
And in your jQuery part:
$("#trigger").click( function() {
var e = $(this);
e.addClass("animated");
$('.' + e.data('reference')).addClass("animated");
});

How about a reverse referring? Add classes in the meters which points to the trigger. This way you may add any number of meters which referring the trigger:
<div id="trigger">Trigger</div>
...
...
<div id="meter" class="ref-trigger">
<!-- Its children goes here -->
</div>
...
...
<div id="voltmeter" class="ref-trigger">
<!-- Its children goes here -->
</div>
...
...
<div id="ammeter" class="ref-trigger">
<!-- Its children goes here -->
</div>
...
...
<div id="vmeter" class="ref-trigger">
<!-- Its children goes here -->
</div>
And change the click handler for trigger as follows:
$("#trigger").click( function() {
$('.ref-trigger').addClass("animated");
});
How about this?

You can use an attribute on referenced elements:
<div id="trigger">Trigger</div>
...
...
<div id="meter" data-reference="trigger">
<!-- Its children goes here -->
</div>
...
...
<div id="voltmeter" data-reference="trigger">
<!-- Its children goes here -->
</div>
...
...
<div id="ammeter" data-reference="trigger">
<!-- Its children goes here -->
</div>
...
...
<div id="vmeter" data-reference="trigger">
<!-- Its children goes here -->
</div>
And then you access all referencing elements this way:
$("#trigger").click( function() {
$("#trigger, [data-reference=trigger]").addClass("animated");
});
The [data-reference=trigger] parts of the query match all elements that has an attribute reference with a value of trigger.

Related

Add and remove class on multiple element when clicked

I have the below as an example of what I'm working on; I'm trying to add a class to two elements when one of the elements is clicked.
<div id="main">
<div id="section1">
- contents here -
</div>
<div id="section2">
- contents here -
</div>
<div id="section3">
- contents here -
</div>
<div class="plans-group">
<div class="plans-columns plans-type-1">
<div class="plans-col plans-left plans-heading">Heading</div>
<div class="plans-col plans-right">
<div class="select-plan select-gold">Gold</div>
</div>
<!-- end plans-right -->
</div>
<!-- end plans-columns -->
<div class="plans-columns plans-type-2">
<div class="plans-col plans-left plans-heading">Heading</div>
<div class="plans-col plans-right">
<div class="select-plan select-silver">Silver</div>
</div>
<!-- end plans-right -->
</div>
<!-- end plans-columns -->
<div class="plans-columns plans-type-3">
<div class="plans-col plans-left plans-heading">Heading</div>
<div class="plans-col plans-right">
<div class="select-plan select-bronze">Bronze</div>
</div>
<!-- end plans-right -->
</div>
<!-- end plans-columns -->
</div>
<!-- end plans-group -->
</div>
<!-- end main -->
#1): DIV with class "select-plan"
When div with class "select-plan" is clicked, add class "clicked" to that div. When it's clicked again, remove the added class.
#2): DIV with id "main"
When "select-plan" is clicked (as explained above) also add class to the container div with id "main". And remove the added class when "select-plan" is clicked again.
This is where I have a problem because different classes have to be added to "main". For example:
When "select-gold" is clicked, add class "gold-selected" to "main"
When "select-silver" is clicked, add class "silver-selected" to "main"
When "select-bronze" is clicked, add class "bronze-selected" to "main"
I don't want previously clicked div to have its added class removed because another div is clicked. The added class should only be removed when that same div is clicked for the second time and so on...
Also, I might have up to 8 or more plans. The solution should not be limited to the 3 plans (Gold, Silver, and Bronze). I should have the ability to create more plans.
I really appreciate everyone's help with this.
Thanks in advance.
let selectPlan = document.querySelectorAll('.select-plan');
let mainDiv = document.getElementById('main');
selectPlan.forEach(el =>{
el.addEventListener('click',function(e){
if(e.target.classList.contains('select-plan')){
e.target.classList.toggle('clicked');
}
if(e.target.classList.contains('select-gold')){
mainDiv.classList.add('gold-selected');
mainDiv.classList.remove('silver-selected');
mainDiv.classList.remove('bronze-selected');
}else if(e.target.classList.contains('select-silver')){
mainDiv.classList.add('silver-selected');
mainDiv.classList.remove('gold-selected');
mainDiv.classList.remove('bronze-selected');
}else{
mainDiv.classList.add('bronze-selected');
mainDiv.classList.remove('silver-selected');
mainDiv.classList.remove('gold-selected');
}
});
});
let main = document.getElementById("main");
let select = document.querySelector(".select-plan");
let selectG = document.getElementsByName("gold");
let selectS = document.getElementsByName("silver");
let selectB = document.getElementsByName("bronze");
function toggleGold() {
if (main.classList.contains('gold-select')) {
main.classList.remove('gold-select');
} else {
main.classList.add('gold-select');
}
selectG[0].classList.toggle('cliqué')
}
//You can add same function for silver and bronze
document.querySelector(".select-gold").addEventListener("click", toggleGold);
document.querySelector(".select-silver").addEventListener("click", toggleSilver);
document.querySelector(".select-bronze").addEventListener("click", toggleBronze)
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
<div name="gold" class="select-plan select-gold">Gold</div>
<div name="silver" class="select-plan select-silver">Silver</div>
<div name="bronze" class="select-plan select-bronze">Bronze</div>

How to detach and append to relevant div only jQuery

I am trying to detach the div from the relevant parent and then append to the same parent div.
//Jquery Code
jQuery(function(){
moveColorDots();
});
function moveColorDots(){
var copyDivData = jQuery('.variations_form.wvs-archive-variation-wrapper').detach();
copyDivData.appendTo('.product-variations');
}
<div class="pp-content-post">
<div class="variations_form wvs-archive-variation-wrapper">
some data here
</div>
<div class="product-box">
<div class="glasses-sec">
<h3>title</h3>
</div>
<div class="product-variations"></div>
</div>
</div>
Expected result.
But after running the above code I am getting the following result.
.detach Description: Remove the set of matched elements from the DOM.
That means you append all the detached elements to every product-variations element ..So
You need to loop through the variations_form.wvs-archive-variation-wrapper elements by using .each()
Also you can use .appendTo() directly
//Jquery Code
jQuery(function(){
moveColorDots();
});
function moveColorDots(){
jQuery('.variations_form.wvs-archive-variation-wrapper').each(function(){
var product_variations = jQuery(this).next('div').find('.product-variations');
jQuery(this).appendTo(product_variations);
});
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="pp-content-post">
<div class="variations_form wvs-archive-variation-wrapper">
some data here 1
</div>
<div class="product-box">
<div class="glasses-sec">
<h3>title</h3>
</div>
<div class="product-variations"></div>
</div>
</div>
<div class="pp-content-post">
<div class="variations_form wvs-archive-variation-wrapper">
some data here 2
</div>
<div class="product-box">
<div class="glasses-sec">
<h3>title</h3>
</div>
<div class="product-variations"></div>
</div>
</div>
Note: This line of code var product_variations = jQuery(this).next('div').find('.product-variations'); is depending on your html structure it works for the posted html here .. But if you've another html structure you need to modify it to catch the desired element

jQuery created element with insertAfter is not working

There are several divs on the page with class "wrap-me".
I want add an element "add-me" after "wrap-me", and doubly wrap the two in a "wrapper-inner" and "wrapper".
Basically - it should look like this:
<div class="wrapper">
<div class="wrapper-inner">
<div class="wrap-me"></div>
<div class="add-me"></div>
</div>
</div>
This is my implementation:
const $addMe = $("<div>", { class: "add-me" });
const $wrapper = $('<div>', { class: "wrapper" });
const $wrapperInner = $('<div>', { class: "wrapper-inner" });
$.each($(".wrap-me"), (i, wrapMe) => {
const $wrapMe = $(wrapMe);
$wrapMe.wrap($wrapper).wrap($wrapperInner);
$addMe.insertAfter($wrapMe);
});
Here's the output:
<div class="wrapper">
<div class="wrapper-inner">
<div class="wrap-me"></div>
</div>
</div>
It's almost there, the only thing is that the "add-me" is not getting inserted into the DOM. What's wrong?
//get the template
var wrapperTemplate = $('#wrapperTemplate').text();
$('.wrap-me').each(function(index, element){
//create a new element to put in the DOM
var $wrapper = $(wrapperTemplate);
//put the wrapper after the element we are going to replace
$wrapper.insertAfter(element);
//move the element into the wrapper where it should be
$wrapper.find('.wrapper-inner').prepend(element);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="wrap-me">A</div>
<div class="wrap-me">B</div>
<div class="wrap-me">C</div>
<div class="wrap-me">D</div>
<!-- HTML template for what we want to add, so it's not in the javascript -->
<script type="text/html" id="wrapperTemplate">
<div class="wrapper">
<div class="wrapper-inner">
<div class="add-me"></div>
</div>
</div>
</script>

JS, Highlight content between comments

I have few comments in my code, like this:
<!-- DebugDataTemplateBegin {"template":"one"} -->
<div class="row notices" id="admin">
comment One content
</div>
<!-- DebugDataTemplateEnd {"template":"one"} -->
<!-- DebugDataTemplateBegin {"template":"two"} -->
<div class="row notices" id="admin">
comment Two content
</div>
<!-- DebugDataTemplateEnd {"template":"two"} -->
and I have anchors like this:
one <br/>
two
These links content corresponds to the comments 'template' element, what I want to achieve is that when the user hover over any of these links it's correspondence content (between the comment) will be highlighted.
I started a simple jsfiddle example http://jsfiddle.net/Banzay/md79aaby/ , but not sure if this is even possible.
Sorry if I didn't explain this very well.
Youssef
Cleaned up my answer above and removed it.
You might have to change the parent you are looking for comments in. And the regex could use some love but this is the general idea.
HTML:
<!-- DebugDataTemplateBegin {"template":"one"} -->
<div class="row notices" id="admin">comment One content</div>
<!-- DebugDataTemplateEnd {"template":"one"} -->
<!-- DebugDataTemplateBegin {"template":"two"} -->
<div class="row notices" id="admin">comment Two content</div>
<!-- DebugDataTemplateEnd {"template":"two"} -->
one
<br/>
two
JS:
var getComment = function (templateName) {
return $("body").contents().filter(function () {
return this.nodeType == 8 && this.nodeValue.match(RegExp('DebugDataTemplateBegin.*'+templateName));
})
}
$('a').hover(function () {
var templateName = this.href.split('#')[1];
var comment = getComment(templateName);
var element = $(comment).next();
element.toggleClass('highlight');
})
http://jsfiddle.net/md79aaby/18/

How to use AngularJS features to insert multiple divs in one div (i.e. some kind of multi-element template)

In my AngularJS application, I would like to make some kind of directive that inserts multiple HTML elements to an HTML element.
Basically, I want Angular to build this result:
<div class="maindiv">
<!-- Below are some divs common to all "maindiv" -->
<div> ..XXX.. </div>
<div> ..YYY.. </div>
<!-- Below are some elements specific to maindiv1 -->
<div> ..ABCD.. </div>
<div> ..EFGH.. </div>
<div> ..IJKL.. </div>
</div>
<div class="maindiv">
<!-- Below are some divs common to all "maindiv" -->
<div> ..XXX.. </div>
<div> ..YYY.. </div>
<!-- Below are some elements specific to this particular maindiv -->
<div> ..1235.. </div>
<div> ..5678.. </div>
</div>
... from HTML that looks like this :
<div class="maindiv" generate-common-stuff>
<!-- Below are some elements specific to maindiv1 -->
<div> ..ABCD.. </div>
<div> ..EFGH.. </div>
<div> ..IJKL.. </div>
</div>
<div class="maindiv" generate-common-stuff>
<!-- Below are some elements specific to this particular maindiv -->
<div> ..1235.. </div>
<div> ..5678.. </div>
</div>
... or like this:
<div class="maindiv">
<generate-common-stuff></generate-common-stuff>
<!-- Below are some elements specific to maindiv1 -->
...
When I tried to make my own directive, Angular complained about having multiple root elements in my template.
Note that because of incompatibilities with other libraries (JQueryMobile), I cannot regroup <div> ..XXX.. </div><div> ..YYY.. </div> under a div and use it in the template. They must be inserted just under the maindiv
Do you have any idea on how to implement that ?
Try write a directive called generate-stuff and pass common and specific stuff as attributes, binded from the scope.
<generate-stuff common="commonStuffInScope" specific="specificStuffInScope"></generate-stuff>
...and in your directive
myModule.directive('', function() {
return {
...
scope: {
common: "=common",
specific: "=specific"
}
...
};
});
so in the link function you have a bidirectional binding either to the common and the specific variables on the scope.
Releated documentation fragment: http://docs.angularjs.org/guide/directive#directivedefinitionobject

Categories

Resources