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.
Related
In my project ,I have to load JS and CSS file dynamically after the page load.
By using below code I am able to add and remove the js file But after adding the new file by removing the previous one,then the previous file is not shown in the header but when I run the code both js file code is executed.I don't known how to remove the file completely ,Can some body help me.
For that the code is.
In the the view page header:-
<link rel="stylesheet" id="videoCss" />
<script id="videojs"></script>
Jquery for Dynamically load JS and CSS file:-
function addRemoveJsCssFile(filename, filetype)
{
var fileref='';
if (filetype == "js") { //if filename is a external JavaScript file
document.getElementById("videojs").remove();
fileref=document.createElement('script');
fileref.setAttribute("type", "text/javascript");
fileref.setAttribute("src", filename);
fileref.setAttribute("id", "videojs");
}
else if (filetype == "css") { //if filename is an external CSS file
document.getElementById("videoCss").remove();
fileref = document.createElement("link");
fileref.setAttribute("rel", "stylesheet");
fileref.setAttribute("type", "text/css");
fileref.setAttribute("href", filename);
fileref.setAttribute("id", "videoCss");
}
if (typeof fileref != "undefined")
document.getElementsByTagName("head")[0].appendChild(fileref)
}
In this function we have to pass the file location and type of file i.e css or js to add file dynamically.Thank you.
I don't know if I've understood your issue, but let me try to explain:
if the original script is in head section, it will be executed immediately, because Javascript is a procedural language, so there's nothing that you can do in a script placed "later": scripts defined earlier are executed earlier so, maybe your problem is when you call your function, it's simply too late to stop the videojs execution.
On the other side with scripts defined before, you can't see script tags defined later.. or better, you could if you're deferring, but in a deferred situation you'll be fighting again with the same issue, the videojs script would be always executed (it would be always too late or too early, because your statements executes or before, or after, there isn't a third way).
Of course you can load a script before just to set a global object that could say to videojs "stop, don't proceed with your stuff!" but obviously you shall edit videojs code either, with a wrapper "if" that asks that object the permission to proceed, and I don't think that's the response you're looking for.
But the question is: what's executed in that javascript videojs, an event binder that starts on load? Or in another event? Or is just a sequence of statements that are executed - sorry for the wordplay - sequentially?
In the first and second case there's something that you can do before: if video.js starts when an event is triggered, you can stop that function to be executed, operating before that trigger: you must delete the event subscription. To unbind the event, you must know how the first script operates and what event it subscribes in order to unbind it.
Here is how to execute script before jQuery ready event (but it's valid also for native javascript events, so I think that might be helpful):
running jQuery code before the dom is ready
This answer is useful even for every document events, not only for the load or "jQuery ready".
But, even if it's possible to remove the bind "vanishing" every videojs script effects, it's not a clean job, because
Overall, videojs has been executed
This will work only with videojs and at least it may work only with hardcoded scripts that uses the same event to start, but not for all hardcoded scripts
So, what I suggest for your purpose, it's to manage load and unload of scripts entirely with this manager, don't hardcode them in HTML.
PS: Have you ever heard about require.js?
If not, take a look here
Instead of deleting whole element, and than creating new one, maybe try just to change the 'src' attribute in existing element?
now
document.getElementById("videojs").remove();
fileref=document.createElement('script');
fileref.setAttribute("type", "text/javascript");
fileref.setAttribute("src", filename);
fileref.setAttribute("id", "videojs");
suggest
document.getElementById("videojs").setAttribute("src", filename);
You can use $.getScript() to dynamically load js file.
Try this
$('#scriptid').remove(); //remove it first and then add the new one
var script = document.createElement('script');
script.src = something;
document.head.appendChild(script); //Add element to head tag
OR
$("<style type='text/css' href=''></style>").appendTo("head");
$("<script type='text/javascript' src=''></script>").appendTo("head");
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);
I'm trying to load a CSS dynamically in cordova over a xhr request.
The loading of the CSS is not a Problem, I can load it over xhr and store it to the filesystem over the HTML5 File API. Then I can get a URL this works perfectly.
But if i create a new link element in the header by javascript, like this:
<link rel="stylesheet" type="text/css" id="skin" href="cdvfile://localhost/temporary/mydomin.tdl/skin.css">
Thy stylesheet don't have any effect, how can I force cordova to take the stylesheet in account?
* UPDATE: I've got a working solution and I'll add it to my answer below *
I've found this problem and the suggested answers unfortunately haven't resolved it.
Loading the CSS data from an external PHP script via an XHR request (as my CSS data is dynamic to each page) I use:
var storeCSSURL = "https://www.example.com/dynamicCSS.php?storeID=x";
$('head').append('<link rel="stylesheet" href="' + storeCSSURL + '" type="text/css" />');
I'd also tried replacing the existing stylesheet link with the new URL; and added datetime stamp to it to prevent caching, which also didn't work.
Works great in the web browser and I know the data is loading through the XHR request and also being applied to the head CSS tag, although it doesn't work in Cordova / Phone Gap... the Apps just don't update with the CSS changes from the PHP script.
* NEW UPDATE *
I finally came up with a solution that works, it's a bit of a hack as it doesn't directly solve the problem; but works around it and is great for my needs.
In PhoneGap / Cordova, I use a pageInit.js type scenario that loads the web page in dynamically from a PHP script, I imagine most people use it in a somewhat similar way.
After page load I added:
$("body").append('<style id="dynamicStyles"></style>');
Then simply did a $.POST request to the Dynamic CSS (PHP) file, which returned all the dynamic style data; which I then loaded into a style tag.
This looks something like this:
$.post("https://www.example.com/controller.php", { url: url }, function (data, status) {
if (status == "success") {
$("body").html(data);
// Loads the main page content into the body tag
$("body").append('<style id="dynamicStyles"></style>');
// Appends the main page content with a style tag
$.post("https://www.example.com/dynamicCSS.php", { storeID: storeID }, function (data, status) {
if (status == "success") {
$("#dynamicStyles").html(data);
// Loads CSS data from external PHP script dynamically
// then places it into the new style tag.
}
});
}
});
The CSS updates from this line:
$("#dynamicStyles").html(data);
This loads all the new dynamic style data into the style tag; so the result is an on-page style definition, which you can replace the styles with using .html() at any stage from your external PHP with CSS data.
Phone Gap / Cordava recognises the style tag changes and updates visuals accordingly :-)
I'm sure you could set your project up to load all CSS data in this way instead of the normal head CSS link; and you'd never have that annoying CSS caching issue with Phone Gap / Cordova.
I hope this is useful to someone!
$('head').append('<link rel="stylesheet" href="style2.css" type="text/css" />');
$(document).ready(function () {
$("a").click(function () {
$('head').append('<link rel="stylesheet" href="style2.css" type="text/css" />');
});
});
When I launch my page, the css is totally messed up because my js is supposed to dynamically load css on click (mobile or standard website css). Currently, it just loads them both. Here's the code:
function loadjscssfile(filename, filetype)
{
if (filetype=="css")
{
var fileref = document.createElement("link");
fileref.rel= "stylesheet";
fileref.type = "text/css";
fileref.href = filename;
document.getElementsByTagName("head")[0].appendChild(fileref)
}
}
loadjscssfile("HCSS.css", "css")
I have two links on the site. One loads the mobile css, the other loads the standard website css. I have it linked like this:
load hcss
<br/>
load mobile
What you are after is swapping css files, not just loading a new one. In jquery it would probabaly look something like this (code not tested):
function swapCssFiles(fileToLoad, fileToUnload) {
$('head link[href="'+fileToUnload'"]') // select the tag with css to unload
.attr('href', fileToLoad); // swap the href attribute with the file to load
}
This is off course possible with 'pure' javascript, but I'm to much a jQuery addict to tell you how. If you see how easy the syntax is, you can probably tell why.
Your links would look something like this:
load hcss
I hope this is helpfull.
Note however that this is not the way I would approach this. If you want to target mobile devices with specific css, I would use mediaqueries to detect screensize, and not javascript.
I am building a firefox extension and need to insert some elements and css into the doc.
I tried following How can a Firefox extension inject a local css file into a webpage? and Inserting CSS with a Firefox Extension, but had no luck.
I know am missing some silly point but I cant really make out what it is,and would really appreciate if some one can point it out to me.
Heres my chrome.manifest:
content helloworld content/
overlay chrome://browser/content/browser.xul chrome://helloworld/content/overlay.xul
locale helloworld en-US locale/en-US/
skin helloworld classic/1.0 skin/
And my overlay.js:
var fileref = gBrowser.contentDocument.createElement("link");
fileref.setAttribute("rel", "stylesheet");
fileref.setAttribute("type", "text/css");
fileref.setAttribute("href", "resource://helloworld/skin/global.css");
gBrowser.contentDocument.getElementsByTagName("head")[0].appendChild(fileref);
I even tried this inside my overlay.js
var sss = Components.classes["#mozilla.org/content/style-sheet-service;1"]
.getService(Components.interfaces.nsIStyleSheetService);
var ios = Components.classes["#mozilla.org/network/io-service;1"]
.getService(Components.interfaces.nsIIOService);
var uri = ios.newURI(url, null, null);
sss.loadAndRegisterSheet(uri, sss.USER_SHEET);
No luck again.
What am I missing? I seriously can't figure out.
Tried using the console,shows nothing
When I copy and paste my href "chrome://helloworld/skin/global.css", I can see my css file in the browser.
You should set the javascript.options.showInConsole, restart, then check the Error Console.
The nsIStyleSheetService snippet should be the simplest to get working.
What's the url in it? The other snippets/comments you posted contradict each other -- the chrome.manifest and your comment "When I copy and paste my href ..., I can see my css file in the browser" imply you're using chrome://helloworld/skin/global.css, but your other snippet shows you use a resource:// URL, which is a different beast.
How do you determine the snippet is not working? Could you have your stylesheet wrong? Did you try something simple like * {color:red !important;} as your CSS?
P.S. If you use nsIStyleSheetService, please note the comment on MDC about taking care not to register the same sheet multiple times.
Also note that when using nsIStyleSheetService you should be careful not to make your styles apply to the pages you didn't intend to modify. #-moz-document can be very useful for that.
I'm not sure if this will solve your problem, but you should listen for load events in all tabs changing your overlay.js to something like:
window.addEventListener('load', function () {
gBrowser.addEventListener('DOMContentLoaded', function (event) {
if (event.originalTarget.nodeName == '#document' &&
event.originalTarget.defaultView.location.href == gBrowser.currentURI.spec)
{
var document = event.originalTarget;
// Your css injection here
}
}, false),
true);
Forget the overlay.js file and the overlay.xul file, you don't need it. Use the style instruction for chrome.manifest instead, like so:
style chrome://browser/content/browser.xul resource://helloworld/skin/global.css
No js req'd