Swap div on link hover - Javascript error in Firefox - javascript

I have some code which allows me to hover over a number of links and subsequently replace the content in a specified DIV. It works in most browsers but Firefox gives an error - the error can be 'fixed' by removing the doctype code for the page, but clearly this means there is a massive problem with the code and it's not compliant.
Here is the Javascript:
var description = new Array();
description[0] = "Content one";
description[1] = "Content two";
description[2] = "Content three";
Each link looks like this, with a different number:
<a onMouseOver="FeatureSwap.innerHTML = description[1];">
And this is the DIV which has its content changed upon hovering on one of the links:
<div id="FeatureSwap">Default content here</div>
The error that Firefox throws up is:
FeatureSwap is not defined

innerHTML is an attribute of an element of the DOM, the Document Object Model.
So you need to first gain access to the element. In your case, the element is the div with id of FeatureSwap.
In the following code, we first look up the element by its ID using a method that is common to most all browsers. Then we set its innerHTML property.
Try
<a onMouseOver="document.getElementById('FeatureSwap').innerHTML = description[1];">
FYI, by removing the doctype declaration you led Firefox to display your page in "quirks mode" rather than the standards-compliant mode. One of the notable features of quirks mode in Firefox is that elements can be accessed by their IDs as if they were variables. For more information see the WHATWG spec.

Try:
<a onMouseOver="document.getElementById('FeatureSwap').innerHTML = description[1];">

Related

When are dynamic scripts executed?

I was doing the google XSS games (https://xss-game.appspot.com/level2), but I couldn't quite figure out why level 2 wasn't working the way I was expecting. Even though the hint says that script tags won't work, I didn't know why. My question is basically when are dynamic script tags executed and does this vary by browser?
I tried something simple as:
<script>alert();</script>
And while it adds the element to the page, it doesn't do what I had hoped.
I found this post which has the same problem, but the solution is just an answer, but not an explanation:
Dynamically added script will not execute
If a site sanitizes only SCRIPT tags but allows other HTML - it opens itself to XSS. The hint in the Level 2 is text in the message window having some HTML formatting (italic, color etc.) so the assumption here - HTML tags are allowed.
So you can enter something like
<i>Hello Xss</i>
Into the message window to display text in italic. But a DOM element can have an event handler attached to it - you can include executable JavaScript into event handler without any SCRIPT tags.
Try entering this into message window:
<i onmouseover="alert(1)">Hello Xss</i>
and after submitting message wave mouse over your message text.
The answer to your question is that <script> tags added via .innerHTML do not execute.
From https://developer.mozilla.org/en-US/docs/Web/API/Element.innerHTML :
Security considerations
It is not uncommon to see innerHTML used to insert text in a web page. This comes with a security risk.
var name = "John";
// assuming el is an HTML DOM element
el.innerHTML = name; // harmless in this case
// ...
name = "<script>alert('I am John in an annoying alert!')</script>";
el.innerHTML = name; // harmless in this case
Although this may look like a cross-site scripting attack, the result is harmless. HTML5 specifies that a tag inserted via innerHTML should not execute.
However, there are ways to execute JavaScript without using elements, so there is still a security risk whenever you use innerHTML to set strings over which you have no control. For example:
var name = "<img src=x onerror=alert(1)>";
el.innerHTML = name; // shows the alert

Remove title tag tooltip

Is there any way to remove the tooltip from title attribute without actually remove the title.
I have a link with a title attribute like this
It is important that the title is intact since I need to read the url from there. All the fixes for this that I have found is to remove the title attribute and reuse it but in this case this is not possible.
Any ideas?
It's all about the browser. It's the browser that sees the title as a tooltip, from the browser specifications and interpretations.
You should use if you want to handle data like that, the HTML5 way (which you can use in any other document type as it's ignored) and use:
with the data- attributes, there will be no tooltip as title is not used, and you can easily get that using:
$("a").attr("data-title")
but, you will need to convert stuff and you said that you don't/can't do that.
you can easily convert all titles into data-title and clean the title using
$("a").attr("data-title", function() { return $(this).attr("title"); } );
$("a").removeAttr("title");
(all code is to be used with jQuery Framework)
As you didn't mark this question as jquery, I'm assuming that you'd be open to a pure JavaScript solution?
The following works (on Ubuntu 11.04) in Firefox 5, Chromium 12 and Opera 11, I'm unable to test in IE, but as I'm using querySelectorAll() I'd suspect that it wouldn't work well, if at all. However:
var titled = document.querySelectorAll('[title]'); // gets all elements with a 'title' attribute, as long as the browser supports the css attribute-selector
var numTitled = titled.length;
for (i=0; i<numTitled; i++){
titled[i].setAttribute('data-title',titled[i].title); // copies from 'title' to 'data-title' attribute
titled[i].removeAttribute('title'); // removes the 'title' attribute
}
JS Fiddle demo.
References:
document.querySelectorAll at the Mozilla Developer Network.
Why don't you use jQuery to move this information from title to element data.
Run this on element load:
$(el).data('url', $(el).attr('title')).attr('title', '');
And afterwards read URL like this:
$(el).data('url');
Variable el here is DOM element or element selector.

Access elements in one frameset from other frameset

I have a html page in which I have two framesets each pointing to different html.
Now let's say, I have a textbox in first frameset (html) and a button in my second frameset (html).
Could anyone please let me know how to hide textbox when I click the button?
not tested, but it should be like this (in the onclick-handler of your button):
parent.frames[1].document.getElementByid('mytextfield').style.display = 'hidden';
// ^^^ here you could also access the frame by its name using ['mysecondframe']
you can do all of the above only if the two frames are in the same domain. Due to browsers security policies, if the frames aren't on the same domain and even on the same protocol, they cannot interact with each other ( javascript is out of the question ).
You can access the element via the getElementById function on the document object of the frame in question (note that we use the target frame's document, not our own). You can get the frame from the frameset by name — frame names become properties of the frameset's window object.
Example (live copy; button frame code):
var textbox = parent.targetFrame.document.getElementById('theTextBox');
textbox.value = "You clicked at " + new Date();
...where targetFrame is the name of the target frame. You can also use frames[n] where n is the index of the frame in the frameset, but I find names more robust.
The above example is tested and works on Firefox, Chrome, and Opera for Linux and IE6 — and so should work on a broad set of browsers.

DOCTYPE breaks style.display

I have a (legacy) JS function, that shows or hides child nodes of argument element. It is used in mouseover and mouseout event handlers to show-hide img tags.
The function looks like this:
function displayElem(elem, value, handlerRoot){
try{
var display = 'inline';
if(!value)
display = 'none';
if(handlerRoot)
elem.style.display = display;
var childs = elem.childNodes;
for (i = 0; i < childs.length; i++){
if(childs[i].nodeType == Node.ELEMENT_NODE){
childs[i].style.display = display;
alert("Node "+childs[i].tagName+" style set to " +childs[i].style.display);
}
}
}catch(e){
alert('displayElem: ' + e);
}
}
Here, value and handlerRoot are boolean flags.
This function works perfectly, if target html page has no doctype. Adding any doctype (strict or transitional) breaks this. Alert shows style has been set to the right value, but child elements are not displayed.
Would be good, if this function could work with any DOCTYPE.
Image (a child node of elem) is initialized like this (perhaps something is wrong here?):
var img = new Image();
img.style.cssText =
'background: transparent url("chrome://{appname}/content/dbutton.png") right top no-repeat;' +
'position: relative;' +
'height:18px;'+
'width:18px;'+
'display:none;';
JavaScript doesn't really work over plain HTML but on the DOM tree generated by the browser. Thus the DOCTYPE does not have a direct influence on JavaScript but on the way the browser handles invalid HTML and CSS.
I think the first step is to clean-up the HTML and make sure it's valid, esp. that tags are used in allowed places and properly nested. That will guarantee that the generated node tree is the same no matter the rendering mode.
You can also use your favourite browser tool (such as Firebug) the inspect the real tree and make sure nodes are placed where you think they are.
Update:
I wonder if when dealing with a document in standards mode (the document has a DOCTYPE), Firefox is inserting an implied element that it doesn't insert in backward-compat mode (no DOCTYPE), and so the image isn't an immediate child of elem but instead a child of this implied element that's then a child of elem; so you won't see the image in elem.childNodes. Walking through the code in a debugger is the best way to tell, but failing that, alert the tagName of each of the child nodes you're iterating through in the loop.
For example, with this markup:
<table id='theTable'>
<tr><td>Hi there</td></tr>
</table>
...Firefox will insert a tbody element, so the DOM looks like this:
<table id='theTable'>
<tbody>
<tr><td>Hi there</td></tr>
</tbody>
</table>
...but it won't be that specific example unless the DOCTYPE is a red herring, because I just tested and Firefox does that even in backward-compat mode. But perhaps you were testing two slightly different documents? Or perhaps it does it with some elements only in standards mode.
Original:
Not immediately seeing the problem, but I do see two issues:
i isn't declared in the function, and so you're falling prey to the Horror of Implicit Globals. Since your alert is showing the correct value, I can't see why that would be the problem.
url(..) in CSS doesn't use quotes. Yes they can, optionally.
Thanks to Álvaro G. Vicario. Though he didn't gave an exact answer, the direction was right.
I've checked the page with w3c validator, and found that my Image objects were missing src attribute. Thus, adding img.src = "chrome://{appname}/content/dbutton.png"; helped.
Still, I'm not sure, why the original code author used background style instead of src... Perhaps, that would remain a mystery. :)

Firefox not able to find iframe

This is the iframe I'm trying to access:
<div class="mceBody" id="additionalTxt_b">
<iframe frameborder="0" id="additionalTxt_f" src='javascript:""' class="punymce"/>
</div>
Using this line:
frames['additionalTxt_f'].document.getElementsByTagName("body")[0].innerHTML
For some reason I'm getting "frames.additionalTxt_f is undefined" from firebug.
I have similar iframes (dynamically created by punyMCE plugin) on other pages, and they work perfectly fine. And IE7/8 has no problem accessing this iframe either.
Just at a complete loss here. Any ideas on why Firefox can't find the iframe?
The window.frames[] array is indexed by the [i]frame's name attribute (aka frame target). id can't be relied upon to also work — although it may in IE <8, which often thinks names and ids are the same thing.
If you want to access a frame's content via ID, use the DOM Level 2 HTML contentDocument property instead of the old-school (“DOM Level 0”) frames array:
document.getElementById('additionalTxt_f').contentDocument.body.innerHTML
...but then, for compatibility with IE <8, you also have to add some fallback cruft, since it doesn't support contentDocument:
var f= document.getElementById('additionalTxt_f');
var d= f.contentDocument? f.contentDocument : f.contentWindow.document;
d.body.innerHTML
So it's up to you which method you think is less ugly: the extra script work, or just using the name attribute.
if you have only 1 iframe you can also find it with window.frames[1] or
document.getElementsByTagName('iframe')[0]
(In the first option, the parent window is #0)

Categories

Resources