Style Attribute Manipulation wiht native Javascript on FF - javascript

I tried to find a related question but could not find anything that sounded alike.
Im building a small javascript Slider plugin for multiple projects at our company.
Therefore i need to do basic style manipulation on some Elements in the DOM.
I tested this on current Chrome +ChromeOnAndroid, Safari +SafariIOS, Opera +OperaMobile.
When i try to do this on Firefox it seems like the Style attributes dont get touched at all:
Heres the code ( or the fiddle) :
// the html
<div id="testwrapper">
</div>
// the javascript
(function(){
var extend = function(source, additions) {
for (var addition in additions) {
source[addition] = additions[addition];
}
};
var testEl = document.getElementById('testwrapper');
var testStyles = {
width: '150px',
height: '150px',
padding: '5px',
margin: '5px'
};
window.setTimeout(function(){
extend(testEl.style, testStyles);
}, 15000)
}());
It's pretty obvious what im trying to accomplish.
Im taking the style attributes the element has and try to extend them by the ones i give in testStyles.
This seemed very straight forward to me and much easier then writing down all attributes i want to change this way :
testEl.style.width = 'Xpx';
testEl.style.height = 'Ypx';
// and so on
This way it would work in ff but..
that would blow up my code because i will have different conditions were some attributes may change and some may not.
So here comes the Question:
Is there a way to get the same result as in Chrome etc. in Firefox or am I doing something wrong.
Is this way of manipulating the style attribute supported in FF at all?
Thanks for your help.
PS: I dont need anyone telling me to use jQuery instead. Keep that in mind please.

Because objects are passed around by reference, you don't need return source; and you don't need testEl.style = either. Try removing these two things and see if that fixes the problem in Firefox - it probably doesn't like you doing a complete re-assign of the style object ;)

Related

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 do I add CSS rules to a document fragment across IE/FF?

I am trying to create and then style a document fragment, but am having quite a bit of difficulty. Ironically, IE is not my problem!
I have this:
var newDom = document.createDocumentFragment();
newDom.appendChild(document.createElement("style"));
newDom.appendChild(document.createElement("div"));
if (newDom.childNodes[0].styleSheet){
newDom.childNodes[0].styleSheet.cssText = "div{color:red;}";
alert(newDom.childNodes[1].currentStyle.color);
}else{
newDom.childNodes[0].appendChild(document.createTextNode("div{color:red;}"));
alert(window.getComputedStyle(newDom.childNodes[1], null).color);
};
...which alerts "red" in IE7/8/9, but "rgb(0,0,0)" in FF3.0/4/10. And, yes, I will need to know what styles are applied, so I will need to read from getComputedStyle in FF (or use some other method, so long as it's reliable).
What am I doing wrong? Is this possible? (I would think/hope so...)
I've tried lots of things - like "newDom.styleSheets", which exists in IE but not FF - to no avail.
Please help - Thanks! :D
Reading on the web, it seems that the right syntax to change the CSS using Javascript is:
obj.style.cssText = 'something';
Anyway, this doesn't seem to solve the problem. I would suggest you to read this article, that might help you: http://www.phpied.com/the-new-game-show-will-it-reflow/.
I would also suggest to change the approach and put your CSS code in a pre-existing CSS stylesheet, associated with a class like .red-color, and then just the class to the newly created div, with setAttribute('class', 'red-color'). Another alternative would be to set the style inline, always with the same function: setAttribute('style', 'color: red').

better html watermark mechanism for input and textareas

I'm using jquery.watermark for adding watermarks for html form inputs. I love it, really easy to use as a developer and makes the site easier to use for visitors. Problem is, for some browsers, people are submitting forms with fields that are supposed to be left empty... but they get submitted with the watermark text! That is an absolute dealbreaker problem and I'm going to have to stop using this watermark unfortunately because of it.
Are there any other mechanisms which do not exhibit this behavior, at least not in any modern browser (including IE6+)? I prefer jQuery, but any mechanism will do. I assume javascript is necessary..
UPDATE: I think I'm going to go with jq-watermark, unless there are better mechanisms someone knows about or there's something wrong with this? It looks great:
supports individualized css
supports html5's placeholder attribute as a fallback mechanism, which I was unaware of
uses a mechanism which doesn't allow for submitting watermarks to the server
has an elegant feel which fades the watermark with focus and only removes when entering text
UPDATE 2: Unfortunately, looks like the jq-watermark plugin doesn't actually work well at all... at least not for me and I have a pretty standard setup. Maybe there's a conflict with other javascript, but I doubt it. I really like their feature set, particularly the html5 fallback. In fact, I like the html5 fallback so much that I'm tempted to just forget about a javascript mechanism for this and only have this for html5 browsers. But not even firefox has this html5 feature yet, only safari and chrome as far as I can see :(. That's only 10% or so of my visitors...
UPDATE 3: I've finally been able to get jq-watermark to work well. I've had to add some CSS rules to its classes and adopt some html conventions (like using a div container instead of setting the width on an input element). The reason the html5 fallback mechanism wasn't working and I was experiencing weird behavior was that you can't rely on the automatic application of jq-watermark to all elements with the class jq_watermark, in fact it's harmful to have any elements with that class if you want to use the placeholder attribute. Instead you have to call $(selectors).watermark('placeholder text', {fallback:true});. Kind of sucks because you have to duplicate the placeholder text in that call and on the placeholder attribute. But, of course, you can use jQuery's .each() to read that attribute. Also, on firefox, the fading upon focus looks somewhat bad... but Firefox 4 will have placeholder html5 support, so I'm not too worried. The font changes a little as well frequently when focusing on an input element.
A bit disappointing having wasted a good few hours testing all the solutions out there and having a pretty poor choice for such a simple mechanism. jq-watermark, after tweaking it and your html, is probably the best solution there is.
I built a really simple jQuery plugin for this sort thing, it isn't that difficult. This uses the title attribute for the placeholder text but that is pretty easy to change.
(function($) {
$.fn.egText = function(options) {
options = $.extend({ }, $.fn.egText.defaults, options || { });
var $all = this;
$all.focus(function() {
var $this = $(this);
if(!$this.data(options.dataKey))
$this.data(options.dataKey, 'yes').removeClass(options.egClass).val('');
})
.blur(function() {
var $this = $(this);
if($this.val() == '')
$this.addClass(options.egClass).removeData(options.dataKey).val($this.attr('title'));
else
$this.data(options.dataKey, 'yes');
})
.blur();
$.unique($all.closest('form')).submit(function() {
$all.each(function() {
var $this = $(this);
if(!$this.data(options.dataKey))
$this.val('');
});
return true;
});
};
$.fn.egText.defaults = {
dataKey: 'egText', // The key we use for storing our state with .data(), just in case there are conflicts...
egClass: 'lolite' // The CSS class to add to the <input> when we're displaying the example text.
};
})(jQuery);
You're welcome to use this if it does what you need. I don't know if it works in IE6 but it does work in the latest Firefox, Safari, Opera, Chrome, IE7, and IE8.
This jQuery Watermark plugin does not alter the value of the input fields. So you should be safe using it.

JS : Compatibility problem with Safari

I have a small portion of code which works well on FF but I can't seem to get it to work on Safari unless I put an alert instruction anywhere inside of the whiles.
Anyone knows what may be the problem ?
var liste_ele = document.getElementsByClassName('accordion_content');
i=0;
while(i<liste_ele.length)
{
var j=0;
var liste_sel = liste_ele[i].getElementsByTagName('select');
while(j<liste_sel.length)
{
liste_sel[j].style.visibility = '';
j++;
}
i++;
}
Why don't you try setting visibility to visible instead of ''.
liste_sel[j].style.visibility = 'visible';
And are they really hidden by setting visibility to hidden or are the hidden by display:none that might also make a difference.
If putting an alert in your while loop solves the problem, it's almost certainly a timing issue. Where in the DOM is this code being run? Are you sure it's being run AFTER the elements you're trying to find are created?
A simple test would be to put your code inside a timeout:
window.setTimeout(function(){
// your code here
},100);
If that works, then your issue is related to order of operations; make sure your DOM is created before attempting to access it.
#jitter : I already tried to set visibility to visible, but I didn't have a result so I just tried '', hoping it would help. And yes, my elements are hidden and not undisplayed, otherwise my script wouldn't run perfect on FF.
#jvenema : This looks like a good solution indeed :)
Even though I don't know why would my elements not be created since they are initialised as visibility:hidden by another script in my firmware before I pass on them with this script :/
Anyway thanks, you just solved my problem (well I had solved it the good way, by modifying the script that sets it to hidden but I was curious :p) ! :)
If you don't need to block off the position then use the style display:none. Otherwise hide it initially as Safari will render the page initially with the style visibility:hidden you just won't be able to toggle it with Javascript. As a workaround just toggle the opacity with the javascript;
document.getElementById('Div').style.opacity = 0; to make it disappear
and
document.getElementById('Div').style.opacity = 100; to make it reappear.
Its holding up for me until Safari gets it together.

Get css value without DOM element

I am wondering if there is a way to get css value from stylesheet file when there is no element in the DOM using it? I am using jQuery and I use selector $(".classname").css() to get the values. But with the case "classname" is not in any element, what to do to get the value" Thanks
Just create an element with that class name and inspect it. You don't even need to attach it to the DOM:
var $el = $('<div class="classname"></div>');
var opacity = $el.css('opacity') // or whatever
Even though $el is not actually present in the DOM, you still get access to all of its style properties.
Edit: as mentioned in the comments, this approach does not always work as expected (eg inherited css values not defined on .classname explicitly, selector specificity above .classname, etc).
For example the following fails due to #foo increasing the selector specificity beyond that of a standalone .bar:
css:
#foo .bar { color: red; }
js:
var $el = $('<div class="bar"></div>');
$el.css('color'); // Expected: "red", Actual: ""
See http://www.hunlock.com/blogs/Totally_Pwn_CSS_with_Javascript which presents a cross-browser approach to getting and adding css dynamically.
It works with document.styleSheets and both IE's .rules and everyone else's .cssRules
It also has the advantage of being somewhat abstracted so you don't need to worry about the details.
The above link no longer works. The following is a screenshot of the blog-article, captured by the internet archive wayback in 2008.
The function basically iterates over all styles of all stylesheets and provides the ability to modify / delete them.
Please note that this cannot be recommended, since most modern stylesheets are too large to make this an efficient operation.
You could go (this also works in chrome):
var $elem = $('<div id="foo"></div>').appendTo('body'),
value = $elem.css('margin-top');
$('#foo').remove();
You have to parse the styles from document.styleSheets.
To workaround the Chromium problem, you need to add it to the body:
Sample CSS:
.dummy {
min-width: 50px;
max-width: 250px;
}
Sample Javascript:
$(document).ready(function() {
var dummy = $('<div class="dummy" style="display: none;"></div>').appendTo('body');
console.log(dummy.css("min-width"));
console.log(dummy.css("max-width"));
dummy.remove();
});
This works on all modern browsers, Chrome, FF, IE11.

Categories