How to call images from CSS when page are loaded using https - css

This one is driving me nuts. It's (yet) another IE6/7 idiosyncrasy, but one of my web pages needs to be loaded using https. In IE6/7 I get the dreaded "contains secure and nonsecure items" message which is causing users to panic. I've gone through the code top to bottom and isolated the problem (as IE sees it) to background images in my CSS. However, these use absolute paths...
background: url(/images/imagename.jpg);
Looks like this is tripping up IE and causing the nonsecure message on https. Anybody got any ideas how to get around this? Any help much appreciated.

That shouldn't be causing you any troubles, as long as the CSS file itself is also coming from HTTPS. Absolute paths without an explicit protocol (i.e. /path/to/file instead of http://example.com/path/to/file) inherit the protocol of the file calling them, be it HTML or CSS.
Can we see your page? It's possible there's something else on the page you're overlooking.

You are correct, relative url paths in background style will cause this message to appear in IE6/7.
The only method I have used successfully, is to either build the absolute path from available browser data, or to hard code the absolute path. Here is an example of how you can build the absolute path with JavaScript:
Using a top level style definition like this:
<style type="text/css">
.fixBgImage {
background: url(/images/imagename.jpg);
}
</style>
You can use a JavaScript function that looks up that rule, and changes the backgroundImage style for that rule. (Keep in mind that this example assumes you've defined the rule on sheet[0])
// this function needs to be run after the page has loaded
// (body.onload, window.onload or something similar)
function fixBackgroundImages() {
// using sheet 0 defined first on this page
var rule = getRule('.fixBgImage', document.styleSheets[0]);
if (rule != null) {
var bgUrl = rule.style.backgroundImage.replace(/^url|[\(\)]/g, '');
bgUrl = fixHttpsBgUrl(bgUrl);
rule.style.backgroundImage = 'url("' + bgUrl + '")';
}
}
function getRule(name, sheet){
var rules = (sheet.rules) ? sheet.rules : sheet.cssRules;
for (var i = 0; i < rules.length; i++) {
if (rules[i] && rules[i].selectorText == name) {
return rules[i];
}
}
return null;
}
// This function returns an absolute path if https is used
function fixHttpsBgUrl(imgUrl){
if (document.location.protocol.indexOf('https') >= 0){
var basepath = document.URL.substring(0, document.URL.lastIndexOf('/') + 1);
var pcol = document.location.protocol + '//';
var host = document.location.hostname;
var port = (document.location.port) ? ':' + document.location.port : '';
if (imgUrl.indexOf('/') == 0){ // server root path
imgUrl = pcol + host + port + imgUrl;
}
else{ // app root
imgUrl = basepath + imgUrl;
}
}
}

Try with:
background: url(//images/imagename.jpg);
According to this answer that should work. Try using it for the stylsheet as well, eg:
<link rel="stylesheet" type="text/css" src="//style/style.css" />

IE should have absolutely no problem with relative-pathed images so long as they're relative to a secure root. The problem you're hitting quite likely is caused elsewhere.
http://blogs.msdn.com/ieinternals/archive/2009/06/22/HTTPS-Mixed-Content-in-IE8.aspx

Related

Using Selenium to determine the visibility of elements for Print media

I would like to determine if particular elements on a page are visible when printed as controlled by CSS #media rules.
Is there a way to do this with Selenium?
I know there is the isDisplayed method, which takes the CSS into account, but there is nothing I can find to tell Selenium which media type to apply.
Is there a way to do this?
Or is there another way to test web pages to make sure the elements you want are printed (and those you don't aren't)?
Update:
For clarity, there are no plans to have a javascript print button. The users will print using the normal print functionality of the browser (Chrome, FF and IE). #media css rules will be used to control what is shown and hidden. I would like Selenium to pretend it is a printer instead of a screen, so I can test if certain elements will be visible in what would be the printed version of the page.
I've managed to write a script that does just what you want: it hides screen-only styles and sets print-only styles to be screen-only.
You need to inject the following JavaScript with Selenium:
(function pretendToBeAPrinter() {
//For looking up if something is in the media list
function hasMedia(list, media) {
if (!list) return false;
var i = list.length;
while (i--) {
if (list[i] === media) {
return true;
}
}
return false;
}
//Loop though all stylesheets
for (var styleSheetNo = 0; styleSheetNo < document.styleSheets.length; styleSheetNo++) {
//Current stylesheet
var styleSheet = document.styleSheets[styleSheetNo];
//Output debug information
console.info("Stylesheet #" + styleSheetNo + ":");
console.log(styleSheet);
//First, check if any media queries have been defined on the <style> / <link> tag
//Disable screen-only sheets
if (hasMedia(styleSheet.media, "screen") && !hasMedia(styleSheet.media, "print")) {
styleSheet.disabled = true;
}
//Display "print" stylesheets
if (!hasMedia(styleSheet.media, "screen") && hasMedia(styleSheet.media, "print")) {
//Add "screen" media to show on screen
styleSheet.media.appendMedium("screen");
}
// Get the CSS rules in a cross-browser compatible way
var rules;
try {
rules = styleSheet.cssRules;
} catch (error) {
console.log(error);
}
try {
rules = styleSheet.rules;
} catch (error) {
console.log(error);
}
// Handle cases where styleSheet.rules is null
if (!rules) {
continue;
}
//Second, loop through all the rules in a stylesheet
for (var ruleNo = 0; ruleNo < rules.length; ruleNo++) {
//Current rule
var rule = rules[ruleNo];
//Hide screen-only rules
if (hasMedia(rule.media, "screen") && !hasMedia(rule.media, "print")) {
//Rule.disabled doesn't work here, so we remove the "screen" rule and add the "print" rule so it isn't shown
console.info('Rule.media:');
console.log(rule.media)
rule.media.appendMedium(':not(screen)');
rule.media.deleteMedium('screen');
console.info('Rule.media after tampering:');
console.log(rule.media)
}
//Display "print" rules
if (!hasMedia(rule.media, "screen") && hasMedia(rule.media, "print")) {
//Add "screen" media to show on screen
rule.media.appendMedium("screen");
}
}
}
})()
You can see it in action at JSFiddle.
Bookmarklet
You can also install it as a bookmarklet.
More information:
About mediaList
About document.styleSheets
Note: I've only tested this in Google Chrome and Mozilla Firefox. It may or may not work in other browsers.
There is some cases that it can be useful to use visual automation tools such as applitools.
We implements it in some of our tests, and it's great so far.
//jquery
function printDetail() {
window.print();
}
//html
<button type="button" class="btn" value="Print Div" onclick="printDetail()"><i class="icon-print"></i> Print</button>
//css
#media print{
.header{display:none;}
.footer{display:none;}
.leftside{display:none;}
.rightside{display:block;}
}
// http://jsfiddle.net/kisspa/52H7g/
I think I have a little clever way to accomplish this:
Can I assume that the PRINT button is going to be on the html page as is the case in the jsfiddle.net link above?
Basically, can I EXCLUDE the FILE->PRINT or RIGHT CLICK->PRINT options and only assume that the only way someone can print your page is by clicking on a print button embedded in your html page as shown in the jsfiddle link above if not what are other test cases?
Finally, can I assume that your selenium tests will ONLY run in the Chrome browser and not firefox? This is important because the PRINT command behaves different in Chrome as it does in Firefox. My fix will only work w/ Chrome.

CSS3: set background image to rel attribute value

I'm looking to set the background-image (or even render an image via the pseudo elements :after or :before) to the value, which will be a URL, of a rel attribute, but only in certain cases (this is a cloud file listing). For example:
HTML:
<div class="icon ${fileExtension}" rel="${fileURL}"></div>
It would be great if I could do something like this:
CSS:
.icon.png,
.icon.jpg,
.icon.jpeg,
.icon.bmp,
.icon.gif { background-image: attr(rel,url); }
... but obviously that doesn't work as, if I'm not mistaken, the attr() CSS function only works inside pseudo element blocks.
I know there are ways of doing this using conditional JSP or even jQuery logic, but I'd like to figure out a neat way of doing it via CSS3, since I'm only concerned with modern browsers at the moment anyway.
Also, I don't want to explicitly set the background image to the URL or create an <img> element, because by default if the file is not a supported image, I'd rather display a predetermined set of icons.
Using
.icon:after{ content: ""attr(rel)""; }
displays the rel value as text.
A jQuery solution is to add the background-image (taken from the rel value) as inline CSS:
jQuery(function($) {
$('.icon').each(function() {
var $this = $(this);
$this.css('background-image', 'url(' + $this.attr('rel') + ')');
});
});
I've tried to do something using jQuery but i don't exactly understand what you want so i can't go on with my code. So far i've done only this.
EDITED I hope it's exactly what you need
$(function(){
var terms = new Array('png','jpg','jpeg','bmp','gif');
$('.icon').each(function(){
var t = $(this),
rel = t.attr('rel'),
cls = t.attr('class');
cls = cls.split(' ');
for (var i=0; i < terms.length; i++) {
if (terms[i] == cls[1]) {
t.css('background-image','url('+rel+')');
}
}
});
});
if you can give me a better example, to undestand exactly what you want, i hope somebody from here will be able to solve your problem.
Regards,
Stefan
I've decided to go the jQuery route, and used a combination of #ryanve and #stefanz answers. Thanks guys
$(document).ready(function() {
$(".png,.jpg,.jpeg,.bmp,.gif,.tiff").each(function(n) {
var bg = 'url(' + $(this).attr("rel") + ')';
$(this).css('background-image', bg);
});
});
I think this is relatively neat/concise and works well for my needs. Feel free to comment on efficiency, methodology, etc.

How to change the FireBug representation of a css class with a FireBug extension?

When messing around in the FireBug css panel, you change the their representation of the original css file. Like:
.myCssClass { width: 100px; }
However, if you add a jQuery line to this,
$(".myCssClass").css("width", "200px");
you end (of course) up with changing the style tag for this element and you see that your original width:100px has a strikethough in the FireBug representation.
So my question is, do you know a way to change the "original" width:100px instead of changing the style tag. I guess you have to through a FireBug extension to access that property, and that is not a problem for me. But I don't know where to start :)
Edit: Have to point out that I am need to change the property by code! Either from a FireBug extension or somehow reload the corresponding css so that FireBug think it is the orginal value.
Here is an old JS function that usually worked well for me (Before Stylish and Greasemonkey).
Note that plain JS has security restrictions from accessing some stylesheets. A FF add-on can get around that, but then you need to also beware of corrupting browser-chrome styles.
function replaceStyleRuleByName (sStyleName, sNewRule)
{
var iNumStyleSheets = document.styleSheets.length;
var bDebug = 0;
if (bDebug) console.log ('There are ' + iNumStyleSheets + ' style sheets.');
for (iStyleS_Idx=0; iStyleS_Idx < iNumStyleSheets; iStyleS_Idx++)
{
var iNumRules = 0;
var zStyleSheet = document.styleSheets[iStyleS_Idx];
if (zStyleSheet)
{
/*---WARNING!
This next line can throw an uncaught exception!
Error: uncaught exception:
[Exception... "Access to restricted URI denied" code: "1012"
nsresult: "0x805303f4 (NS_ERROR_DOM_BAD_URI)"
location: ... ...]
*/
//--- try/catch for cross domain access issue.
try
{
var zRules = zStyleSheet.cssRules;
if (zRules)
{
iNumRules = zRules.length;
}
}
catch (e)
{// Just swallow the error for now.
}
}
if (bDebug) console.log ("Style sheet " + iStyleS_Idx + " has " + iNumRules + " ACCESSIBLE rules and src: " + zStyleSheet.href);
//for (var iRuleIdx=iNumRules-1; iRuleIdx >= 0; --iRuleIdx)
for (var iRuleIdx=0; iRuleIdx < iNumRules; ++iRuleIdx)
{
if (zRules[iRuleIdx].selectorText == sStyleName)
{
zStyleSheet.deleteRule (iRuleIdx);
if (bDebug) console.log (sNewRule);
if (sNewRule != null)
{
zStyleSheet.insertRule (sStyleName + sNewRule, iRuleIdx);
}
//return; //-- Sometimes changing just the first rule is not enough.
}
}
//--- Optional: Punt and add the rule, cold, to any accessible style sheet.
if (iNumRules > 0)
{
if (sNewRule != null)
{
try
{
zStyleSheet.insertRule (sStyleName + sNewRule, iRuleIdx);
}
catch(e)
{// Just swallow the error for now.
}
}
}
}
return;
}
Sample Usage:
replaceStyleRuleByName ('body', '{line-height: 1.5;}' );
replaceStyleRuleByName ('#adBox', '{display: none;}' );
replaceStyleRuleByName ('.BadStyle', null );
Just right click on the property in question and then edit [stylename]
Look for the "Computed" tab, it displays the actual values used of the properties of an element. The "Style" tab only displays the "stylesheet values" that affects a particular element, which may or may not be actually used by Firefox due to CSS' cascading rule and other layouting considerations.

when using SimpleModal and open an Iframe it is calling the src twice

I am using SimpleModal and i am opening an Iframe (using ff)
it seems to work ok in ie9 but in ff it is calling the iframe src twice
Thanks for any help
the code i am calling looks like
function addNew(){
var src = "/php/ftp/parsehome.php?dir="+userDir+"&idx=new";
$.modal('<iframe src="' + src + '" height="445" width="800" style="border:0">', {
containerCss:{
backgroundColor:"#E1EFF7",
borderColor:"#00A99D",
height:450,
padding:0,
width:840
},
modal: true
});
}
I ran into the same problem. Looking at the plugin code...
// add styling and attributes to the data
// append to body to get correct dimensions, then move to wrap
s.d.data = data
.attr('id', data.attr('id') || s.o.dataId)
.addClass('simplemodal-data')
.css($.extend(s.o.dataCss, {
display: 'none'
}))
.appendTo('body');
data = null;
You can see the data is added to the page body with the line .appendTo('body'); to calculate the correct dimensions for the modal. If you comment out this line, it will prevent the iframe being called twice.
// add styling and attributes to the data
// append to body to get correct dimensions, then move to wrap
s.d.data = data
.attr('id', data.attr('id') || s.o.dataId)
.addClass('simplemodal-data')
.css($.extend(s.o.dataCss, {
display: 'none'
}));
data = null;
Not sure if this modification will cause your modal size to have the wrong dimensions, but my iframe was set to width=100% and height=100% so didn't affect me.

Find style references that don't exist

Is there a tool that will find for me all the css classes that I am referencing in my HTML that don't actually exist?
ie. if I have <ul class="topnav" /> in my HTML and the topnav class doesn't exist in any of the referenced CSS files.
This is similar to SO#33242, which asks how to find unused CSS styles. This isn't a duplicate, as that question asks which CSS classes are not used. This is the opposite problem.
You can put this JavaScript in the page that can perform this task for you:
function forItems(a, f) {
for (var i = 0; i < a.length; i++) f(a.item(i))
}
function classExists(className) {
var pattern = new RegExp('\\.' + className + '\\b'), found = false
try {
forItems(document.styleSheets, function(ss) {
// decompose only screen stylesheets
if (!ss.media.length || /\b(all|screen)\b/.test(ss.media.mediaText))
forItems(ss.cssRules, function(r) {
// ignore rules other than style rules
if (r.type == CSSRule.STYLE_RULE && r.selectorText.match(pattern)) {
found = true
throw "found"
}
})
})
} catch(e) {}
return found
}
Error Console in Firefox. Although, it gives all CSS errors, so you have to read through it.
IntelliJ Idea tool does that as well.
This Firefox extension is does exactly what you want.
It locates all unused selectors.

Resources