How do I reference a javascript variable from a razor section? - javascript

I'm trying to dynamically render a CSS file to my view, but part of the location of the file is in a javascript variable.
Currently I have:
#section Styles {
#{
<link href="#Url.Content(Model.CssPath)" rel="stylesheet" type="text/css" />
}
}
But I need to include the variable in the path, like this:
#section Styles {
#{
var pathPrefix = "somePath/";
<link href="#Url.Content(pathPrefix + Model.CssPath)" rel="stylesheet" type="text/css" />
}
}
I understand the server-side code is evaluated before the javascript variable exists, so how else do I accomplish this?

First of all - why mixing client-side/server-side code?
You cannot use JS variable along with server-side generated content because - as you said - it is executed on server before client's browsers hits JS code. This is expected behavior.
If this variable value can be determined on the server-side, you should move it there.
If it has to be generated on the client side, you can generate <link> tag using document.createElement('link'); but it seems odd to me :)

Rather than trying to add the stylesheet via the razor view I would put the csspath into a javascript variable and then use jquery to combine it with the pathPrefix and append the stylesheet that way.
something like....
<script>
var cssPath = #Model.cssPath;
var pathPrefix = "www.";
$('head').append('<link rel="stylesheet" type="text/css" href="'+pathPrefix+cssPath+'">');
</script>

Related

How to dynamically load a CSS file avoiding navigator cache

I've usually loaded CSS files with PHP by adding a GET variable that changes each time. For example the value of the microtime
But I need to dynamically load a CSS file avoiding navigator cache for see the continuous changes making in production development.
<?php echo '<link rel="stylesheet" type="text/css" href="myFile.css?v='.round(microtime(true)).'"></script>';?>
Sometimes you will need to load a dynamic file name as well.
It is possible to do it without PHP like this:
<link rel="stylesheet" type="text/css" href="" id="myCSS">
<script>
var microTime = Date.now();
var myVar = "myCSSFile";
var myUrl = myVar+'.css' + '?v=' + microTime;
myCSS.href= myUrl;
</script>

Setting href for .less stylesheet through JS

I'm using cookies to find out if the user is in light or dark mode onload of body. I always use the light.less as the fallback/default if a cookie can't be found. So in my <head> I have
<link rel="stylesheet" type="text/css" href="../assets/main.css">
<link rel="stylesheet/less" type="text/css" id="colorMode" href="../assets/light.less">
<script src="../assets/less.js/dist/less.min.js" type="text/javascript"></script>
and my body tag is as follows:
<body onload="checkNav(); checkCookies();" onresize="checkNav()">
The checkCookies() is the function to review the cookie and act accordingly, it is shown below.
function checkCookies() {
var style = getCookie("style");
if (style == 'dark') {
document.getElementById("colorMode").href = "../assets/dark.less";
document.getElementById("switchIcon").innerHTML = "toggle_on";
document.cookie = "style=dark; path=/~sam.walker";
}
else {
//Already set by default
}
}
The getCookie() function simply returns the relevant style cookie
The colorMode stylesheet with href = ../assets/light.less does change as expected to ../assets/dark.less as I've checked with inspector but the style itself does not physically change. I've checked cache and its nothing to do with that. Any help would be greatly appriciated.
Including the stylesheet as a .less format won't work unless you have <script src="less.js" type="text/javascript"></script> added within the <head> section of your page.
Check out the usage information from Less.js here
less.min.js will find references to LESS files and generates CSS from them when it loads.
You are creating a new reference to a LESS file after that, by which time it is too late for less.js to notice.
You need to call checkCookies(); after you have linked to the LESS stylesheet but before you load the less.js script.
Thanks for your help,
Through your info I have found the following (botch) fix:
var elem = document.getElementById('NameOfOriginalLessGeneratedStyle'); //REQUIRES CHANGE ON SERVER CHANGE
elem.parentNode.removeChild(elem);
//Deleted previous styles
less.refresh();
//Loads new style
Should run after stylesheet href change.

CSS file is not being loaded dynamically via ng-href

I am trying to dynamically load different css styles into my page using ng-href, but the page is not being updated with the activated style. Code is as follows:
<html ng-app="myapp" ng-controller="myController as myctrl">
<head>
<link rel="stylesheet" ng-href="../assets/css/{{ myctrl.style }}.css">
</head>
</html>
In my controller, I do the following:
vm.style = "redStyle";
pub.subscribe('style', function(theStyle) {
vm.style = theStyle;
});
The variable in the subscribe is updated with the new style once a publish has taken place. But the respective css file is not being loaded such that the style is updated on the page. Any ideas what I am missing out on?
Here is a working demo
It's very much the same as what you have so it's something else in your code. Hard to tell unless you put up all your code.
Assuming the stylesheet actually does exist, and the style variable is getting updated then my guess is that the culprit is
pub.subscribe()
If this callback is being triggered by something outside of angular then angular wont see the updated variable. You can bring it back into angular space like so:
pub.subscribe('style', function (theStyle) {
$scope.$apply(function(){
vm.style= theStyle;
});
});
Try this:
<link rel="stylesheet" data-ng-if="myctrl.style" data-ng-href="../assets/css/{{ myctrl.style }}.css" />
I solved it differently.
In my html, I gave the link element an id:
<link id="theme" rel="stylesheet" ng-href="../assets/css/{{theme}}.css">
And in the controller I say:
var myTheme = document.getElementById("theme");
var path = "../assets/css/{{theme}}.css";
myTheme.href = path.replace("{theme}", theme.class);

How to change stylesheet with Jquery and Django

Hello I've been trying to solve this problem for quite a while. Back when I was using vanilla html this code seems to work. (Changing from tile view to list view). Now that I have incorporated it in django and the hrefs contains static tags, I dont know how to refer to it in jquery and change its href. Pls help
HTML
<link rel="stylesheet" type="text/css" href="{% static "Stylesheets/tileVersion.css" %}">
I want to change it to this css href
<link rel="stylesheet" href="../Stylesheets/listVersion.css">
JQUERY
$('#listicon').click(function () {
$('link[href="static/Stylesheets/tileVersion.css"]').attr('href', 'static/Stylesheets/listVersion.css');
});
$('#tilesicon').click(function () {
$('link[href="static/Stylesheets/listVersion.css"]').attr('href', 'static/Stylesheets/tileVersion.css');
});
I want to be able to switch between them if possible. Any kind of help would be appreciated
You can do one of two things.
You can use static references to load one CSS file over another, by using a if tag in your code getting the css link value (the address/url) from a variable or from a data source. This compiles during server time. This also means that only one css is loaded at runtime. This is static for the client. For example:
Same as #1, but you can use an inline if to determine which one goes forward to the client.
Lastly, ensure both css files are held within the static process, and maintain your jquery:
$('#listicon').click(function () {
$('link[href="{% static /path/to/first/css/page %}"]').attr('href', '{% static /path/to/first/css/page %}');
});
$('#tilesicon').click(function () {
$('link[href="{% static /path/to/second/css/page %}"]').attr('href', {% static /path/to/second/css/page %});
});
I typed this out of memory, so please bear with me.
Hope this helps.
Just put an additional attribute id for the link tag. You can remove the current stylesheet from head and add another one.
<link rel="stylesheet" id="myid" href="../Stylesheets/listVersion.css">
$('#myid').remove();
$('head').append( $( '<link/>', {'rel' : 'stylesheet', 'id': 'myid', 'href':'newlink' } ));

Group of CSS and JS files import at HTML?

I have a group of CSS imports as like:
<link rel="stylesheet" href="/css/reset.css"/>
<link rel="stylesheet" href="/css/visualize.css"/>
<link rel="stylesheet" href="/css/datatables.css"/>
and some JavaScript code imports as like:
<script src="/js/excanvas.js"></script>
<script src="/js/jquery.js"></script>
<script src="/js/jquery.livesearch.js"></script>
<script src="/js/jquery.visualize.js"></script>
Is it possible to put all CSS import lines into a file i.e. cssImports.css and put all JS import lines into a file i.e. jsImports.js. So when I want to import that CSS and JS group files I will write something like:
<link rel="stylesheet" href="/css/cssImports.css"/>
<script src="/js/jsImports.js"></script>
so all the files listed above will be imported?
PS: I don't want to write any code belongs to web server specific.
Javascript imports: no.
CSS import: yes, but you shouldn't because it breaks parallel downloading of stylesheets.
Your best bet is to use a local build script (such as the Ant script included with the HTML5 Boilerplate) to concatenate your stylesheets and scripts before uploading them to the server, then linking to the 'master' resources in your HTML:
<link rel="stylesheet" href="/css/master.css">
<script src="/js/master.js"></script>
There is a tutorial on using the Ant script.
Go with LazyLoad! https://github.com/rgrove/lazyload/
It's a very small js (less than 1kb) that takes care of resource loading for you.
Download the package and save on your js folder. Then you would probably want to do this:
<script src="js/lazyload-min.js"></script>
Then for javascript files:
<script>
LazyLoad.js(["/js/excanvas.js", "/js/jquery.js", "/js/jquery.livesearch.js", "/js/jquery.visualize.js"], function () {
alert('all js files have been loaded');
});
</script>
Css:
<script>
LazyLoad.css(["/css/reset.css", "/css/visualize.css", "/css/datatables.css"], function () {
alert('all css files have been loaded');
});
</script>
This will also boost the performance of your page, enabling parallel css and js loading (the latter on firefox opera only).
You can Import CSS like this:
Create a new CSS cssImports.css and add there lines
#import url('/css/reset.css');
#import url('/css/visualize.css');
#import url('/css/datatables.css');
and relate it in your homepage as:
<link rel="stylesheet" href="/css/cssImports.css"/>
For Javascript import doesn't work. But you can create a single JS file and include the javascript code of each file after one another. But this is not recommended. It is better to have separate <script> tag for each js file.
for css:
<style>
#import url('/css/styles.css');
</style>
for js you could try something like
document.write("<script type='text/javascript' src='otherScript.js'></script>");
but i dont see a reason to do either of theese...
Yes just copy all the code and place in into a new file in the order than you would like it to run.
I know there are some javascript libraries that can do this for you but I dont have an experience of using them. I think Yahoo compiler/ YUI has one.
I'm not recommend do that because performance issue, but if you want the way, you can do that:
For CSS yes its possible, in cssImports.css you can put:
#import url(/css/reset.css);
#import url(/css/visualize.css);
#import url(/css/datatables.css);
But for JS, I think no way as much as CSS, but you can do this (adding JS files) from one JS file (ex jsImports.js), by write code create script element and add this element to page, like that :
var jsE = document.createElement('script');
var url = 'JS LINK HERE';
jsE.setAttribute('type', 'text/javascript');
jsE.setAttribute('src', url);
document.getElementsByTagName('head').item(0).appendChild(jsE);
Do this for each link of JS that you want to put, I have and idea, using Arracy contains JS links like this:
var jsLinks = new Array(
"/js/excanvas.js",
"/js/jquery.js",
"/js/jquery.livesearch.js",
"/js/jquery.visualize.js"
);
then a loop read a link each time and put this, like :
for (i = 0; i < jsLinks.length; i++)
{
var jsE = document.createElement('script');
var url = jsLinks[i];
jsE.setAttribute('type', 'text/javascript');
jsE.setAttribute('src', url);
document.getElementsByTagName('head').item(0).appendChild(jsE);
}
I didn't test my code, But I hope my idea is explained well.
Best
Edit 1: yes you can use Gatekeeper solution for JS (Very Simple), but it use "write" but "for me" I don't like that way :)
This is now possible as follows with HTML Imports which are in W3C draft
<link rel="import" href="import.html">
import.html
<link rel="stylesheet" href="/css/reset.css"/>
<link rel="stylesheet" href="/css/visualize.css"/>
<link rel="stylesheet" href="/css/datatables.css"/>
<script src="/js/excanvas.js"></script>
<script src="/js/jquery.js"></script>
<script src="/js/jquery.livesearch.js"></script>
<script src="/js/jquery.visualize.js"></script>
At this time only Chrome, Android and Opera support HTML Imports natively, but WebComponents provides a very mature polyfill script called webcomponents-lite.js to support all modern browsers

Categories