I’m a beginner in JavaScript and have the following problem,
I have multiple pages in 2 languages. Later maybe more. I use a javascript var to set the language. Either:
Var language=”de”; or var language=”en”;
then I used this to load the correct language file:
<script src="javascript"+language+".js" type="text/javascript"></script>
Is there a way to change this variable with an onclick() event. So that it changes and stays changed until I change it again?
Thanks for you time.
You can add scripts dynamically like this:
var selectorEls = document.querySelectorAll(".language-select");
var current;
function _handleClick ( ev ) {
if ( current ) current.parentNode.removeChild(current)
var language = ev.target.getAttribute("data-language");
var newScript = document.createElement("script");
var newSrc = "javascript" + language + ".js";
newScript.setAttribute("src",newSrc);
current = newScript;
document.head.appendChild(newScript);
}
for ( var i = 0; i < selectorEls.length; i += 1 ) {
selectorEls[i].addEventListener("click", _handleClick);
}
<a class="language-select" data-language="en">EN</a>
<a class="language-select" data-language="fr">FR</a>
<a class="language-select" data-language="de">DE</a>
This code binds clicks on a number of <a> elements, each with a language data attribute. Clicking on one creates a new <script> with the correct language and adds it to the page. It also deletes any scripts that you've added previously this way, to ensure no clashes.
Related
I have a list of products say:
laptops/prod1.html
laptops/prod2.html
laptops/prod3.html
monitors/prod1.html
monitors/prod2.html
monitors/prod3.html
I would like a button on my page that 'cycles' through the available items.
No idea how to do this. Is this possible with javascript?
function nextProduct(incr) {
var href = window.location.href
, offset = (typeof(incr)==='undefined' ? 1 : incr);
window.location = href.replace(/(\d+)\.html/, function(m, g1) {
return (Number(g1) + offset) + '.html'
});
}
Then you can do something like:
var button;
button = document.getElementByID('next-button');
button.addEventListener('click', function() { nextProduct(1); });
button = document.getElementByID('prev-button');
button.addEventListener('click', function() { nextProduct(-1); });
Setup a main page, this should not be a static html page but in your server side language of choice.
Include jquery to a main page using a script tag (you can get jquery from http://jquery.com/).
Your html could look like this:
<div id='content'></div>
<div>
<a href='javascript:void(0)' id='prev' class='btn'>Previous</a>
<a href='javascript:void(0)' id='next' class='btn'>Next</a>
</div>
In your js file you would have something like this:
var currPage = 0;
var pageList = ["laptops/prod1.html","laptops/prod2.html", "laptops/prod3.html"];
var totalPages = pageList.length;
$(".btn").on("click",function(){
//if we are at the last page set currpage = 0 else increment currPage.
currPage = currPage < (totalPages - 1) ? ++currPage : 0;
var page = pageList[currPage];
$('#content').load(currPage);
});
Some points to consider:
You will want to decide if the first page gets loaded on the main page load or on click
You will need to set a js variable to keep track of the currently loaded page
You will need to add some method of storing all the possible pages (think an array). This can get printed out to a script tag on the page on page load.
You need to decide what happens when you hit the end of the line. You can either cycle around or grey out the appropriate link.
jquery on
jquery load
I am having difficulty writing some JavaScript that will cycle through an array of .js files.
I have some JavaScript widgets saved in .js files.
I want to be able to click a "Next" or "Previous" button to cycle through an array of those .js files and have the widgets called and displayed on my HTML page. They can be displayed in an iFrame if that would be a better solution.
I will continue researching until a kind soul helps out. Thanks a bunch in advance!
I have tried:
<script>
function onWindowLoad(){
document.getElementById('js_type').innerHTML = ****.settings.type;
var widget_arr = [1column.js,2column.js,1row.js,modal.js]; //etc..etc..
var currentWidget = 0;
theBtn.onRelease = function(){
currentWidget++;
if(currentWidget == widget_arr.length){
currentWidget=0;
}
var selectedWidget = widget_arr[currentWidget];
//now you have a variable pointing to the next widget..
//what you do with it is up to you.. add the code you need..
}
and this
<SCRIPT LANGUAGE="JavaScript">
<!--
// Use the following variable to specify
// the number of widgets
var NumberOfWidgets = 4
var widget = new Array(NumberOfWidgets)
// Use the following variables to specify the widget names:
widget[0] = "1column.js"
widget[1] = "2column.js"
widget[2] = "1row.js"
widget[3] = "modal.js"
var widgetNumber = 0
function NextWidget()
{
widgetNumber++
if (widgetNumber == NumberOfWidgets)
widgetNumber = 0
document.widgets["VCRWidget"].src = widget[widgetNumber]
}
function PreviousWidget()
{
widgetNumber--
if (widgetNumber < 0)
widgetNumber = NumberOfWidgets - 1
document.widgets["VCRWidget"].src = widget[widgetNumber]
<IMG SRC="modal.js" NAME="VCRWidget">
}
//-->
</SCRIPT>
Code for the previous and next buttons:
<A HREF="javascript:PreviousWidget()">
<IMG SRC="prev.png" BORDER=0></A>
<A HREF="javascript:NextWidget()">
<IMG SRC="next.png" BORDER=0></A>
One idea can be to use the fact thst even a static page can have parameters in the url. You can for example:
create the html page that will be opened in the <iframe> with any js include you need (e.g. jquery)
add to this page a js function that given a widget js filename will create a <script> tag loading the widget creation code.
extract the name of the js file to use to call the function in (2) from document.location.href by looking at the part of the string after ?
in your main page create dinamically the iframe using for example contdiv.innerHTML = "<iframe src=\"widgetpage.html?" + widgetname + ".js\"></iframe>";
With this approach the widgets will be shown in a separate html page without interferring with your main page.
I need to manipulate HTML code. Specifically, the user should be able to copy/paste the code to create an AddThis button in a textarea, and I want to manipulate the pasted code.
A typical AddThis button looks like this :
<!-- AddThis Button BEGIN -->
<div class="addthis_toolbox addthis_default_style ">
<a class="addthis_button_facebook_like" fb:like:layout="button_count"></a>
<a class="addthis_button_tweet"></a>
<a class="addthis_counter addthis_pill_style"></a>
</div>
<script type="text/javascript">var addthis_config = {"data_track_clickback":true};</script>
<script type="text/javascript" src="http://s7.addthis.com/js/250/addthis_widget.js#pubid=ra-123456798"></script>
<!-- AddThis Button END -->
It consists of start and end comments, a div and/or some links, followed by 2 scripts: a config setting, and a call to their library.
The problem is, we need to call this many times on the page ; so, if I just put this every time I want to place an AddThis button, I fear that at least some browsers will have weird behavior, if it works at all.
So, I want to extract the config setting and the lib call, so I can call them just once, and extract the buttons config, so I can place it as many times as I want on the page.
I have already done that :
var codeAT = $(this).val();
if (codeAT.indexOf("AddThis Button BEGIN") >= 0) {
codeAT = codeAT.replace("<", "<");
codeAT = codeAT.replace(">", ">");
codeAT = $(codeAT);
// extract the call to the config var and the lib
var scriptConfig = "";
var scriptSRC = "";
codeAT.each(function() {
if ($(this).attr("nodeName") == "SCRIPT") {
if ($(this).attr("src") && $(this).attr("src") != "") {
scriptSRC = $(this).attr("src");
} else {
scriptConfig = $(this).text();
}
}
});
// extract the addthis identifier
scriptSRC = scriptSRC.split("=")[1];
}
Now, I can use the vars scriptConfig (with var addthis_config = {"data_track_clickback":true};) and scriptSRC (with ra-123456789), and they have the correct values.
What I want now, is the original code (between the two comments), without the comments, and without the script tags.
To remove the tags, I tried to use codeAT.remove($(this)), but it crashes (something about c.replace not being a function).
To get the code back, I tried codeAT.html(), but it gets only the tags.
Instead of .each() I'd do:
//remove <script> tags and get required info
var scriptSRC = $('script[src]', codeAT).remove().attr('src');
var scriptConfig = $('script:not([src])', codeAT).remove().text();
//get the code (as string)
var code = $('<div>').append(codeAT).remove().html();
I have an html page with (among other things) a Unity3D window. I would like to replace everything on the page without causing the Unity window to reload. I have tried the following jquery-tastic
function replaceSurround(keepElem, newElem)
{
keepElem.siblings().remove();
keepElem.prepend(newElem.prevAll());
keepElem.append(newElem.nextAll());
var keepParent = keepElem.parent();
var newParent = newElem.parent();
if (keepParent && newParent)
{
replaceSurround(keepParent, newParent);
}
}
where keepElem is an element in the original document and newElem is the corresponding element in the new document, but it did not work very well.
Here is what I've got, it seems to work...
jQuery.fn.rewrap = function(newWrap){
var $parent = jQuery(this).parent();
var $clone = jQuery(this).siblings().clone()
var $newParent = $clone.wrap(newWrap).parent().clone();
$parent.replaceWith($newParent);
}
$('#header').rewrap('<div class="container" style="background-color:blue;" />');
I tested it on the Stackoverflow website. One small problem though, it seems to be refiring some onX events...?
[edit]
On second thought, that is not what you meant at all....
Can't you just do something like:
$('#result').load('ajax/test.html #result');
?
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>