I placed a class in my <html> element called "no-js". This indicates that the user isn't using javascript, (whether it be disabled or blocked). And then, in a script file I created, I want to revoke "no-js" and inject "js" so that I can determine if the user is using javascript or not via classes. I tried using the replace() method by querying the html tag, but it isn't working. Here's what I have:
var html = document.getElementsByTagName("html")[0];
if(html.className == "no-js") {
html.className.replace("no-js", "js"); // user has JS enabled
}
There are no errors in Google Chrome or Firefox's bug console, but neither is it changing no-js to js. I would use the <noscript> tag but I like to keep the markup side of it clean.
replace returns the new string, it doesn't modify the original.
Try html.className = 'js', since you've already established that it's the only class name with your if statement.
EDIT: Also, the <html> tag is already available as document.documentElement.
document.documentElement.className = 'js';
That's all you need, really. No if statement, no variable, nothing.
The accepted answer is indeed correct, but this way will replace all classes of the <html>, not only .no-js.
This little script will do the same thing, but will instead search only for the no-js class and rewrite it.
document.documentElement.className = document.documentElement.className.replace(/\bno-js\b/g, '') + ' js ';
Took script from here, very simple!
http://snipplr.com/view/63895/remove-nojs-class-from-html-tag-add-js-class/
You forgot to assign the html.className to the new value:
var html = document.getElementsByTagName("html")[0];
if(html.className == "no-js") {
html.className = html.className.replace("no-js", "js"); // user has JS enabled
}
With a little regex
(function(html) {
html.className = html.className.replace(/\bno-js\b/, 'js')
})(document.documentElement);
<!DOCTYPE html>
<html class="no-js">
<head>
</body>
</html>
Related
https://stackoverflow.com/a/43635720
On this answer, it says to define a variable (window.parentPage = true;) in the index.html page. How can I go about doing this?
You would need to define the variable using JavaScript. You can embed some JavaScript in the HTML file by encasing it in a script tag like so:
<script type="text/javascript">
window.parentPage = true;
</script>
First you need to clearly realize your reason... what you want to achieve.
After that defining that to yourself:
First option:
You can store/save some data as stated on the link you added to your question inside a tag, like that:
<script>
var myLittleBox = "box content";
</script>
And access it later like:
<script>
myLittleBox = myLittleBox + " extra content";
console.log(myLittleBox);
//this will print "box content extra content"
</script>
You need to use the tag to access the javascript environment.
Second option:
You can save/store data with pure HTML using an with type "hidden" to not show it on screen as an input box, and changing it's value, like that:
<input type="hidden" value="box content">
But this way you'll not be able to access the data directly without aid of javascript code, unless you send this input somewhere reachable as GET or POST within a and recover it getting the respective GET or POST.
Javascript variables:
https://www.w3schools.com/js/js_variables.asp
Ex: https://www.w3schools.com/js/tryit.asp?filename=tryjs_variables
HTML input:
https://www.w3schools.com/tags/tag_input.asp
HTML form handling:
https://www.w3schools.com/php/php_forms.asp
You're probably trying to understand the first option, but you question do not make that clear. Anyway, good studies.
Whatever you do you will have to use JavaScript in order to access the variable. An orthodox way of doing it that is not mentioned yet is using an data-attribute inside the html and than you access it by JavaScript:
const attributeName = 'data-parentPage';
const setup = () => {
let parentPageBool = document.querySelector(`html[${attributeName}]`).getAttribute(attributeName);
console.log(parentPageBool)
};
window.addEventListener('load', setup);
<html data-parentPage="true">
</html>
I have an app that uses HTML Email templates. I want to write a script that parses through the HTML of an email template and modifies the code. This is easy when the template is loaded on the page, but I want to do these dynamically where the HTML is just a value from a <textarea> (or more specifically CodeMirror).
The value of the <textarea> (CodeMirror) would look like this:
<!doctype html>
<html>
<head>...HEAD HTML...</head>
<body>...BODY HTML...</body>
</html>
I've tried:
// This part works great. Stores the HTML as a varaible.
var template_html = codeMirrorInstance.getValue();
// This shows the proper HTML in console as text
console.log(template_html);
// From here I can't access the HTML though
console.log($(template_html).find('body'));
But I keep getting undefined. Nothing I try is working... any ideas?
It appears you can do what you are trying to do. You just have to create a new document and possibly an second instance of jQuery.
You should take a look at this: https://stackoverflow.com/a/15496537/1819684 and this: https://stackoverflow.com/a/15479402/1819684
$(function() {
var doctype = document.implementation.createDocumentType( 'html', '', '');
var dom = document.implementation.createDocument('', 'html', doctype);
var jq2 = jQuery(dom);
var txt = $('textarea').val();
console.log(jq2.find('html').html(txt).find('body'));
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<textarea>
<html>
<head>...HEAD HTML...</head>
<body>...BODY HTML...</body>
</html>
</textarea>
I have created a very simple editor that has been working great. However, I just tried to put JavaScript into it and I can't get it to work.
The code for the editor:
<div id="buttoncontainer">
<input id="button" onclick="update();" type="button" value="Update page">
</div>
<div id="tryitcontainer">
<textarea id="codebox"></textarea>
<iframe id="showpage"></iframe>
</div>
The JavaScript for the editor:
<script>
function update() {
var codeinput = document.getElementById('codebox').value;
window.frames[0].document.body.innerHTML = codeinput;
}
</script>
I just wanted to run some simple JavaScript that changes an image when it is clicked. This code works fine when I run it in a full browser, so I know its the editor thats the problem.
Is there a simple fix for this that I'm missing?
The button is not finding the update() method. You need that function to be globally available:
http://jsfiddle.net/t5swb7w9/1/
UPDATE: I understand now. Internally jQuery basically evals script tags. There's too much going on to be worth replicating yourself... either use a library to append, or eval the code yourself. Just a warning that eval'ing user input is rarely a good thing and is usually a welcome mat for hackers.
window.myScope = {
update: function() {
var div = document.createElement('div'),
codeinput = document.getElementById('codebox').value,
scriptcode = "";
div.innerHTML = codeinput;
Array.prototype.slice.apply(div.querySelectorAll("script")).forEach(function(script) {
scriptcode += ";" + script.innerHTML;
div.removeChild(script);
});
window.frames[0].document.body.appendChild(div);
// hackers love to see user input eval'd like this...
eval(scriptcode);
}
};
And then you would update your button like so:
<input id="button" onclick="myScope.update();" type="button" value="Update page">
Or, even better, use addEventListener and forget the onclick part altogether. I'll let you do that research on your own ;)
JavaScript inserted via innerHTML will not be executed due to security reasons:
HTML5 specifies that a <script> tag inserted via innerHTML should not execute.
from MDN: Element.innerHTML - Security considerations, see also: W3: The applied innerHTML algorithm.
A possible solution using the jQuery method .append() works around that, as it somehow evals the content. But this will still not solve your problem, as the JavaScript code is executed in the current scope.
Here's a test scenario:
function update() {
var codeinput = document.getElementById('codebox').value;
$(window.frames[0].document.body).append(codeinput);
}
Try it here
Try to insert this script:
<script>
alert( document.getElementById('tryitcontainer') );
</script>
and this one:
<p id="test">Test</p>
<script>
window.frames[0].document.getElementById('test').innerHTML = 'updated';
</script>
The first one will return a [object HTMLDivElement] or similar. Here you can see, that you're still in the same scope as the parent frame. The second one will correctly update the content within the iframe. Keep that in mind, when experimenting with those things.
Maybe Executing elements inserted with .innerHTML has some more infos for you.
<html>
<head>
<title>Test</title>
</head>
<body>
hello
<script>
var str=document.body.innerHTML;
document.body.innerHTML=str.replace(/hello/g, "hi");</script>
</body>
</html>
In this code hello.html and hello will change hi.html and hi. I don't want to replace href="". How to write regular expression for that ?
The following regex replace wil do what you want:
<script>
var str=document.body.innerHTML;
document.body.innerHTML=str.replace(/(>[^<]*)hello/g, "\1hi");
</script>
But I think it is still fragile, and any solution with regex replaces in .innerHTML will be... Remember that regexes are always a hacky solution when trying to solve problems which involve html/xml parsing.
What do you need this for? Am I guessing correctly when I say that you want to replace all the text content of the document?
In that case, I would suggest getting a list of all content nodes from the DOM (see this question’s accepted answer for two ways to do this, one with jQuery and one without).
Using that, you could then apply your function to update each text node's contents:
var textNodes = getTextNodesIn(el);
for (var i = 0; i < textNodes.length; i += 1) {
textNodes[i].innerHTML = textNodes[i].innerHTML.replace(/hello/g, "hi");
}
This would leave all the HTML attributes unaffected. If you want to adjust those as well (excepting, of course, any href attribute), you could expand the getTextNodes function to include attributes (excepting href attributes) in the returned list of nodes.
I'm very much not a javascript/html/css person.
Even so I find myself in the position of having to do a webpage. It's static the only thing you can do on it is click on flags to change dispay-language based on a cookie.
If the cookie says "this" I write text in one language, and if the cookie says "that" I write in another language. This works perfectly but I have to use lots of document.write statements and it's ugly and cumbersome.
Right now I type the text I want and use a macro in emacs to fold the text at about
80 chars and put document.write(" in the beginning of each line and "); at the end. I then paste it into the web page in a if(cookie_this) { } else { }.
There must be a better way to do it... Please?
Edit:
I was looking workaround for the limitations in document.write
Constraints:
No server side magic, that means no ruby/php/perl
One page only, or rather only one visible url
The solution should be simpler than the working one I have
Expanding on artlung's answer:
You can display or hide things given a lang attribute (or any other criteria, such as a class name). In jQuery and HTML:
<p>Language:
<select id="languageSelector">
<option value="en">English</option>
<option value="es">Español</option>
</select>
</p>
<div lang="en-us">
Hello
</div>
<div lang="es">
Hola
</div>
<script type="text/javascript">
var defaultLanguage = 'en';
var validLanguages = ['en', 'es'];
function setLanguage(lang, setCookie) {
if(!$.inArray(languages, lang))
lang = defaultLang;
if(typeof(setCookie) != 'undefined' && setCookie) {
$.cookie('language', lang);
}
// Hide all things which can be hidden due to language.
$('*[lang]').filter(function() { return $.inArray(languages, $(this).attr('lang')); }).hide();
// Show currently selected language.
$('*[lang^=' + lang + ']).show();
}
$(function() {
var lang = $.cookie('language'); // use jQuery.cookie plugin
setLanguage(lang);
$('#languageSelector').change(function() {
setLanguage($(this).val(), true);
});
});
</script>
jQuery can do this with I lot less ease, but you could create an element then set that elements innerHTML property. You may have to change your call slightly so that you append the child element. See createElement function for more info. For example
<script type="text/javascript">
function writeElement(language, elementId) {
var newElement = document.createElement("span");
if (language = "this") {
newElement.innerHTML = "text for this";
}
else {
newElement.innerHTML = "text for that";
}
var element = document.getElementById(elementId);
element.appendChild(newElement);
}
</script>
Usage
<span id="data1"></span>
<script type="text/javascript">
writeElement("this", "data1")
</script>
Add a comment if you can support jQuery and you want a sample of that instead.
I think that the right way to approach this is to parse the Accept-Language header, and do this server-side.
But in the instance that you are stuck with client-side scripting. Say your content was marked like this
<script type="text/javascript">
if(cookie_this) {
document.getElementById('esContent').style.display = 'block';
} else {
document.getElementById('enContent').style.display = 'block';
}
</script>
<div id="esContent" style="display:none">
Hola, mundo.
</div>
<div id="enContent" style="display:none">
Hello, world.
</div>
This does not degrade for people with CSS enabled, and JavaScript disabled. Other approaches might include using Ajax to load content based on a cookie value (you could use jQuery for this).
If you just want one visible URL, but can host multiple pages on the server you could also try XHR. I use jQuery because I am most familiar with it although it would be possible to implement in javascript alone:
<html>
<head>
<script type="text/javascript" src="path/to/jquery.js"> </script>
<script type="text/javascript">
$(document).ready(function () {
if (cookie_this) {
$("body").load("onelanguage.html body");
} else {
$("body").load("otherlanguage.html body");
}
});
</script>
</head>
<body>
</body>
</html>
The detection should be on the server (preferably based on the Accept-Language header the client sent), and you should send a static file that has already been localized.
This does not fit the (edited) criteria of the original question, but may be useful regardless.
Use a server-side script. What you're looking for can easily be done in PHP. You'd probably want a hierarchy of documents based on language, and would look up given that. For example, a directory tree:
/en/
/en/page1.html
/en/page2.html
/es/
/es/page1.html
/es/page2.html
In PHP it's as simple as
$language = $_GET['lang'];
$page = $_GET['page'];
include($language . '/' . $page);
// URL is: /whatever.php?lang=LANGUAGE_HERE&page=PAGE_HERE
However, that has many security issues along with it. Sanitize your input and make sure the directory and file exist. Fuller example:
$contentRoot = './'; // CHANGE ME. Do include trailing /.
$defaultLanguage = 'en'; // CHANGE ME.
$defaultPage = 'home'; // CHANGE ME.
if(isset($_GET['lang']))
$language = $_GET['lang'];
else
$language = substr($_SERVER['HTTP_ACCEPT_LANGUAGE'], 2);
if(isset($_GET['page']))
$page = $_GET['page'];
else
$page = $defaultPage;
$languageDir = basename($_GET['lang']) . '/';
$pageFile = basename($page) . '.html';
if(!file_exists($contentRoot . $languageDir) || !is_dir($contentRoot . $languageDir))
$languageDir = $defaultLanguage;
$fullFileName = $contentRoot . $languageDir . $pageFile;
if(!file_exists($fullFileName) || !is_file($fullFileName) || !is_readable($fullFileName))
$pageFile = $defaultPage;
readfile($fullFileName);
// Or, if you want to parse PHP in the file:
include($fullFileName);
You may also want to use mod_rewrite (Apache) to allow URL's such as http://www.mysite.com/en/page1. (Just be sure to hide the actual page.)
// TODO mode_rewrite rules
Another approach is putting the above hierarchy into the document root and handing out URL's directly. This gives you less power (e.g. templating is more difficult), however, and you have to worry about external media being referenced properly.
If you're looking for a dynamic approach, on the client side use Javascript to fetch the data using Ajax. This is also trivial, and does not require a dynamic server backend. I recommend a Javascript framework such as jQuery to make this as easy as possible.
There is no good way to do this in JS. The best way is to use VERY simple PHP code.
But, if you want, there is a way in JS - prepare pages like these:
some pages with different language versions, like index_en.html, index_ru.html
main index.html page, where you have code like
if(cookie) windows.location.replace('index_en.html') else ...