CSS style refresh in IE after dynamic removal of style link - javascript

I've got a problem with the dynamic style manipulation in IE7 (IE8 is fine). Using javascript I need to add and remove the < link /> node with the definition of css file.
Adding and removing the node as a child of < head /> works fine under Firefox. Unfortunately, after removing it in the IE, although The tag is removed properly, the page style does not refresh.
In the example below a simple css (makes background green) is appended and removed. After the removal in FF the background turns default, but in IE stays green.
index.html
<html>
<head>
</head>
<script language="javascript" type="text/javascript">
var node;
function append(){
var headID = document.getElementsByTagName("head")[0];
node = document.createElement('link');
node.type = 'text/css';
node.rel = 'stylesheet';
node.href = "s.css";
node.media = 'screen';
headID.appendChild(node);
}
function remove(){
var headID = document.getElementsByTagName("head")[0];
headID.removeChild(node);
}
</script>
<body>
<div onClick="append();">
add
</div>
<div onClick="remove();">
remove
</div>
</body>
</html>
And the style sheet:
s.css
body { background-color:#00CC33 }
Here is the live example: http://rlab.pl/dynamic-style/
Is there a way to get it working?

Rybz, I, personally, would setup an "initial" style sheet to reset back to (also because it helps reset browsers to "my" desired initial settings, not the browser defaults) and when removing the style sheet from the DOM I would insert the one to reset to. I don't know if this will work for what you are trying to do, but it worked for me in the similar situation, and if I remember correctly I was having the same problem as you do, and that fixed it.

Related

Swap Stylesheet OnClick For Demo Page

My level of JavaScript experience is minimal. I have searched this site and the web for answers to my problem and found lots of them. I have cut-and-pasted then tested solutions but none work for me. I don't know where I'm going wrong.
I picked up this code here but clicking buttons makes no changes. Doesn't even set the wait cursor spinning as if it's thinking about it. (The test style sheet angelfish only attempts to change h2 color, for now.) Any help would be greatly appreciated as I have a real need to do this on my site.
<!DOCTYPE html>
<html>
<head>
<link
id="original"
rel="stylesheet"
type="text/css"
href="https://cyndikirkpatrick.com/wp-content/themes/twentysixteen-child/ctc-style.css"
/>
</head>
<script>
$('#original').click(function() {
$('link[href="https://cyndikirkpatrick.com/wp-content/themes/twentysixteen-child/ctc-style.css"]').attr(
'href',
'style1.css'
);
});
$('#angelfish').click(function() {
$('link[href="https://cyndikirkpatrick.com/wp-content/themes/twentysixteen-child/angelfish.css"]').attr(
'href',
'style2.css'
);
});
</script>
<body>
<h2>Javascript Change StyleSheet Without Page Reload</h2>
<button id="original">Original</button><br />
<button id="angelfish">Angelfish</button>
</body>
</html>
https://cyndikirkpatrick.com/test/
My end goal: One page that can switch styles for each texture set in my library, to produce a simplified version of this page:
https://cyndikirkpatrick.com/angelfish-texture-tiles-teal/
Style are not dynamically reset and reloaded if you modify the href.
You can however delete the style and append a new one in the body.
// Remove
var elements = document.querySelectorAll('link[rel=stylesheet]');
for(var i=0;i<elements.length;i++){
elements[i].parentNode.removeChild(elements[i]);
}
// Add
var head = document.getElementsByTagName('head')[0];
var link = document.createElement('link');
link.id = cssId;
link.rel = 'stylesheet';
link.type = 'text/css';
link.href = 'http://website.com/css/stylesheet.css';
link.media = 'all';
document.body.appendChild(link);
I just dropped back to mention the solution I used, for the moment. I think it's closest to Chris' suggestion. I'm making a function for each texture tile, then displaying them onclick in a "Demonstration Swatch" area. A visitor gets to see what the tiles look like as a repeating background.
I did it that way because research mainly provided examples of people changing one element. I watched quite a few videos, then cobbled together bits of code from W3school.
I am fairly sure I am doing this in the most awkward and repetitive way imaginable but I hope to make the code elegant as my understanding of JavaScript grows. For now, it works and serves its purpose.
Thanks again to all.
https://cyndikirkpatrick.com/texture-tiles/gray-texture-sets/

How to delay script tag until other script tag has run

I've been experimenting with metaprogramming in webpages, and need to delay a script tag from running until just after another script tag has been run. However, the script tag needs to be loaded first or both of them will fail.
Shortened and more readable version of what I'm trying to do:
<script defer>
w=function(){
<stuff that gives a parser error until modified by the next script tag>
}
</script>
<script>
<stuff that changes the previous script tag and any other script tags that ever will be added via the DOM
so it doesn't give a parser error>
</script>
<button onclick='w()'></button>
This would work perfectly well, except that the button's onclick attribute fails because the button was loaded before the first script tag was run.
Thanks in advance!
(EDIT: I linked a pastebin to show the full version of my code, it might clear things up a bit since it seems my summed-up version wasn't very good.
As suggested by #meagar in the comments, if you don't mind changing the type property of your "not actually javascript" script blocks you can do something like this:
<script type='derpscript'>
var derp;
var w=function(){alert('hello')};
derp||=5;
console.log(derp);
</script>
<script>
function compileDerps() {
// find all derpscript script tags
var x = document.querySelectorAll('script[type=derpscript]');
for(var i=0;i<x.length;i++){
meta=x[i].text
while(true){
pastmeta=meta;
console.log(exc=regex.exec(meta))
if(exc){
meta=meta.replace(regex,exc[1]+'='+exc[1]+'||');
}
if(pastmeta==meta){break;}
}
// make a new javascript script tag to hold the compiled derp
var s = document.createElement('script');
s.text = meta;
document.body.appendChild(s);
// delete the derpscript tag
x[i].parentNode.removeChild(x[i]);
}
}
//stuff that changes the previous script tag and any other script tags that ever will be added via the DOM
var regex=/([a-zA-Z$_][a-zA-Z$_1-9]*)(\|\|\=)/;
var meta;
var pastmeta='';
var exc='';
compileDerps();
</script>
<button onclick='w()'>THIS IS W</button>

How can I make a template tag inert in IE?

I have seen that there are polyfills to replicate the use of the html5 <template> element in internet explorer, but they all seem to be scripts that only end up hiding the template tag before activation. Unfortunately, this does not stop IE from rendering the content of the template. For example:
var template = document.querySelector('#myTemplate');
var myNode = document.importNode(template.content, true);
//comment out the line below to de-activate the template.
document.body.appendChild(myNode);
<template id="myTemplate">
<h1>You should only see this when the template is activated</h1>
<script>alert('this alert should only be displayed when the template is activated.')</script>
</template>
In IE, the alert is displayed even when the template content is not being appended to document.body. I understand that the example code isn't exactly appropriate for IE because the template tag doesn't have a content property, but adding that property to the element doesn't stop the alert script from running.
Is there any way to make the contents of the template tag completely inert to IE or do I just have to wait until the template element is properly implemented for edge?
Update(09/02/15):
As minitech stated in the comments, it looks like there is no way to make the contents of a tag completely inert in ie. As an alternative, I am looking into suppressing any code that would be executed at the time of parsing by modifying the tag. It feels like an ugly hack, but it seems to work for now. I found the original polyfill here: http://jsfiddle.net/brianblakely/h3EmY/
markup:
<script>
// Shim so we can style in IE6/7/8
document.createElement('template');
</script>
<template id="example">
<h1>This is template content.</h1>
<p id="great">It's really great.</p>
<script type="text/x-suppress">alert('hi')</script>
</template>
<div id="target">
<p>This is regular old content.</p>
</div>
script:
/* POLYFILL */
(function templatePolyfill(d) {
if('content' in d.createElement('template')) {
return false;
}
var qPlates = d.getElementsByTagName('template'),
plateLen = qPlates.length, elPlate, qContent, contentLen, docContent;
for(var x=0; x<plateLen; ++x) {
elPlate = qPlates[x];
qContent = elPlate.childNodes;
contentLen = qContent.length;
docContent = d.createDocumentFragment();
while(qContent[0]) {
docContent.appendChild(qContent[0]);
}
elPlate.content = docContent;
}
})(document);
/* EXAMPLE */
var elTemplate = document.getElementById('example').content.cloneNode(true),
elTarget = document.getElementById('target');
//Comment out the line below to test if the script will run before template activation.
activateTemplate(elTarget, elTemplate);
/* Template Activation */
function activateTemplate(targetNode, sourceNode){
var findScripts = sourceNode.querySelectorAll('script');
for (var i = 0; i < findScripts.length; i++) {
var testScript = findScripts[i];
testScript.setAttribute("type", "text/javascript");
}
targetNode.appendChild(sourceNode);
}
css:
template {
display: none !important;
}
So can someone tell me why I would be stupid to use this method to suppress scripts being loaded within a template tag in ie? Can anybody tell me a better way of doing this?
Here is my jsfiddle.
http://jsfiddle.net/rqqvvaft/4/

Adding a stylesheet dynamically

After the document.ready event fires, I load the stylesheet dynamically based on the user's resolution. This is what works in Chrome, Firefox and IE:
var TheFileName = '/SomeDirectory/SomeFileName.css';
if (document.createStyleSheet) {
//finally found something IE got right
document.createStyleSheet(TheFileName);
} else {
$('<style id="TestCSS" type="text/css"></style>').appendTo('head');
$.get(TheFileName , function (TheCSS) {
$("#TestCSS").append(TheCSS);
});
}
The problem is that it doesn't work in Safari. I don't have a mac so I don't have the console error but all I know is that the stylesheet doesn't get added. What do I need to change to make it work in Safari?
PS: I don't want to use media queries.
Edit
I initially had a function that used a <link> tag that was added. My page is entirely dynamically generated and the problem is that adding the stylesheet after the DOM is rendered makes the elements unstyled if you use a <link> tag. So what I do is use a setTimeout to check for $('#TestCSS').length to see if the stylesheet loaded and then I fire the functions that create the HTML. With a tag, there's no way of knowing when the CSS is attached.
Why not just insert the stylesheet as a link tag, instead of loading it with ajax, should be cross-browser ?
var link = document.createElement('link');
link.setAttribute('rel', 'stylesheet');
link.type = 'text/css';
link.href = '/SomeDirectory/SomeFileName.css';
document.head.appendChild(link);

Dynamically changing stylesheet path not working in IE and Firefox

I have the following file:
<html>
<head>
<title></title>
<link rel="css" type="text/css" href="/empty.css" title="css" />
<script type="text/javascript" src="/Prototype"></script>
<script type="text/javascript">
function load_content()
{
var d = new Date();
new Ajax.PeriodicalUpdater('content', '/DOC?'+d.getTime(),
{
method: 'post',
frequency: 5,
onSuccess: function(transport) {
for(i=0; (a = document.getElementsByTagName('link')[i]); i++)
{
if(a.getAttribute('rel') == 'css' && a.getAttribute("type") == 'text/css')
{
a.href = '/CSS?'+d.getTime();
}
}
}
});
}
</script>
</head>
<body>
<div id="content"></div>
<script type="text/javascript">
load_content();
</script>
</body>
</html>
Note: Ignore the d.getTime() calls...these are just to get around an issue with IE not loading a new page from an AJAX call because it's caching scheme is too aggressive.
Basically, when it reloads the file at /DOC, it is supposed to be setting the current stylesheet to the file at /CSS... both DOC and CSS and constantly changing.
What's weird is that in Chrome it works great. DOC loads up in the "content" div and the stylesheet gets set to CSS and that css is applied to the page. I can change with CSS page and withing 5 seconds, when the page is refreshed, the CSS will be refreshed as well.
But in IE and Firefox, the HTML will load and I can see that the href attribute of the stylesheet link IS getting changed to "/CSS + getTime()" but, while the HTML loads, the css is never applied to the page. I can even change the content of DOC and it updates, but the css is never even applied. It just stays a style-free page.
Does Firefox and IE not support changing the style sheet reference in this way?
Is there a better way to do this?
Rather than changing the sheet in a single link, try using alternate style sheets. See this link on using alternate style sheets:
http://www.alistapart.com/articles/alternate/
The best way to include files via javascript is to insert a new dom element.
var a = document.createElement('link');
a.href="inset.css";
a.rel="stylesheet";
document.getElementsByTagName("head")[0].appendChild(a);
However, obviously the problem you're going to run into though is that firefox and ie will not repaint the canvas once the document is finished loading (and you're using ajax). The way you get around that is by taking the contents of the stylesheets and including them in a style element. This sample code will change the color on the page dynamically.
function onLoadFunction() {
var a = document.createElement('style');
a.appendChild(document.createTextNode('body {color: blue;}'));
document.getElementsByTagName("body")[0].appendChild(a);
}
When you load a new sheet, just destroy the css inside the style element and replace it.
maybe this will help you ...
http://www.javascriptkit.com/javatutors/loadjavascriptcss.shtml
function loadjscssfile(filename, filetype){
if (filetype=="js"){ //if filename is a external JavaScript file
var fileref=document.createElement('script')
fileref.setAttribute("type","text/javascript")
fileref.setAttribute("src", filename)
}
else if (filetype=="css"){ //if filename is an external CSS file
var fileref=document.createElement("link")
fileref.setAttribute("rel", "stylesheet")
fileref.setAttribute("type", "text/css")
fileref.setAttribute("href", filename)
}
if (typeof fileref!="undefined")
document.getElementsByTagName("head")[0].appendChild(fileref)
}
It looks like you are simply reloading the existing page every time. Why not just use the refresh tag in your header to force the document to reload each time and put in the CSS and content server-side. A lot simpler and it works even with javascript disabled.
<meta http-equiv="refresh" content="5;url=http://example.com/DOC" />
It might be a caching issue. If you do a hard refresh (Ctrl+R in FF, Ctrl+F5 in IE) does it display the style properly? If that does fix it, you may want to look at removing the Last-Modified header from the CSS file or adding a cache control header telling the browser not to cache it.

Categories

Resources