Dynamically Creating bootstrap-sliders with jquery or javascript - javascript

I'm trying this with no success. For reference, the bootstrap slider is here : http://seiyria.github.io/bootstrap-slider/.
I'm not a javascript expert, either, so this might be very simple. The bootstrap-slider site has many examples of how to configure the sliders the way you want them. I'm going to have many sliders generated depending on how many objects are pulled from a JSON file or some other data storing method. It could be 2 or it could be 20.
I created a javascript function called createSlider that I've attempted to pass all of the information required at the bootstrap-slider site. I'm not getting any errors in my Chrome debugging area, but nothing is happening. All of the appropriate client-side sources are loading.
function createSlider (orgId) {
slidersList = document.getElementById('slidersList');
element = slidersList.createElement("div");
var sliderElement = element.createElement('input');
var sliderUnique= orgId.concat("Slider");
var sliderUniqueVal = orgId.concat("SliderVal");
sliderElement.setAttribute('id', charityId);
sliderElement.setAttribute('data-slider-id', sliderUnique);
sliderElement.setAttribute('type', 'text');
sliderElement.setAttribute('data-slider-min', '0');
sliderElement.setAttribute('data-slider-max', '100');
sliderElement.setAttribute('data-slider-step', '1');
sliderElement.setAttribute('data-slider-value', '50');
var span = element.createElement('span');
span.setAttribute('style', 'padding-left:5px;');
span.innerHTML =' ';
var innerSpan = span.createElement('span');
innerSpan.setAttribute('id', sliderUniqueVal);
innerSpan.innerHTML = '50';
sliderElement.slider({tooltip: 'hide'});
sliderElement.on("slide", function(slideEvt) {
innerSpan.innerHTML = text(slideEvt.value);
});
}
The slider() function is from the external site, and runs fine if I explicitly call it like the examples state to. Anyone know what's going wrong? Is there a better way to do this? Any ideas would be appreciated.

Note, in plain JavaScript, you can only use document.createElement and then append to another HTML element. You cannot call createElement directly against another HTML element.
I changed some of what you wrote from plain old JavaScript into JQuery, and now seems to work:
P.S. Didn't know where charityId came from, so just added it as another parameter into the function.
$(function() {
createSlider('o1','c1');
createSlider('o2','c2');
createSlider('o3','c3');
});
function createSlider (orgId, charityId) {
var slidersList = $('#slidersList');
var element = $("<div></div>").appendTo(slidersList);
var sliderElement = $("<input/>").appendTo(element);
var sliderUnique= orgId.concat("Slider");
var sliderUniqueVal = orgId.concat("SliderVal");
sliderElement.attr('id', charityId);
sliderElement.attr('data-slider-id', sliderUnique);
sliderElement.attr('type', 'text');
sliderElement.attr('data-slider-min', '0');
sliderElement.attr('data-slider-max', '100');
sliderElement.attr('data-slider-step', '1');
sliderElement.attr('data-slider-value', '50');
var span = $('<span></span>').appendTo(element);
span.attr('style', 'padding-left:5px;');
span.html(' ');
var innerSpan = $('<span></span>').appendTo(span);
innerSpan.attr('id', sliderUniqueVal);
innerSpan.html('50');
sliderElement.slider({tooltip: 'hide'});
sliderElement.on("slide", function(slideEvt) {
innerSpan.text(slideEvt.value);
});
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<link rel="stylesheet" type="text/css" href="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css">
<script type='text/javascript' src="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/js/bootstrap.min.js"></script>
<link rel="stylesheet" type="text/css" href="http://seiyria.github.io/bootstrap-slider/stylesheets/bootstrap-slider.css">
<script type='text/javascript' src="http://seiyria.github.io/bootstrap-slider/javascripts/bootstrap-slider.js"></script>
<div id="slidersList"></div>

Related

Failed to execute 'appendChild' on 'Node': The new child element is null

This weird bug is bugging me from half an hour. I am dynamically trying to apply a slider using only JavaScript. Any idea as to why this is occurring to me? I could find other questions on SO, but could not understand the solution. I am new to JS and highly appreciate if someone could explain me things in laymen terms. Here is my code.
MARKUP
<!DOCTYPE html>
<html>
<head>
<title>JS sample test page</title>
<link rel="stylesheet" type="text/css" href="jquery.bxslider.css">
</head>
<body>
<div class="og-fullimg"></div>
<script type="text/javascript" src="jquery-1.11.1.js"></script>
<script type="text/javascript" src="jquery.bxslider.min.js"></script>
<script type="text/javascript" src="main.js"></script>
</body>
</html>
JAVASCRIPT
// code for thumbnail slider begins
(function() {
var ogImg = document.getElementsByClassName("og-fullimg");
alert(ogImg.length);
var bxSlider = document.createElement("ul"); //created ul
bxSlider.setAttribute("class", "bxslider"); // gave a class name bxslider.
for (i = 1; i < 4; i++) {
var itemsList = document.createElement("li");
var linkImages = document.createElement("img");
linkImages.src = "images/bid_" + i + ".jpg";
itemsList.appendChild(linkImages);
bxSlider.appendChild(itemsList);
}
ogImg[0].appendChild(bxSlider);
document.body.appendChild(ogImg); //append everything to the body.
//call the slider.
$(document).ready(function() {
$('.bxslider').bxSlider({
auto: true,
pager: false,
adaptiveHeight: true,
slideWidth: 550
});
});
}());
// code for thumbnail slider ends.
Thanks in advance.
Several issues here:
document.body.appendChild(ogImg); is just wrong. ogImg is a nodeList. You can't directly append a nodeList to the body AND it's already in the DOM (you just got it with document.getElementsByClassName("og-fullimg");.
You are using $(document).ready() to wait to call .bxSlider(), but NOT using it to call document.getElementsByClassName(). My guess would be your code is just running too soon. If that is the case, then just put all your code inside the .ready() handler.
You're using a very odd mix of plain javascript and jQuery when switching the plain javascript over to jQuery could make your code smaller and more consistent. If you have jQuery, you may as well use it for what it's good at (which is selectors and operations on collections - among other things).
This is what I'd suggest:
//create and initialize the slider.
$(document).ready(function() {
var bxSlider = $("<ul class='bxslider'></ul>"), img;
for (var i = 1; i < 4; i++) {
img = new Image();
img.src = "images/bid_" + i + ".jpg";
$("<li>").append(img).appendTo(bxSlider);
}
bxSlider.appendTo(".og-fullimg");
bxSlider.bxSlider({
auto: true,
pager: false,
adaptiveHeight: true,
slideWidth: 550
});
});

I'm a bit lost on DOM manipulation

Alright. As a part of a personal project to get familiar with Javascript, css and html outside of tutorials I've decided to try to create a cookie clicker like game for fun. However, I'm a bit stuck on the DOM manipulation.
var multiplier=1;
var money=5;
var moneyTotal=money*multiplier;
$(document).ready(function() {
$('div #button').click(function() {
var money++;
});
});
document.getElementById('counter').innerHTML = moneyTotal;
What I'm trying to do is having some text in my html index page, that changes whenever you click the div with the ID button. That piece of text has the id counter. But I can't seem to make this work, and I'm starting to get really frustrated after having this problem for 4 hours and not finding a solution. I have a feeling I'm missing some very obvious syntax, but I have no idea on what.
Edit:
Alright I changed the code so that it looks like this now:
var multiplier=1;
var money=5;
$(document).ready(function() {
$('#button').click(function() {
money++;
$('#counter').html(money * multiplier);
});
});
However it still won't target my div with the ID counter.
Here's the index.html, but I'm 99% sure there's no syntax errors there, and I have no idea on why it won't work.
<!DOCTYPE html>
<html>
<head>
<script type='text/javascript' src='script.js'></script>
<link rel='stylesheet' type='text/css' href='style.css'/>
</head>
<body>
<div id="button"></div>
<div id="counter">0</div>
</body>
</html>
Edit:
This is the final solution, thanks again everyone!
var mp = 1
var money = 0
$(document).ready(function() {
var localMoney = localStorage.getItem("money");
var localmp = localStorage.getItem("mp")
$('#moneycounter').click(function() {
money++;
$('#counter').html(money * mp);
});
});
I'm not sure what you're expecting it to do...
But var money +1 is wrong. Should be money++
Then you have to recalculate moneyTotal, and set it into the innerHTML at that point.
You need to run the function to update your div everytime you click!
var multiplier=1;
var money=5;
var moneyTotal=money*multiplier;
$(document).ready(function() {
$('div #button').click(function() {
money++;
updateElement();
});
});
function updateElement(){
document.getElementById('counter').innerHTML = moneyTotal;
}

javascript document.write script

Edited qestion
I'm trying to create two separate HTML documents: main.html and sufler.html . Idea is to control sufler.html page from main.html . To do that I found a solution
to write sufler's.html code like string element on main.html page, change what I need in that string element and write it with document.write function from main.html . Everything
works fine except <script> function...
main.html
<script type="text/javascript">
var HTMLstringPage1 = '<!DOCTYPE html><html><head><link href="stilius.css" rel="stylesheet" type="text/css" />',
HTMLstringPage2 = '</body></html>',
HTMLstringStyle = '\x3Cscript type="text/javascript">function styluss(){document.getElementById("flip").style.font="normal normal 30px sans-serif";}\x3C/script>',
HTMLstringDiv1 = '</head><body onload="styluss()"><div id="sufler"><div id="mov"><p id="flip">',
HTMLstringDiv2 = '</p></div></div>';
var newWindow = window.open('sufler.html','_blank','toolbar=no, scrollbars=no, resizable=no, height=615,width=815');
newWindow.document.body.innerHTML = '';
newWindow.document.write(HTMLstringPage1,HTMLstringDiv1+"Text"+HTMLstringDiv2,HTMLstringPage2); //works fine
// newWindow.document.write(HTMLstringPage1,HTMLstringStyle,HTMLstringDiv1+"Text"+HTMLstringDiv2,HTMLstringPage2);//works except script function
</script>
Can someone help on this?
To dynamically add a script tag, it is much better to do this:
var newDoc = newWindow.document;
var script = newDoc.createElement("script");
script.type = "text/javascript";
var text = newDoc.createTextNode('function styluss(){document.getElementById("flip").style.font="normal normal 30px sans-serif";}');
script.appendChild(text);
newDoc.getElementsByTagName("head")[0].appendChild(script);
Working demo: http://jsfiddle.net/jfriend00/JqW5F/
But, creating code on the fly like this is almost never needed. Since you must, by definition, generally already know what you want the code to do, you can just have a pre-created function that takes some arguments and then call that existing function with the right arguments to accomplish what you wanted to rather than creating a custom function on the fly:
function styleIt(id, fontStyle) {
document.getElementById(id).style.font = fontStyle;
}
styleIt("flip", "normal normal 30px sans-serif");
styleIt("flip2", "normal normal 12px sans-serif");
You have to use normal opening brackets for <script> tags:
var HTMLstringStyle = '<script type="text/javascript">function styluss(){document.getElementById("flip").style.font="normal normal 30px sans-serif";}<\/script>';
Although I can't see why you would ever use this... attaching a <script> tag to the <head> or the <body> is almost always a superior solution.

Appending children into a popup-window. (JavaScript)

I'm having some trouble trying to get a fairly simple popupper to work. The idea is that the parent should open a popup window and then append a div in it.
The relevant parts of the code:
parent.html:
var childWindow;
function togglePref() {
childWindow = window.open("popup.html", "prefPopup", "width=200,height=320");
}
function loadPopupElements() {
var prefElements = document.getElementById("prefBrd").cloneNode(true);
var childDoc = childWindow.document;
var childLink = document.createElement("link");
childLink.setAttribute("href", "pop.css");
childLink.setAttribute("rel", "stylesheet");
childLink.setAttribute("type", "text/css");
childDoc.head.appendChild(childLink);
childDoc.body.appendChild(prefElements);
}
popup.html:
<head>
</head>
<body onload="opener.loadPopupElements();">
</body>
This works fine with Safari and Chrome, but for some reason IE refuses to append anything.
Ok, I managed to work around the problem with a uglyish solution using innerHTML. Apparently, as Hemlock mentioned, IE doesn't support appending children from a another document. Some suggested to take a look at the importNode() method but I seemed to have no luck with it either.
So, the workaround goes as follows:
parent.html:
var childWindow;
function togglePref() {
childWindow = window.open("popup.html", "prefPopup", "width=200,height=320");
}
function loadPopupElements() {
var prefElements = document.getElementById("prefBrd");
var childDoc = childWindow.document;
childDoc.body.innerHTML = prefElements.innerHTML;
}
popup.html:
<head>
<link href="pop.css" rel="stylesheet" type="text/css">
</head>
<body onload="loadElements();">
</body>
<script type="text/javascript">
function loadElements() {
opener.loadPopupElements();
}
</script>
This seems quite a nasty way to go because in my case the #prefBrd contains some input elements with dynamically set values, so in order for the popup.html to grab them, it has to do a bit of iteration at the end of the loadElements() function, which wouldn't have been necessary using appendChild.

How do you execute a dynamically loaded JavaScript block?

I'm working on a web page where I'm making an AJAX call that returns a chunk of HTML like:
<div>
<!-- some html -->
<script type="text/javascript">
/** some javascript */
</script>
</div>
I'm inserting the whole thing into the DOM, but the JavaScript isn't being run. Is there a way to run it?
Some details: I can't control what's in the script block (so I can't change it to a function that could be called), I just need the whole block to be executed. I can't call eval on the response because the JavaScript is within a larger block of HTML. I could do some kind of regex to separate out the JavaScript and then call eval on it, but that's pretty yucky. Anyone know a better way?
Script added by setting the innerHTML property of an element doesn't get executed. Try creating a new div, setting its innerHTML, then adding this new div to the DOM. For example:
<html>
<head>
<script type='text/javascript'>
function addScript()
{
var str = "<script>alert('i am here');<\/script>";
var newdiv = document.createElement('div');
newdiv.innerHTML = str;
document.getElementById('target').appendChild(newdiv);
}
</script>
</head>
<body>
<input type="button" value="add script" onclick="addScript()"/>
<div>hello world</div>
<div id="target"></div>
</body>
</html>
You don't have to use regex if you are using the response to fill a div or something. You can use getElementsByTagName.
div.innerHTML = response;
var scripts = div.getElementsByTagName('script');
for (var ix = 0; ix < scripts.length; ix++) {
eval(scripts[ix].text);
}
While the accepted answer from #Ed. does not work on current versions of Firefox, Google Chrome or Safari browsers I managed to adept his example in order to invoke dynamically added scripts.
The necessary changes are only in the way scripts are added to DOM. Instead of adding it as innerHTML the trick was to create a new script element and add the actual script content as innerHTML to the created element and then append the script element to the actual target.
<html>
<head>
<script type='text/javascript'>
function addScript()
{
var newdiv = document.createElement('div');
var p = document.createElement('p');
p.innerHTML = "Dynamically added text";
newdiv.appendChild(p);
var script = document.createElement('script');
script.innerHTML = "alert('i am here');";
newdiv.appendChild(script);
document.getElementById('target').appendChild(newdiv);
}
</script>
</head>
<body>
<input type="button" value="add script" onclick="addScript()"/>
<div>hello world</div>
<div id="target"></div>
</body>
</html>
This works for me on Firefox 42, Google Chrome 48 and Safari 9.0.3
An alternative is to not just dump the return from the Ajax call into the DOM using InnerHTML.
You can insert each node dynamically, and then the script will run.
Otherwise, the browser just assumes you are inserting a text node, and ignores the scripts.
Using Eval is rather evil, because it requires another instance of the Javascript VM to be fired up and JIT the passed string.
The best method would probably be to identify and eval the contents of the script block directly via the DOM.
I would be careful though.. if you are implementing this to overcome a limitation of some off site call you are opening up a security hole.
Whatever you implement could be exploited for XSS.
You can use one of the popular Ajax libraries that do this for you natively. I like Prototype. You can just add evalScripts:true as part of your Ajax call and it happens automagically.
For those who like to live dangerously:
// This is the HTML with script element(s) we want to inject
var newHtml = '<b>After!</b>\r\n<' +
'script>\r\nchangeColorEverySecond();\r\n</' +
'script>';
// Here, we separate the script tags from the non-script HTML
var parts = separateScriptElementsFromHtml(newHtml);
function separateScriptElementsFromHtml(fullHtmlString) {
var inner = [], outer = [], m;
while (m = /<script>([^<]*)<\/script>/gi.exec(fullHtmlString)) {
outer.push(fullHtmlString.substr(0, m.index));
inner.push(m[1]);
fullHtmlString = fullHtmlString.substr(m.index + m[0].length);
}
outer.push(fullHtmlString);
return {
html: outer.join('\r\n'),
js: inner.join('\r\n')
};
}
// In 2 seconds, inject the new HTML, and run the JS
setTimeout(function(){
document.getElementsByTagName('P')[0].innerHTML = parts.html;
eval(parts.js);
}, 2000);
// This is the function inside the script tag
function changeColorEverySecond() {
document.getElementsByTagName('p')[0].style.color = getRandomColor();
setTimeout(changeColorEverySecond, 1000);
}
// Here is a fun fun function copied from:
// https://stackoverflow.com/a/1484514/2413712
function getRandomColor() {
var letters = '0123456789ABCDEF';
var color = '#';
for (var i = 0; i < 6; i++) {
color += letters[Math.floor(Math.random() * 16)];
}
return color;
}
<p>Before</p>

Categories