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

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>

Related

Add complexe Javascript array elements to HTML [duplicate]

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.

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.

Updating Variable in HTML with JQuery

I'm a beginner programmer and I'm building a game. Whenever the player clicks on the gold image, he should get 1 gold. So I have the following HTML piece of code:
<li id="gold">Gold: 0</li>
That's the starting gold, and through JQuery I update that with:
$('#gold-image').click(function() {
gold++;
$('#gold').replaceWith('<li id="gold">Gold: ' + gold + '</li>');
});
But I don't feel that's the best way to update how much gold the player has. Is there a way that I can write in the HTML to update the variable whenever it's being changed or something like that without having to replace that whole item?
Later in the game there will be many functions running at the same time and increasing the gold number, so I think replacing HTML code is not the optimal way.
Try this with your existing div <div id="gold">Gold: 0</div>:
$('#gold-image').click(function() {
gold++;
$('#gold').html('Gold: ' + gold);
});
Although the above code would work. I would NOT use jQuery for something like this. There are other frameworks which would be way better for such applications. For example you can take a look at AngularJS or Ember.
The same functionality can be achieved using the two-way binding with AngularJS.
1) the markup:
<div controller="GameCtrl">
<img src="/path/to/img.png" ng-click="goldClicked()">
<div>Gold {{ gold }}</div>
</div>
2) the javascript code
app.controller('GameCtrl', function($scope) {
$scope.gold = 0;
$scope.goldClicked = function() {
$scope.gold += 1;
};
});
The code is very very simple and you do not need to deal with selectors. Every time you change the gold (or any other variable) it will automatically be updated in the DOM. You will automatically get modular code and dependency injection. In addition you will write everything declaratively and your code will be much easier to read and easy to change in future.
UPDATE: Here is a working AngularJS fiddle: http://jsfiddle.net/absolutemystery/7WgYK/
Or, using a div only around the number (e.g., <div id="gold">0</div>),
$('#gold-image').click(function() {
$('#gold').html(++gold);
});
You could user Ember.js for this kind of thing. Ember.js its a MVC javascript library.
In this case:
<li id="gold">Gold: {{YourController.goldAmmount}}</li>
and them in your controler you only have to call the function updateAmmount():
var YourController= Em.ArrayController.create({
goldAmmount : 0,
updateAmmount : function(){
this.goldAmmount++;
}
})
If you can add a <span> element it would make it a little cleaner:
HTML:
<li>Gold: <span id="gold">0</span></li>
JAVASCRIPT:
$('#gold-image').click(function() {
gold++;
$('#gold').text(gold);
});
You can use custom events for that. Everytime gold value updates, you can trigger an event, passing an argument, for example:
$('#gold-image').click(function() {
gold++;
jQuery.event.trigger({type: "onGoldUpdate",val:gold});
});
After that, you can be always listening to that event and do whatever you want with this information, like this:
jQuery(document).on("onGoldUpdate", function(e){
var goldValue = e.val;
jQuery('.gold .value').html(goldValue);
});
And on HTML part, you can put a span around the value:
<li id="gold">Gold: <span class="value">0</span></li>
You could use a simple MVVM solution for your needs, for example Knockout.js. You can create a model and bind it's values to a place in your html and anytime you update a value in the model the rendered html is automatically updated without your interference. Quick example of how you could use it here...
<html>
<head>
<script src="http://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.0/jquery.min.js"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/knockout/3.1.0/knockout-min.js"></script>
<script>
function PlayerModel() {
// the player score
this.playerGold = ko.observable(0);
// The increase gold function to add 1 to the player score
this.increaseGold = function() {
var oldScore = parseInt(this.playerGold());
this.playerGold(++oldScore);
};
}
var model = new PlayerModel();
$( document ).ready(function() {
ko.applyBindings(model);
});
</script>
</head>
<body>Gold : <strong data-bind="text: playerGold"></strong></li>
<button onclick="javascript:model.increaseGold()">Standard JS - Increase gold</button>
<button data-bind="click: increaseGold">KO Data bound -Increase gold</button>
</body>
</html>
Its as easy as that. You can add more variables easily to your player model then if you want. I like this approach because it keeps things easy but also affords you a lot of control over the implementation etc. Ember is another great alternative though.

replace content of div with another content

I've been building a list of links, all of which should change the content of a div to another specific content (about 4 lines of stuff: name, website, contact etc.) upon a click.
I found this code:
<script type="text/javascript">
function ReplaceContentInContainer(id,content) {
var container = document.getElementById(id);
container.innerHTML = content;
}
</script>
and used it in such a way:
<li class="pl11">
superlink')">Pomorskie</a>
</li>
And it doesn't work as I expected.
It changes hyperlinks text from 'Pomorskie' to 'superlink'.
The plain text works just fine but I need links.
here's the http://xn--pytyfundamentowe-jyc.pl/projektanci/kontakty-p/ (only two of them show anything)
But after trying all of your recomendations, I think I'd jump to different divs with #links, cause nothing worked with this :/
Thanks a lot for trying, and cheers :)
Just as a completely sideways look at this, I'd suggest avoiding the nesting weirdness / complexity, and reducing the problem down.
Setup the content in a hidden (ie. <div id="replacements">...</div>) Grab the innerHTML from the node you want, and be done with it.
Much easier to get replacement content from non-devs that way too, kinda works great if you're in a team.
// Probably better in a separate helpers.js file.
function replaceContentInContainer(target, source) {
document.getElementById(target).innerHTML = document.getElementById(source).innerHTML;
}
Control it with: (lose that href=javascript: and use onClick, better as an event handler, but for brevity I'll inline it as an onClick attribute here, and use a button.)
<button onClick="replaceContentInContainer('target', 'replace_target')">Replace it</button>
We have our target somewhere in the document.
<div id="target">My content will be replaced</div>
Then the replacement content sits hidden inside a replacements div.
<div id="replacements" style="display:none">
<span id="replace_target">superlink</span>
</div>
Here it is in JSBin
Improve the dynamic nature of this by using Handlebars or another nice JS templating library, but that's an exercise for the OP.
edit: Note, you should also name functions with a leading lowercase letter, and reserve the leading uppercase style for Class names e.g. var mySweetInstance = new MySpecialObject();
The quotes are mismatched! So when you click you are getting a JavaScript error.
The browser sees this string:
href="javascript:ReplaceContentInContainer('wojewodztwo', 'superlink')">Pomorskie<
as:
href="javascript:ReplaceContentInContainer('wojewodztwo', '<a href="
Chnage the " inside to #quot;
<li class="pl11">
Pomorskie
</li>
Example fiddle.
Also note, using the href tag for JavaScript is a BAD practice.
You've got a problem with nested quotes. Take a look in your DOM inspector to see what the HTML parser built from it! (in this demo, for example)
You either need to HTML-escape the quotes inside the attribute as " or ", or convert them to apostrophes and escape them inside the JS string with backslashes:
<a href="j[…]r('wojewodztwo', '<a href="http://address.com">superlink</a>')">…
<a href="j[…]r('wojewodztwo', '<a href=\'http://address.com\'>superlink</a>')">…
See working demos here and here.
Better, you should use a onclick attribute instead of a javascript-pseudo-url:
<a onclick="ReplaceContentInContainer('wojewodztwo', …)">Pomorskie</a>
or even a javascript-registered event handler:
<li class="pl11">
<a id="superlink">Pomorskie</a>
</li>
<script type="text/javascript">
function replaceContentInContainer(id,content) {
var container = document.getElementById(id);
container.innerHTML = content;
}
document.getElementBId("superlink").onclick = function(event) {
replaceContentInContainer('wojewodztwo', 'superlink');
event.prevenDefault();
};
</script>
(demo)

Getting the current script DOM object in a (jquery) ajax request

I have a html component that includes some javascript.
The component is a file in a template engine, so it can be used
in the initial rendering of the whole html page
as stand-alone html rendered through an ajax request
The javascript should be applied to an object in the template, i.e. :
<div class="grid" >
<div class="item" id="item_13">
This is item 13
</div>
<div class="item" id="item_14">
This is item 14
</div>
</div>
<script type="text/javascript">
$(document).ready(function(){
$(HOW_DO_I_GET_PREVIOUS_ELEMENT???).someEffect(params)
})
</script>
I've checked this similar question but the best answers seem to rely on the current script being the last one in the 'scripts' variable as the next ones are not loaded yet. If I append the html and js with an ajax request, it will not be the case.
To be 100% clear : the question is about getting the previous object WITHOUT reference to any specific attribute : no unique id for the tag, no random id as there is theoretically always a chance it will show up twice, no unique class attribute,as exactly the same component could be displayed in another part of the HTML document.
Simple solution involving a two step process:
1) find out which element your script tag is
2) find the previous sibling of that element
in code:
<div id="grid">
<!-- ... -->
</div>
<script type="text/javascript">
var scripts = document.getElementsByTagName("script");
var current = scripts[scripts.length-1];
var previousElement = current.previousSibling;
// there may be whitespace text nodes that should be ignored
while(previousElement!==null && previousElement.nodeType===3) {
previousElement = previousElement.previousSibling; }
if(previousElement!==null) {
// previousElement is <div id="grid"> in this case
$(document).ready(function(){
$(previousElement).someEffect(params);
});
}
</script>
Is this good web programming? No. You should know which elements should have effects applied to them based on what you're generating. If you have a div with an id, that id is unique, and your generator can tell that if it generates that div, it will also have to generate the js that sets up the jQuery effect for it.
But let's ignore that; does it work? Like a charm.
If you can give your <script/> block an Id you could easily call prev() to get the previous element.
<script type="text/javascript" id="s2">
$(document).ready(function(){
$("#s2").prev().append("<h1>Prev Element</h2>");
})
</script>
Example on jsfiddle.
You will need to get a way to reference the script tag immediately after the "grid" div. As #Mark stated, the easiest way to do this is by giving the script tag a unique id. If this is beyond your control, but you do have control of the script contents (implicit by the fact that you are creating it) you can do something like this:
var UniqueVariableName;
var scripts = document.getElementsByTagName('script');
var thisScript = null;
for(var i = 0; i < scripts.length; i++){
var script = $(scripts[i]);
if(script.text().indexOf('UniqueVariableName') >= 0){
thisScript = script;
break;
}
}
if(thisScript){
thisScript.prev().append("<h1>Prev Element</h2>");
}
Hack? Yes. Does it Work? Also, yes.
Here's something that works in FF, Chrome and IE 8, untried anywhere else. It looks at the element before the last element on the page (which is the script being parsed), stores it locally (with a self calling function) so the load handler can use it.
http://jsfiddle.net/MtQ5R/2/
<div class="grid" >
<div class="item" id="item_13">
This is item 13
</div>
<div class="item" id="item_14">
This is item 14
</div>
</div><script>(function(){
var nodes = document.body.childNodes;
var prevSibling = nodes[nodes.length - 2];
$(document).ready(function(){
console.log( prevSibling );
})
})();</script>
Having said that. I still have to mention that you're tightly coupling the behavior (JS) and HTML, by putting them into the same file which kind of goes against the web flow of separating them. Also, I don't know how you'd expect this to work with an AJAX request since you're not just adding it to the HTML as it's being rendered. In that case, it would be very easy to get a reference to the html you just inserted though.

Categories