Trying to read styleSheets returns undefined - javascript

I've searched for an answer and no solution seems to fix this problem, so hopefully stating it specifically will help me find a solution.
I'm trying to read cssText of the first stylesheet using document.styleSheets[0].cssText, but it always returns undefined. I do have a stylesheet and it's visibly noticeable, but JavaScript doesn't seem to recognize it.
This did, however, work when I included the stylesheet within the page using <style>. I don't see why this would change when using <link>, though. Not only is it placed before the script, but it even returns undefined when using javascript:alert(document.styleSheets[0].cssText) in the omnibar after the page is fully loaded.
Thanks for any help.
Edit: This applies to any method with document.styleSheets[0], including those of which are supposed to work on multiple browsers and have worked for me prior to using <link>. For example: document.styleSheets[0].cssRules[0].selectorText

According to quirksmode.org, document.styleSheets[n].cssText is only supported in IE.
The form
document.styleSheets[n].cssRules[m].cssText
seems to be more widely supported, so you could just loop over that and build a string from the individual rules. (Although you have to replace cssRules with rules for IE).

I thing that this answer is out of time, but it could be useful for someone else.
The result can be "undefined" due 2 different reasons:
a) In some browsers, the property "cssRules" does not work (in accord with http://www.javascriptkit.com/domref/cssrule.shtml, only for supported in NS/ Firefox). For the other browser, you should use the property "rules", instead.
You can solve the problem using something like:
if (document.styleSheets[0].cssRules)
crossrule=document.styleSheets[0].cssRules[0]
else if (document.styleSheets[0].rules)
crossrule=document.styleSheets[0].rules[0]
to extract the rule and, afterwards, to extract the name of selector:
document.styleSheets[0].cssRules[0].selectorText
b) After the overpassing of the issue a), you may have another problem: The rules that starts with a #, like #import of #font-face, as considered as rules. However, their "selectorText" is undefined. So, you must have a way of skip them. I am working on it, right now. But I have not found yet a solution. Anyway, it is an help to know way it is happening.
Hope this helps

Related

Javascript code working in Mozilla Firefox but not in Google Chrome

I'm facing a little issue with my javascript code. In fact it's working in Firefox but not in Chrome, do you have any idea why I'm facing this issue?
Here is my code:
$('a').each(function(){
if($(this).css('background-image')=='url("linktothepng.png")'){
$(this).parent().remove();
}
});
Thank you for helping me, have a good day ;)
chrome will get it as url(linktothepng.png) (no quotes)
browsers parse css and format it their own way, it is not advisable to do text matches on those properties, just use a class with that background and check with hasClass() to prevent the inconsistency
The value returned by css('background-image') can be normalised in different ways by different browsers; they're all valid as long as they are equivalent CSS.
You could test for css('background-image').indexOf('linktothepng.png') != -1 which would work, assuming there isn't another image in use that has linktothepng.png as part of its name (which would require a more complicated test).
If possible though, you'd be better off only ever setting that background image by setting a class.
Easier to change.
Separates the meaning you are ascribing to that image from the fact that the image is how you are representing it.
Quicker to find, instead of replacing the test to something like if($(this).hasClass('the-class-you-use') remove the test and change the selector to $('a.the-class-you-use').

What repercussions do I get by using an undefined HTML element?

In an effort to write more expressive HTML, I feel custom HTML elements are a good way for any webapp or document I may write to have good meaning gleamed from the tag name itself without the use of comments.
It appears I can define a custom HTML element with:
document.registerElement("x-el");
However it also appears that I can use a custom element before defining it:
<body>
<x-salamander>abc</x-salamander>
</body>
Or even:
<salamander>abc</salamander>
I suppose this is invalid HTML, however both Firefox and Chromium proceed to display the element without any problems or console warnings.
I can even execute the following with no complaints from the browser:
document.getElementsByTagName("salamander")[0]
Using this tag name as a selector in CSS also works fine. So, what problems might I face if I use undeclared elements in this way?
The problem with what you're trying to do is not that we can tell you it will break in some expected ways. It's that when you deviate from standards in this way, no one knows what to expect. It is, by definition, undefined, and the behavior of browsers that see it is also undefined.
That said, it might work great! Here's the things to keep in mind:
The HTMLUnknownElement interface is what you're invoking to make this work in a supported way - as far as I can tell in 5 minutes of searching, it was introduced in the HTML5 spec, so in HTML5 browsers that use it appropriately, this is no longer an undefined scenario. This is where registerElement comes into play, which can take an HTMLUnknownElement and make it known.
Browsers are typically very good at coping with unexpected markup... but it won't always result in great things (see: quirks mode).
Not all browsers are created equal. Chrome, Firefox, Safari, Opera, even IE will likely have some reliable way to handle these elements reliably (even pre-HTML5)... but I have no idea what a screen reader (Lynx) or various other esoteric, outdated, niche or even future browsers will do with it.
Everyone has said the same thing, but it's worth noting: you will fail validation. It's OK to have validation errors on your page so long as you know what they are and why they are there, and this would qualify, but you'd better have a good reason.
Browsers have a long history of taking whatever you give them and trying to do something reasonable with it, so you're likely to be OK, and if you are interested in primarily targeting HTML5 browsers, then you're very likely to be OK. As with everything HTML related, the only universal advice is to test your target demographic.
First problem I can see is that IE8 and lower will not apply your styling consistently. Even with "css resets", I get issues in IE8. It's important for the browser to know whether it's dealing with a block, inline block, list, etc, as many CSS behaviors are defined by the element type.
Second, I've never tried this, but if you use jQuery or another framework, I don't think they're built to handle non HTML tags as targets. You could create issues for your coders.
And HTML validators will probably have heart-attacks, so you lose a valuable tool.
You are re-inventing the wheel here. AngularJS has already solved the problem of adding HTML elements and attributes via what it calls directives:
Angular's HTML compiler allows the developer to teach the browser new
HTML syntax. The compiler allows you to attach behavior to any HTML
element or attribute and even create new HTML elements or attributes
with custom behavior. Angular calls these behavior extensions
directives.
The goal of Angular is broader in that it treats HTML as if HTML were a tool meant to build applications instead of just display documents. To me, this broader goal gives real meaning and purpose to the ability to extend HTML as described in your question.
You should use the namespaced version document.createElementNS instead of plain document.createElement. As you can see in the snippet below,
(...your custom element...) instanceof HTMLUnknownElement
will return false if you do that (it will be true when you do it unnamespaced)
I strongly suspect that validators won't even complain, because it's in your own namespace, and the validator (unless written by a stupid person) will (at least, really really really should) acknowledge that the 'namespaced stuff' is something it doesn't know enough about to condemn it.
New (formerly custom) elements arising in future HTML versions is a certain thing to happen, and it will happen even more often for namespaced elements compared to elements in the default namespace. And the 'HTML specs crowd' is simply not in charge of what, for example, the 'SVG spec crowd' will be doing next year or in 10. And which new namespaces will be introduced by god knows who and become common. They know they are not 'in charge of that', because they aren't stupid. For those reasons, you can bet your last shirt that you will not run into any serious problems (like errors being thrown or something of that sort) when you just go ahead and use them - it's OK if you're the first one. The worst thing that could possibly happen is that they don't look (aren't rendered) the way you'd wish, if you didn't write any CSS for them; anyway, the foremost use-case are probably invisible elements (you can be sure that display:none will work on your custom elements) and "transparent containers" (which won't effect the rest of the CSS unless you have ">" somewhere in the CSS). Philosophically, what you're doing is very much akin to jQuery using class names to better be able to transform the document in certain ways. And there is absolutely nothing wrong with jQuery doing that, and if the class in question is not referenced by some CSS, that does not make the slightest difference. In the same fashion, there is absolutely nothing wrong when you use custom elements. Just use the namespaced version. That way, you're also safe to use any names that might later be added to 'proper' HTML without causing any conflicts with how those elements later will be supposed to work.
And if - surprisingly - some validator does complain, what you should do is go on with your custom elements and ditch that validator. A validator complaining about how you use your very own namespace you just came up with is akin to a traffic cop visiting you at your home and complaining about the fashion in which you use your restroom - ditch it, got me?
bucket1 = document.getElementById('bucket1');
console1 = document.getElementById('console1');
bucket2 = document.getElementById('bucket2');
console2 = document.getElementById('console2');
chicken = document.createElement('chicken');
chicken.textContent = 'gaak';
bucket1.appendChild(chicken);
console1.appendChild(document.createTextNode([
chicken instanceof HTMLUnknownElement,
chicken.namespaceURI,
chicken.tagName
].join('\n')));
rooster = document.createElementNS('myOwnNSwhereIamKing', 'roosterConFuoco');
rooster.textContent = 'gaakarissimo multo appassionata';
bucket2.appendChild(rooster);
console2.appendChild(document.createTextNode([
rooster instanceof HTMLUnknownElement,
rooster.namespaceURI,
rooster.tagName
].join('\n')));
=====chicken=====<br>
<div id='bucket1'></div>
<pre id='console1'></pre>
=====rooster=====<br>
<div id='bucket2'></div>
<pre id='console2'></pre>
MDN article
plus, you've got almost universal browser support for createElementNS.
hmmm... just found out that if you use .createElementNS, the created elements don't have the dataset property. You can still use .setAttribute('data-foo', 'bar') but .dataset.foo='bar' would have been nicer. I almost feel like downvoting my own answer above. Anyway, I hereby frown upon the browser vendors for not putting in dataset.

The jQuery addClass function quits my script

Uhm, I've got this script but it does not work.
It's all about this line: document.getElementById('thetest').addClass('superspecial');
As soon as the class should be added (but it isn't) the whole script quits...
Does anybody know why?
Should be:
jQuery('#thetest').addClass('superspecial');
or
document.getElementById('thetest').className += ' superspecial';
document.getElementById doesn't return a jQuery element.
That's why you get has no method error.
I know this is a bit of an old post by now, but I ran into it myself and I used a method that wasn't named before to solve it.
Instead of using
document.getElementById("name").className+='superspecial';
I used
document.getElementById("name").classList.add('superspecial');
After some research it seems that this is a fairly new way to do it that isn't supported in a lot of browser versions other than the latest. Browser requirements to use this functionality are as described here:
https://www.w3schools.com/jsref/prop_element_classlist.asp
I don't know the exact difference between the two solutions, but it seems to me that getting the classList and adding to it with an existing function would be the preferable option. Especially as += is a general method of adding things to eachother that doesn't always have to work the way you expect it to.

Generating/selecting non-standard HTML tags with jQuery, a good idea?

I've noticed that jQuery can create, and access non-existent/non-standard HTML tags. For example,
$('body').append('<fake></fake>').html('blah');
var foo = $('fake').html(); // foo === 'blah'
Will this break in some kind of validation? Is it a bad idea, or are there times this is useful? The main question is, although it can be done, should it be done?
Thanks in advance!
You can use non-standard HTML tags and most of the browsers should work fine, that's why you can use HTML5 tags in browsers that don't recognize them and all you need to do is tell them how to style them (particularly which tags are display: block). But I wouldn't recommend doing it for two reasons: first it breaks validation, and second you may use some tag that will later get added to HTML and suddenly your page stops working in newer browsers.
The biggest issue I see with this is that if you create a tag that's useful to you, who's to say it won't someday become standard? If that happens it may end up playing a role or get styles that you don't anticipate, breaking your code.
The rules of HTML do say that if manipulated through script the result should be valid both before and after the manipulation.
Validation is a means to an end, so if it works for you in some way, then I wouldn't worry too much about it. That said, I wouldn't do it to "sneak" past validation while using something like facebook's <fb:fan /> element - I'd just suck it up and admit the code wasn't valid.
HTML as such allows you to use any markup you like. Browsers may react differently to unknown tags (and don't they to known ones, too?), but the general bottom line is that they ignore unknown tags and try to render their contents instead.
So technically, nothing is stopping you from using <fake> elements (compare what IE7 would do with an HTML5 page and the new tags defined there). HTML standardization has always been an after-the-fact process. Browser vendors invented tags and at some point the line was drawn and it was called HTMLx.
The real question is, if you positively must do it. And if you care whether the W3C validator likes your document or not. Or if you care whether your fellow programmers like your document or not.
If you can do the same and stay within the standard, it's not worth the hassle.
There's really no reason to do something like this. The better way is to use classes like
<p class = "my_class">
And then do something like
$('p.my_class').html('bah');
Edit:
The main reason that it's bad to use fake tags is because it makes your HTML invalid and could screw up the rendering of your page on certain browsers since they don't know how to treat the tag you've created (though most would treat it as some kind of DIV).
That's the main reason this isn't good, it just breaks standards and leads to confusing code that is difficult to maintain because you have to explain what your custom tags are for.
If you were really determined to use custom tags, you could make your web page a valid XML file and then use XSLT to transform the XML into valid HTML. But in this case, I'd just stick with classes.

Why has innerHTML not been added to the w3c specs?

Is there any particular reason that it isn't in any of the the specs?
It seems to be supported in all browsers, (although I'll admit it doesn't work right in all of them...since you have to use libraries like innerXHTML to get it to work right thanks to Internet Explorer.
Is innerHTML in danger of disappearing from forthcoming versions of browsers? If not shouldn't they just add it already?
I'm marking this community wiki as I know I'm gonna take a beating on my rep for this...but I just wondered why...
http://dev.w3.org/html5/spec/Overview.html#innerhtml
There's absolutely no way it's in danger, thousands of applications rely on it and doing so would be a horrible idea.
I'll admit it doesn't work right in all of them...since you have to use libraries like innerXHTML to get it to work right thanks to Internet Explorer.
IE invented innerHTML; you can't really expect it to work any better than it does there.
Is there any particular reason that it isn't in any of the the specs?
It's proposed for HTML5, for what it's worth. There is certainly no danger of it disappearing in the future, though you should continue to use it only for the simple cases where you are writing straight ‘block’ or ‘inline’ element content. Special cases like tables and selects are going to continue to be troublesome.
IE, being the inventor of dynamically modifying the content has gone with it all the way - other browsers didn't!
Passing the string as innerHTML means that the string will get through a normalization process before it gets passed to the element. Meaning it will get transformed fom a string into a proper html parsing content.
Firefox implemented it wrongly. It doesn't distinguish between html:innerHTML and html:innerText and plain string:text. The difference is literally obvious for IE, but not for FF. Hence the difference in handling situations and the confusion of FF only coders when they go back to the master.

Categories