Use JavaScript in CSS [duplicate] - javascript

Is it possible to use Javascript inside CSS?
If it is, can you give a simple example?

IE and Firefox both contain ways to execute JavaScript from CSS. As Paolo mentions, one way in IE is the expression technique, but there's also the more obscure HTC behavior, in which a seperate XML that contains your script is loaded via CSS. A similar technique for Firefox exists, using XBL. These techniques don't exectue JavaScript from CSS directly, but the effect is the same.
HTC with IE
Use a CSS rule like so:
body {
behavior:url(script.htc);
}
and within that script.htc file have something like:
<PUBLIC:COMPONENT TAGNAME="xss">
<PUBLIC:ATTACH EVENT="ondocumentready" ONEVENT="main()" LITERALCONTENT="false"/>
</PUBLIC:COMPONENT>
<SCRIPT>
function main()
{
alert("HTC script executed.");
}
</SCRIPT>
The HTC file executes the main() function on the event ondocumentready (referring to the HTC document's readiness.)
XBL with Firefox
Firefox supports a similar XML-script-executing hack, using XBL.
Use a CSS rule like so:
body {
-moz-binding: url(script.xml#mycode);
}
and within your script.xml:
<?xml version="1.0"?>
<bindings xmlns="http://www.mozilla.org/xbl" xmlns:html="http://www.w3.org/1999/xhtml">
<binding id="mycode">
<implementation>
<constructor>
alert("XBL script executed.");
</constructor>
</implementation>
</binding>
</bindings>
All of the code within the constructor tag will be executed (a good idea to wrap code in a CDATA section.)
In both techniques, the code doesn't execute unless the CSS selector matches an element within the document. By using something like body, it will execute immediately on page load.

I think what you may be thinking of is expressions or "dynamic properties", which are only supported by IE and let you set a property to the result of a javascript expression. Example:
width:expression(document.body.clientWidth > 800? "800px": "auto" );
This code makes IE emulate the max-width property it doesn't support.
All things considered, however, avoid using these. They are a bad, bad thing.

To facilitate potentially solving your problem given the information you've provided, I'm going to assume you're seeking dynamic CSS. If this is the case, you can use a server-side scripting language to do so. For example (and I absolutely love doing things like this):
styles.css.php:
body
{
margin: 0px;
font-family: Verdana;
background-color: #cccccc;
background-image: url('<?php
echo 'images/flag_bg/' . $user_country . '.png';
?>');
}
This would set the background image to whatever was stored in the $user_country variable. This is only one example of dynamic CSS; there are virtually limitless possibilities when combining CSS and server-side code. Another case would be doing something like allowing the user to create a custom theme, storing it in a database, and then using PHP to set various properties, like so:
user_theme.css.php:
body
{
background-color: <?php echo $user_theme['BG_COLOR']; ?>;
color: <?php echo $user_theme['COLOR']; ?>;
font-family: <?php echo $user_theme['FONT']; ?>;
}
#panel
{
font-size: <?php echo $user_theme['FONT_SIZE']; ?>;
background-image: <?php echo $user_theme['PANEL_BG']; ?>;
}
Once again, though, this is merely an off-the-top-of-the-head example; harnessing the power of dynamic CSS via server-side scripting can lead to some pretty incredible stuff.

Not in any conventional sense of the phrase "inside CSS."

IE supports CSS expressions:
width:expression(document.body.clientWidth > 955 ? "955px": "100%" );
but they are not standard and are not portable across browsers. Avoid them if possible. They are deprecated since IE8.

I ran into a similar problem and have developed two standalone tools to accomplish this:
CjsSS.js is a Vanilla Javascript tool (so no external dependencies) that supports back to IE6.
ngCss is an Angular Module+Filter+Factory (aka: plugin) that supports Angular 1.2+ (so back to IE8)
Both of these tool sets allow you to do this in a STYLE tag or within an external *.css file:
/*<script src='some.js'></script>
<script>
var mainColor = "#cccccc";
</script>*/
BODY {
color: /*{{mainColor}}*/;
}
And this in your on-page style attributes:
<div style="color: {{mainColor}}" cjsss="#sourceCSS">blah</div>
or
<div style="color: {{mainColor}}" ng-css="sourceCSS">blah</div>
NOTE: In ngCss, you could also do $scope.mainColor in place of var mainColor
By default, the Javascript is executed in a sandboxed IFRAME, but since you author your own CSS and host it on your own server (just like your *.js files) then XSS isn't an issue. But the sandbox provides that much more security and peace of mind.
CjsSS.js and ngCss fall somewhere in-between the other tools around to accomplish similar tasks:
LESS, SASS and Stylus are all Preprocessors only and require you to learn a new language and mangle your CSS. Basically they extended CSS with new language features. All are also limited to plugins developed for each platform while CjsSS.js and ngCss both allow you to include any Javascript library via <script src='blah.js'></script> straight in your CSS!
AbsurdJS saw the same problems and went the exact opposite direction of the Preprocessors above; rather than extending CSS, AbsurdJS created a Javascript library to generate CSS.
CjsSS.js and ngCss took the middle ground; you already know CSS, you already know Javascript, so just let them work together in a simple, intuitive way.

This turns out to be a very interesting question. With over a hundred properties being set, you'd think that you'd be allowed to type
.clickable { onclick : "alert('hi!');" ; }
in your CSS, and it'd work. It's intuitive, it makes so much sense. This would be amazingly useful in monkey-patching dynamically-generated massive UIs.
The problem:
The CSS police, in their infinite wisdom, have drawn a Chinese wall between presentation and behavior. Any HTML properly labeled on-whatever is intentionally not supported by CSS. (Full Properties Table)
The best way around this is to use jQuery, which sets up an interpreted engine in the background to execute what you were trying to do with the CSS anyway. See this page:
Add Javascript Onclick To .css File.
Good luck.

Related

Onclick in HTML with custom language

I've made my own minimal language similar to Javascript, and have it functioning in an html file. I have my my-lang code (I'll call the language "my-lang") in between script tags, with the script type property set to "my-lang". Another JS file reads all the code in my-lang, then runs it. Say I had an anchor tag like this:
<a onclick="someJSfunction();">Text text text</a>
In the onclick property it runs some JS code. I want it to run code in my-lang. I had a few ideas, but none of them are ideal. Here are a few:
In my JS parser which is at the bottom of the HTML file, I have a function that just runs code in my-lang, like a my-lang eval() written in JavaScript. Then in HTML, you can do <a onclick='run_my_lang("code in my-lang as a string")'>Text text text</a>
I saw a bunch of devs prefacing the onclick text with a label "javascript:". I thought that was for something else, but I'm not sure. I dont know if this will work, but maybe something like onclick="my-lang:code"
Any ideas on how to do this without the prefixes?
In my-lang I have event handlers working, I just would also like to be able to do it in line.
As I wrote in the comment, the solution would be the 1st (onclick='run_my_lang("code")') if you already can do it than it's totally cool, really.
If you are able to process on-click then your lang should be run on
client (so in a browser), and the only lang available in browser is
JS.
(You can't enforce Chrome or Safari to process construction "my-lang:code").
If you can solve it via 2nd option, then it means you should have a some compiler that would translate your template with "my-lang: code" into "javascript: code" or "run_my_lang('code')", so you still will need to implement 1st.
Oh, ok you have no need to use "my-lang" in Chrome|FF|Safari|Whatever, you have your own "WhateverBrowser" that can process "my-lang: code" (alongside with HTML, CSS and bunch of other things (and not to forget same Javascript)) in the received from the server HTML, and maybe your "WhateverBrowser" even written in "my-lang", that would be cool (but I doubt you have "WhateverBrowser" or ready to compete with Chrome|FF|Safari|Whatever)
Or (maybe) you would have some specific "browser" that browse specific pages, can process mouse events and pass it to your lang.
And now to the main point, what is "my-lang"?
Unless it's 3rd (specific browser) your lang in one or another way is written in JS, so in the end it's JS lib:
window.myLang = function(code) {
let [,func,arg] = code.match(/^myLang:([a-zA-Z]+)\((.*)?\)$/);
if (myLangFunctions[func])
myLangFunctions[func](arg);
return this;
};
let myLangFunctions = {
sound: (arg) => {
switch(arg) {
case 'dog': alert('bark-bark');break;
case 'cat': alert('meow-meow');break;
case 'frog': alert('kero-kero');break;
default: alert('u-u-u-u-u');
}
}
}
div {
width: 70px;
height: 70px;
border: double 3px;
float: left;
margin: 5px;
line-height: 70px;
text-align: center;
}
<div onclick="myLang('myLang:sound(dog)')">dog</div>
<div onclick="myLang('myLang:sound(cat)')">cat</div>
<div onclick="myLang('myLang:sound(frog)')">frog</div>
<div onclick="myLang('myLang:sound(whatever)')">whatever</div>
And to solve it via 2nd option you will just need pre-compiler that will translate your template into some JS or HTML code (like JSX), so it would be just an extension of your 1st solution.
PS: I really think that your question purely theoretical, or even (maybe) one of your probable questions on some exams, but still wrote it for fun )) and hope it helps to you in your future path :)

How do I tag my CSS file with a version number that jQuery can read?

I'm making a Javascript library that comes with a CSS file. I would like for the JS to check the CSS file version.
My best idea is CSS like this
body { someproperty: "v1.3.1"; }
and then you can have JS code like this
console.log($("body").css("someproperty"))
But I'm having a hard time finding the perfect property. Is there some semi obsolete one that takes an arbitrary string or number?
Any other ideas?
#Niet the Dark Absolless gave the perfect answer to my question, but I ended up handling my CSS purely in JS:
$('head').append(my_css)
This gives me one single file to distribute, which can never get out of sync with itself. Good Times!
Actually, there is. Sort of.
body {content:"Hello, world!";}
Because it's not a psuedo-elment, it has no effect.
But if you then do:
console.log($("body").css("content"));
... Close enough! -- Just need to strip the quotes from the start and end ;)
console.log($("body").css("content").slice(1,-1));
Create a javascript file which defines the version and then load the stylesheet via javascript. Include the javascript file instead of the CSS file:
function getVersion()
{
return '1.0';
}
$(document).ready(function()
{
$('head').append('<link rel="stylesheet" href="test.css" type="text/css"/>');
});

jQuery $().css("content") returning the string "normal" in IE9

I'm using the CSS content attribute to pass some values from my LESS stylesheet to JavaScript (to use some colors defined in LESS in Canvas elements).
To make my life easier I decided to place these values in a easy way to parse them in JavaScript.
LESS code:
div#colorChart-critical {
content:'#{critical-highest},#{critical-veryhigh},#{critical-high},#{critical-low},#{critical-medium},#{critical-verylow}';
}
which when compiled brings the following CSS:
div#colorChart-critical6 {
content: '#ff0000,#ff7200,#fffc00,#0000ff,#a200ff,#00ff00';
}
Then I try to read them using jQuery:
$("div#colorChart-critical").css("content").split(",");
The problem is that in IE9 calling $("div#colorChart-critical").css("content") is returning the string "normal" for some reason. Opera, Firefox, Safari and Chrome works fine.
Why does this happen in IE9?
Any work-around this issue on IE9? If not any other CSS atribute I can put random texts in?
I could use something like:
background: url(#ff0000,#ff7200,#fffc00,#0000ff,#a200ff,#00ff00);
But this would generate errors on the console.
It's because content as defined in CSS2.1 doesn't work on elements, only on the :before and :after pseudo-elements. IE9 is simply following the CSS2.1 spec here, which mandates that content on elements be computed to normal, always.
I don't know why other browsers would return the value you have defined, especially considering that .css() makes use of getComputedStyle() on those browsers. If they're implementing CSS2.1 content, then they're violating CSS2.1 by not computing the value to normal. If they're preparing for a late CSS3 implementation, whatever that may be, then it would make sense that they implement it on actual elements somehow... shame on them either way.
Which brings me to another point: if you're not actually trying to use CSS to modify the content of an element, don't use content, even if the fact that it's not defined for use with elements is the reason you're making use of this technique in the first place. You can try assigning those colors to certain classes, creating a hidden element and querying that element's color styles instead.
BoltClock answer shows the cause of my problems. I found a work-around by using the font-family instead of the content CSS property.
My LESS code:
div#colorChart-maincolors {
font-family: '#{colorChart1},#{colorChart2},#{colorChart3},#{colorChart4},#{colorChart5},#{colorChart6}';
}
Which compiled into CSS gives:
div#colorChart-maincolors {
font-family: '#c0392b,#2980b9,#2ecc71,#f1c40f,#ecf0f1,#34495e';
}
The string can be acquired using:
removeQuotes= function(string) {
return string.replace(/^['"]+|\s+|\\|(;\s?})+|['"]$/g, '');
};
removeQuotes($("#colorChart-maincolors").css("font-family")); //add a .split(',') to get the colors as an array
The function removeQuotes is necessary because each browser adds a different kind of quotes into the return of getComputedStyle (and by extension the jQuery .css() method). IE9 adds a double quote, Webkit adds a single quote.
See this post on CSS tricks: http://css-tricks.com/making-sass-talk-to-javascript-with-json/ for more information.
you can use replace(/["']/g, "") to remove extra quotation from string
""string"" will be change to "string"

How to get a css stylesheet value that is not interpreted by the browser?

I would like to get a value of the css stylesheet that is not actually used by the browser during rendering.
For instance:
.blur {
data : "Great";
}
Let us say I use this class on a div as such:
<div class = "blur"></div>
What I tried and does NOT work.
$(".blur").css("data");
Expected Output
Great
EDIT: Sorry, I didn't mention this before, seems to be causing some confusion now. But please read this!
As I stated in the comment below and would like to emphasize, I have made the algorithm for generating a some text shadow on Internet Explorer---not the best algorithm, but still does the trick. However, I am trying to access the text-shadow attribute of a certain element but I can't since Internet Explorer doesn't store it since it doesn't really render it in the first place so I need to access the stylesheet data. So the question which I asked is again accessing "data" which too isn't stored just like textShadow for IE8, IE9.
You could store the data in an HTML5 data attribute.
<div class="blur" data-foo="great"></div>
and then retrieve it with jQuery
$('.blur').data('foo');
You can have raw access to style sheet tags, that's the best you can do, you can then parse the text for the information you're looking for with something like http://jsfiddle.net/V7Zmn/1/
// You'd have to find the right style tag
document.getElementsByTagName("style")[0].innerText
// outputs a string like: .blur { color: red; data : "Great";}
This looks like a big hack, but I can't yet think of a way to do what you need in a more elegant way., a better approach would be to use something like IE's filters instead Text Shadow in Internet Explorer? I think your approach of trying to fix this problem on your own is going to take way more effort than it's worth and you'll be going against the flow, creating friction with other code.
.myclass {
text-shadow: 2px 2px gray;
filter: progid:DXImageTransform.Microsoft.dropshadow(OffX=2, OffY=2, Color='gray')
}
Example
I'm not sure whether the browser is obligated to preserve attributes it does not understand. You could try using this code, which shows how to access a stylesheet rule programmatically. As noted by others, however, this is probably not the best use of CSS even if it happens to work.

How to apply conditional css for IE7 for drupal 7?

I have one file css_browser_selector.js file in sites/all/js and the code of that file is as given below:
function css_browser_selector(u){var ua=u.toLowerCase(),is=function(t){return ua.indexOf(t)>-1},g='gecko',w='webkit',s='safari',o='opera',m='mobile',h=document.documentElement,b=[(!(/opera|webtv/i.test(ua))&&/msie\s(\d)/.test(ua))?('ie ie'+RegExp.$1):is('firefox/2')?g+' ff2':is('firefox/3.5')?g+' ff3 ff3_5':is('firefox/3.6')?g+' ff3 ff3_6':is('firefox/3')?g+' ff3':is('gecko/')?g:is('opera')?o+(/version/(\d+)/.test(ua)?' '+o+RegExp.$1:(/opera(\s|/)(\d+)/.test(ua)?' '+o+RegExp.$2:'')):is('konqueror')?'konqueror':is('blackberry')?m+' blackberry':is('android')?m+' android':is('chrome')?w+' chrome':is('iron')?w+' iron':is('applewebkit/')?w+' '+s+(/version/(\d+)/.test(ua)?' '+s+RegExp.$1:''):is('mozilla/')?g:'',is('j2me')?m+' j2me':is('iphone')?m+' iphone':is('ipod')?m+' ipod':is('ipad')?m+' ipad':is('mac')?'mac':is('darwin')?'mac':is('webtv')?'webtv':is('win')?'win'+(is('windows nt 6.0')?' vista':''):is('freebsd')?'freebsd':(is('x11')||is('linux'))?'linux':'','js']; c = b.join(' '); h.className += ' '+c; return c;}; css_browser_selector(navigator.userAgent);
I have applied different css on different browsers using class of that browser from the code written above.The code is working for every browser but its not working on IE6,IE7.There are two default files of ie6 and ie7 in drupal 6 but these files are also not working.I dont know how to make changes in IE browser.Your help willbe appreciated.
Thankz in advance.
I guess that you have lots of css duplication in that. I bet that only IE dosn't work and css is for rest is common (if you want anyone to read you code, don't paste its inline/minified version).
Check out this, that's how most people do it.
http://www.webdevout.net/css-hacks#conditional_comments
If you want really different CSS on each browser paste you JS's code redable verion or use this http://www.webdevout.net/css-hacks#conditional_comments-css_hack in combination with your solution to do it in ugly way.
Use this module http://drupal.org/project/conditional_styles
It's pretty straight forward how to do it just enable to module, add this line to your theme .info file
stylesheets-conditional[IE 7][all][] = ie7.css
then add the file ie7.css to your theme.

Categories