Add complexe Javascript array elements to HTML [duplicate] - javascript

I have a template:
function useIt() {
var content = document.querySelector('template').content;
// Update something in the template DOM.
var span = content.querySelector('span');
span.textContent = parseInt(span.textContent) + 1;
document.querySelector('#container').appendChild(
document.importNode(content, true));
}
<button onclick="useIt()">Use me</button>
<div id="container"></div>
<template>
<div>Template used: <span>0</span></div>
<script>alert('Thanks!')</script>
</template>
You can try the code here.
This code basically copies the template(html5 templates does not render on your screen) into another div. This allows you to reuse the DOM.
Problem: The line "span.textContent = parseInt(span.textContent) + 1;" changes the template code directly. I need to manipulate the content DOM and clone it into the container, without changing the template. This is very important since if I want to reuse the code, I need it to stay the same.
I have tried multiple ways to use jQuery to mimic the above javascript code, but I can't manage to figure it out. It would be better if there is a jQuery way.

If you NEED to use the new <template> tag, then you are mildly stuck . . . your cleanest alternative is to use importNode to bring in the content and then modify it after it's been appended.
Assuming that the templated code is realtively small, this should happen fast enough that you would never notice the difference in approach, though, in this specific example, the alert(), would delay the change of the content, so you would see "0", until you clicked "Okay", and then it would update to "1".
The code change for that would be:
function useIt() {
var content = document.querySelector('template').content;
var targetContainer = document.querySelector('#container');
targetContainer.appendChild(document.importNode(content, true));
var $span = $(targetContainer).find("div:last-of-type").find("span");
$span.text(parseInt($span.text() + 1));
}
If you are not married to the idea of <templates>, you could use jQuery's clone() method to do what you want to do, very easily . . . but, clone does not "see" the content of a <template>, due to the special nature of that particular element, so you would have to store the templated code some other way (JS variable, hidden div, etc.).
HOWEVER, this method will not work if you need to clone a script, the way that a <template> will. It will not trigger any script code in the "template container" element when the cloned version is created or appended. Additionally, if you store it in a hidden <div>, any script code in the "template container" element will trigger immediately on page load.
A simple version of the code for the clone() approach would look something like this:
function useIt() {
var $content = $("#template").clone();
var $span = $content.find("span");
$span.text(parseInt($span.text()) + 1);
$content.children().each(function() {
$("#container").append($(this));
});
}
Assuming that your template was:
<div id="template" style="display: none;">
<div>Template used: <span>0</span></div>
<script>alert('Thanks!')</script>
</div>
You could also move the <script>alert('Thanks!')</script> out of the template and into the script section (after you completed the "append loop"), to achive the desired alert functionality, if you wanted to.

It's an old question, but, did you try cloneNode(true)? It works on templates, as this:
var span = content.querySelector('span').cloneNode(true)
regards.

Related

Is it possible to write a js variable into plain html?

I am counting my user specificated and dynamically appearing divs...
My situation:
<div class="grid-stack" data-bind="foreach: {data: widgets, afterRender: afterAddWidget}">
<div id="streamcontainer1" class="streamcontainer grid-stack-item" data-bind="attr: {'data-gs-x': $data.x, 'data-gs-y': $data.y, 'data-gs-width': $data.width, 'data-gs-height': $data.height, 'data-gs-auto-position': $data.auto_position}">
</div>
</div>
In PHP i can simply write my COUNT variable inside the html. That would look something like this:
<div id="streamcontainer<?php echo $count ?>" class="" ... and so on...>
How can i archive the same with JS/Jquery?
It's a DOM manipulation question. What do we have to work with? We're adding divs to the page, they have a particular class, and we want to give them an ID.
function assignIds(){
var list = document.getElementsByClassName('streamcontainer');
for(var i=0; i<list.length;i++){
if(list[i].id == undefined) // skip the ones that have already been done.
list[i].id = 'streamContainer' + i.toString();
}
}
Now we just have to run that function on some event so it will keep updating. If you just want to do it on an interval, that's simplest. (setInterval) But that could give you a bug, where there's a small amount of time where that ID hasn't been assigned yet. You could try listening to whatever AJAX/websocket process is streaming these things onto the page.
We'd need to know a bit more about your use case to know which event to attach it to.
Without a Javascript Reactive Framework (Vue.js, React, AngularJS) you can't do this.
What you can do with JS is set a content in element when DOM is loaded, example:
document.getElementById("myElement").textContent = "Hello World!";
Or
document.getElementById("myElement").innerHTML = "<span>Hello World!</span>";
OBS: .innerHTML can insert HTML tags and .textContent just insert texts.
You can make use of the text bindings in knockoutjs to display the javascript value in the HTML. There are lot of ko bindings which can help you. More reference here
var viewModel = {
javascriptVariable: "I am javascript string"
};
ko.applyBindings(viewModel);
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
<span data-bind="text: javascriptVariable"></span>

copy html block with tags script

I have such html code:
<div>
<div id="text">text></div>
<script>$("#text").val('some value');</script>
</div>
I copy this html through .clone() and edit html inside. Result:
<div>
<div id="1-text">text></div>
<script>$("#text").val('some value');</script>
</div>
I want to change id inside tags script. $("#1-text").val('other value');
How can I do it?
You can simply add a variable to the outside that dynamically tells you what to select. so if you were to iterate through your values using a loop you can do something like this:
$("#text_"+i).val('other value');
You could also set a counter and as new divs are added the i increments. So it is flexible.
I'm not exactly sure what your end goal is but I wouldn't recommend this methodology if you're attempting to manipulate the javascript in the <script> tag. As I believe that would be cumbersome.
If you want to copy entire html block, you should bind your inline javascript code to this block as a container. Not id. So when you move or copy the block your script will be able to find any elements related to container.
<div id="containerOne" class="js-container">
<div class="js-text" data-text="some value">some value</div>
<script>
var $el = $("script").last().closest(".js-container").find(".js-text");
$el.text($el.data("text"));
</script>
</div>
Hereby you obtain access to elements by class not id. Note using "js-" prefix is just for javascript manipulation not for css styling.
Also you don't need to change script itself. You can change values via "data-" attributes.
In your external script you can encapsulate any clone logic by various methods. For example:
var myModule = {
clone: function(containerSelector) {
var $donorEl = $(containerSelector);
var $donorScript = $donorEl.find('script');
$script = $("<script />");
$script.text($donorScript.text());
$recipientEl = $donorEl.clone();
$recipientEl.attr('id', 'containerTwo');
var newValue = 'other value';
$('.js-text', $recipientEl).data('text', newValue);
$('body').append($recipientEl);
$('script', $recipientEl).replaceWith($script);
}
};
myModule.clone('#containerOne');
You can see the working example.

Set div background color without using ID

Is possible change color of background my div using JavaScript without using ID? And how?
Html code is:
<div class="post" onmouseover="test(this)">
JS code is:
function test(item){
alert("Hi :-)");
}
Have you tried
function test(item){
item.style.backgroundColor = "red";
}
Since item is the actual div you're triggering this event on you won't need an ID to style the element.
A really easy (inline) solution would be the one below.
<div class="post" onmouseover="javascript:style.backgroundColor = 'red';">
Content blabla
</div>
I would personally rather do all of this inside a JS file but hey this works too.
You can loop through the DOM with JavaScript, but you'll have a better time of it if you're using JQuery. You'll want to invest some time learning about selectors:
http://api.jquery.com/category/selectors/
http://www.w3schools.com/jquery/jquery_ref_selectors.asp.
You'll be looking for something like:
function test(){
var element = $('div');
}
As people have shared in the comments, without a unique identifier, you'll have a rough time, especially as new elements are added to the page.

Updating a CSS attribute using jQuery

Suppose I have the following html:
...
<div class="thinger">...</div>
<div class="thinger">...</div>
<div class="thinger">...</div>
...
I want to dynamically set the width of all of the thinger divs. I know that I can do it like this:
$(".thinger").css("width",someWidth);
This will result in html that looks like this:
<div class="thinger" style="width: 50px;">...</div>
<div class="thinger" style="width: 50px;">...</div>
<div class="thinger" style="width: 50px;">...</div>
I would prefer to have the resulting HTML look like this:
...
<style>
.thinger {
width: 50px;
}
</style>
...
<div class="thinger">...</div>
<div class="thinger">...</div>
<div class="thinger">...</div>
...
I looked around but didn't see a jQuery utility to add/update/modify existing css classes. Does this exist?
I know that I could add it manually using something like this:
var styleElement = document.createElement('style');
styleElement.type = "text/css";
styleElement.innerHTML = ".thinger {width:" + maxWidth + ";}";
document.getElementsByTagName('head')[0].appendChild(styleElement);
But I don't want to have to deal with browser inconsistencies and I want to make sure I am doing things "the jQuery way". Any reason to choose one method over the other?
You can create the style element and append it to the head as you would any other element in the DOM, however it's a waste of time.
The best method to use would be to setup your class rule in a stylesheet and add the class to those elements. This maintains a better separation of concerns which is beneficial for both code reuse and maintenance later on.
I can't setup the class rule in a stylesheet because I don't know what the width will be prior to runtime.
In this case the current method you have of using css() is the best available.
Well that is a whole process read Add Rules to Stylesheets with JavaScript
Interesting question, it would be good to test if there is any performance benefit for using one approach over the other.
$("<style>.thinger{width:" + maxWidth + ";}</style>").appendTo("head");
If you need to update the value over time you should not keep appending new style tags to the page. Instead you'd want to update the existing one with something like this:
http://jsfiddle.net/daniellmb/0u5ffasq/
$('button').click(function(e) {
// get the dynamic width setting
var maxWidth = $(e.target).text(),
newRule = '.thinger{width:' + maxWidth + ';}';
styleTag = $('#thinger-style');
if (styleTag.length) {
// update existing
styleTag.text(newRule);
} else {
// create for the first time
$('<style id="thinger-style">' + newRule + '</style>').appendTo("head");
}
});
Yes there is. You can add or remove classes with jQuery .addClass() and .removeClass() methods.
$('#myDiv').addClass('myFirstClass');
or
$('#myDiv').removeClass('myFirstClass');
You can also use .css() method to update the css of an element like:
$('.myFirstClass').css('width','100px');

Find the tag JavaScript is running in

Generating HTML source on backend, I am using separate independent widgets.
I am simply including pieces of markup like this to the resulting HTML output.
<div>
I want to work with this DOM element
<script>
new Obj(/*but I can't get this <div> as a parameter! */);
</script>
</div>
I'm looking for a way to find the DOM element in which the obj is created (Without any unique IDs). This would add flexibility to my app and speed up the development. But is that technicaly possible in JavaScript?
You could seed an element in there and then get it's parent, and then remove the element.
<div>
I want to work with this DOM element
<script>
document.write("<div id='UniqueGUID_3477zZ7786_' style='display:none;'></div>");
var thatDivYouWanted;
(function(){
var target = document.getElementById("UniqueGUID_3477zZ7786_");
thatDivYouWanted = target.parentNode;
target.parentNode.removeChild(target);
})();
new Obj(/*but I can't get this <div> as a parameter! */);
</script>
</div>
The following code works:
<script>
function Obj(color) {
var scriptTags = document.getElementsByTagName("script");
var scriptTag = scriptTags[scriptTags.length - 1];
// find parent or do whatsoever
var divTag = scriptTag.parentNode;
divTag.style.backgroundColor = color;
}
</script>
<div>
I want to work with this DOM element
<script>new Obj("green");</script>
</div>
<div>
I want to work with this DOM element
<script>new Obj("yellow");</script>
</div>
<div>
I want to work with this DOM element
<script>new Obj("lime");</script>
</div>
This method has very simple code and has almost zero impact on performance.
Note: I am pretty sure this won't work IE6 (as far as I remember it does not support manipulating open tags).
I believe your approach is not ideal. If you're trying to obtain the <div>, it should be done programmatically in a conventional way using JavaScript and the API's that empower you to query the target <div>
Instead of executing inline, you can execute in a separate scope in a controlled way (DOM Ready then Query then Your Method). You can target your div by using an ID, CSS class name, or any other CSS selector in JavaScript.
This allows you to pretty much do the follow anywhere you want, not inline.
// on dom ready...
var div = document.getElementById('myDiv'), // replace with any other selector method
myObject = new Object(div);
Need to find your div? https://developer.mozilla.org/en-US/docs/DOM/Document.querySelectorAll
If you know beforehand how the page will be structured, you could use for example:
document.getElementsByTagName("div")[4]
to access the 5th div.

Categories