IE Javascript Clicking Issue - javascript

First off, I'm working on an app that's written such that some of your typical debugging tools can't be used (or at least I can't figure out how :).
JavaScript, html, etc are all "cooked" and encoded (I think; I'm a little fuzzy on how the process works) before being deployed, so I can't attach VS 2005 to ie, and firebug lite doesn't work well. Also, the interface is in frames (yuck), so some other tools don't work as well.
Firebug works great in Firefox, which isn't having this problem (nor is Safari), so I'm hoping someone might spot something "obviously" wrong with the way my code will play with IE. There's more information that can be given about its quirkiness, but let's start with this.
Basically, I have a function that "collapses" tables into their headers by making normal table rows not visible. I have "onclick='toggleDisplay("theTableElement", "theCollapseImageElement")'" in the <tr> tags, and tables start off with "class='closed'".
Single clicks collapse and expand tables in FF & Safari, but IE tables require multiple clicks (a seemingly arbitrary number between 1 and 5) to expand. Sometimes after initially getting "opened", the tables will expand and collapse with a single click for a little while, only to eventually revert to requiring multiple clicks. I can tell from what little I can see in Visual Studio that the function is actually being reached each time. Thanks in advance for any advice!
Here's the JS code:
bURL_RM_RID="some image prefix";
CLOSED_TBL="closed";
OPEN_TBL="open";
CLOSED_IMG= bURL_RM_RID+'166';
OPENED_IMG= bURL_RM_RID+'167';
//collapses/expands tbl (a table) and swaps out the image tblimg
function toggleDisplay(tbl, tblimg) {
var rowVisible;
var tblclass = tbl.getAttribute("class");
var tblRows = tbl.rows;
var img = tblimg;
//Are we expanding or collapsing the table?
if (tblclass == CLOSED_TBL) rowVisible = false;
else rowVisible = true;
for (i = 0; i < tblRows.length; i++) {
if (tblRows[i].className != "headerRow") {
tblRows[i].style.display = (rowVisible) ? "none" : "";
}
}
//set the collapse images to the correct state and swap the class name
rowVisible = !rowVisible;
if (rowVisible) {
img.setAttribute("src", CLOSED_IMG);
tbl.setAttribute("class",OPEN_TBL);
}
else {
img.setAttribute("src", OPENED_IMG);
tbl.setAttribute("class",CLOSED_TBL);
}
}
­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­

Have you tried changing this line
tblRows[i].style.display = (rowVisible) ? "none" : "";
to something like
tblRows[i].style.display = (rowVisible) ? "none" : "table-row";
or
tblRows[i].style.display = (rowVisible) ? "none" : "auto";

setAttribute is unreliable in IE. It treats attribute access and object property access as the same thing, so because the DOM property for the 'class' attribute is called 'className', you would have to use that instead on IE.
This bug is fixed in the new IE8 beta, but it is easier simply to use the DOM Level 1 HTML property directly:
img.src= CLOSED_IMAGE;
tbl.className= OPEN_TBL;
You can also do the table folding in the stylesheet, which will be faster and will save you the bother of having to loop over the table rows in script:
table.closed tr { display: none; }

You might want to place your onclick call on the actual <tr> tag rather than the individual <th> tags. This way you have less JS in your HTML which will make it more maintainable.

If you enable script debugging in IE (Tools->Internet Options->Advanced) and put a 'debugger;' statement in the code, IE will automatically bring up Visual Studio when it hits the debugger statement.

I have had issues with this in IE. If I remember correctly, I needed to put an initial value for the "display" style, directly on the HTML as it was initially generated. For example:
<table>
<tr style="display:none"> ... </tr>
<tr style="display:"> ... </tr>
</table>
Then I could use JavaScript to change the style, the way you're doing it.

I always use style.display = "block" and style.display = "none"

Related

Read more opens 1st one all the time

I've a page with about 10 short articles.
Each of them as a "Read More" button which when pressed displays hidden text
The issues I have at the moment is when I press the "Read More" on any of the 10 button it shows the 1st articles hidden content and not the selected one.
I think I need to set a unique ID to each article.. and the read more button be linked to it.. But I don't know how to set it.
I looked at this but couldn't get it working how to give a div tag a unique id using javascript
var WidgetContentHideDisplay = {
init:function() {
if ($('#content-display-hide').size() == 0) return;
$('.triggerable').click(function(e){
var element_id = $(this).attr('rel');
var element = $('#'+element_id);
element.toggle();
if (element.is(':visible')) {
$('.readmore').hide();
} else {
$('.readmore').show();
}
return false;
});
}
}
var div = documentElemnt("div");
div.id = "div_" + new Date().gettime().toString;
$(document).ready(function(){ WidgetContentHideDisplay.init(); });
OP Edit: Sorry, the original code wasn't in caps. I kept getting errors when trying to post, so I copied the code into Dreamweaver and it made it all caps for some reason.
Instead of selecting the element to toggle with an ID (i.e. $('#'+ELEMENT_ID)) you could setup a class for your item and use the class selection (e.g. $('.DETAILED-ARTICLE)') to select the child (or the brother, etc. depending how you built the HTML page).
In theory each ID should point to a single element but each class can be put to as many elements as you want.
If you're getting errors, read the errors and see what they are. Off of a quick read of your code, here are a couple things I noticed that will probably cause issues:
"documentElemnt" is misspelled, which will render it useless. Also, documentElement is a read-only property, not a function like you're using it.
toString is a function, not a property, without the parentheses (.toString()) it isn't going to function like you want it to.
Run the code, look at the errors in the console, and fix them. That's where you start.

Title attribute in Firefox

The title attribute on a particular HTML element is not displayed in my application if viewed in Firefox. There are multiple topics explaining this problem. I was unable to find a sollution that would fit my needs. So I ask if you can please help.
I have a number of divs lined up. On mouseover each of the div's should display a different value(title). The title attribute works fine in Chrome but I need something simillar for Firefox.
The title attribute is set dynamically from Javascript!
My Javascript:
dojo.connect(div, 'mousemove',rasterTimeDisplay);
function rasterTimeDisplay() {
dojo.attr(evt.target, 'title', "some new title");
}
Why not to store the data to be displayed in another attribute ? Because you use javascript to feed your data-storage attribute, you can whatever you want.
For example, with jQuery :
//I feed my data-storage attribute
$("#my_div").attr('my-data', '<h1>my content to be displayed</h1>');
//And then i bind the hover event to toggle displaying of this data
$("#my_div").hover(
function(){
$(this).html($(this).attr('my-data'));
},
function(){
$(this).html('');
}
);
Or with standard JavaScript :
document.getElementById('my_div').my_data = '<h1>my content to be displayed</h1>';
document.getElementById('my_div').onmouseover = function(){
this.innerHTML = this.my_data;
};
document.getElementById('my_div').onmouseoout = function(){
this.innerHTML = '';
};
Sorry if i missunderstood you. However, you are trying to trigger the title attribute on hover? But the title attribute is already triggered by hover on default:
So if you just add the attribute to your desired element, you will get the extra information on hover.
var titles = document.getElementsByClassName('title');
for(var i = 0; i < titles.length; i++)
{
titles[i].title = 'Hover information ' + i;
}
jsFiddle
I you're interesting in the jQuery way to do this:
$('.title').attr('title', 'Hover information');
Still doesn't work?
Step-1: First try to run your firefox client in safe-mode. Your problem might be solved now. If this is the case proceed to step-2. Else... Well i would suggest you to update your grapical driver or install a newer version.
Step-2: Disable your Hardware Acceleration(AH).
Check another answer about this here: https://support.mozilla.org/nl/questions/860902
Now if you just want a work around, to even let the oldest Firefox browsers support this. You can find one here: Tooltips (title="...") won't show in Firefox
I hope this solved your problem.

have element change appreance with only javascript and CSS

attempting to have my webpage be a bit more dynamic by having the background change on some elements when a checkbox is clicked. I am trying to do this via class change and a CSS sheet. I have the following which is kicking out an error that my onclick function ins not defined (in IE9). More importantly will the webpage update if I only change the class of the object which would have a different class in the CSS file. Whats a better alternative if this does not work?
my elemenet and function
UPDATE
I made updates to both my HTML and CSS file as suggested by many. I am still getting no change in my webpage but the console is claiming that my function called from the onclick event is not defined which is a bit odd since it is. Also does this type for scripting belong in the HTML or should I pull it out and put in a seperate file. I figured since it was creating elements it belongs in the main html. Is there a cleaner more compact way of accomplishing this and not making my home screen html huge?
<tr class= 'tr.notchosen'><td><input type='checkbox' onclick='handleClick(this.id)'/></td></tr>
function handleClick(cb) {
var currentColumn = cb.parentNode
var currentRow = currentColumn.parentNode
if (currentRow.className === "chosen")
{
currentRow.className = "notchosen";
}
else
{
currentRow.className = "chosen";
}
}
and my css file is the following
tr.chosen
{
background-color:rgba(255,223,0,0.75);
}
tr.notchosen
{
background-color:rgba(255,223,0,0);
}
There are a couple of things going on here. First, your css selector is not quite right. In fact, I would suggest making the class name just "chosen" or "not chosen" and then selecting tr elements with that class.
<tr class='notchosen'>
And then you can target it from css (which was probably the original intention)
tr.notchosen
{
background-color:rgba(255,223,0,0);
}
Further, although I would not suggest using inline javascript, using your example, you should pass this if you want to work with the element and not this.id which would pass a string.
onclick='handleClick(this)'
The last part would be to sync up your javascript with the class name change
if (currentRow.className == "chosen")
{
currentRow.className = "notchosen";
}
else
{
currentRow.className = "chosen";
}

Javascript toggle list-style

I am trying to build a little toggle switch which removes line numbers on click.
I have got it working here: http://www.webdevout.net/test?09&raw
It is code highlighted by Geshi, and i build the javascript at the top to toggle line numbers.
This works fine, but what I would really want is that when the line numbers are 'hidden', that it also removes that gap on the left. So that the actual code fills the screen.
If clicked again, the lines numbers would come back again.
You have to change the ol element's padding to 0:
document.getElementsByTagName("ol")[0].style.padding = '0';
Above script is assuming you only have one <ol> in your document, or at least the first one is the one you'd like to edit.
EDIT
You would have to switch between
document.getElementsByTagName("ol")[0].style.paddingLeft = '20px';
and
document.getElementsByTagName("ol")[0].style.paddingLeft = '0px';
Your approach is a tad bit wrong though, you should be changing the listStyle of the <ol> tag and not of the individual <li> tags.
document.getElementsByTagName("ol")[0].style.listStyle = 'none';
and
document.getElementsByTagName("ol")[0].style.listStyle = 'decimal';
EDIT2 Perhaps give this a try. If you could also link me to it, I can test it in chrome and firefox as well. Maybe I'm not getting your problem..
function toggle_visibility() {
var e = document.getElementsByTagName("ol")[0];
if(e.style.listStyle == 'none') {
e.style.listStyle = 'decimal';
e.style.paddingLeft = '20px';
} else {
e.style.listStyle = 'none';
e.style.paddingLeft = '0px';
}
}
}
Link
<a onclick="toggle_visibility();">toggle</a>
EDIT3
Ah, I found the problem :)
if(document.getElementsByTagName("ol")[0].style.listStyle.substr(0,4) == 'none')
Because when you set the listStyle to 'none' it actually gets set to 'none outside none' by firefox and IE. So if you use .substr(0,4) to get the first 4 characters to compare to none, you should be fine :)

Optimizing jquery selector for Chrome

I have the following jquery code to loop over 525 (I know, alot!) checkboxes:
var elements = $("#profile-list table tr input[type=checkbox].email-checkout:not(:checked)");
$.each(elements, function(i) {
$(elements[i]).attr('checked', 'checked');
});
UPDATE The html looks like this:
<table>
<tr>
<th>Name</th>
<th>Title</th>
<th>E-mail</th>
<th>Telephone</th>
<th id="email_check"><img src="check_black.png"/></th>
</tr>
<?php foreach ($this->profiles as $profile): ?>
<tr>
<?php echo $this->presentProfile($profile, 'list') ?>
</tr>
<?php endforeach; ?>
This basically loops over all profiles in the database and creates a table row for each profile, where the last table data includes a checkbox, which one can select to send email to. If the user clicks the table header with the id of "email_check" then the javascript code should kick in, and that's where Chrome fails.
I attach the event with the following code:
$("#email_check img").live('click', function() {
//my code
}
When I run this code in Firefox (mac), it goes smoothly but when I run it in Chrome (mac) it takes forever and ends up giving me the window where chrome offers me the option of killing the window, so basically it never completes this loop.
I've been trying to optimize this selector as much as I can, and since jquery 1.3, I understand that they switched from left to right to right to left selector, which basically means that I should try to make my right most selector as specific as I can. Can it be any more specific than I currently have?
Or is it the loop that just takes so long? I have tried switching from $.each to just a regular for() without a positive result.
Any tips or ideas how I can fix this?
Ingiber
I really don't think this is a selector issue at all.
Your selector is a valid selector for querySelectorAll, which means it will be extremely fast.
I tested the exact selector in Chrome on Mac against a table with 250 rows, and the result was instantaneous.
I'd guess that there's something else going on.
Try removing the table tr part of the selector. It isn't adding anything.
Try this:
// console.time("test");
var elements = $("#profile-list input[type=checkbox].email-checkout").get();
var len = elements.length;
for (var i = 0; i < len; i += 1) {
elements[i].checked = true;
}
// console.timeEnd("test");
(So, first we select all check-boxes that are of the class "email-checkout" and are inside the #profile-list element. Then we just set their checked property to true. I assume, this is as fast as it can be.)
You could always give each check box a select/deselect event that will add/remove a class from the checkbox, then use the class as the selector.
You can use a .each() on the set to use the elements directly, like this:
$("#profile-list table tr input[type=checkbox].email-checkout").each(function() {
this.checked = true;
});
Also note the removal of :not(:checked) above...if you're going to check them all, that selector is more expensive that actually checking them anyway. More importantly is that this.checked = true; is tremendously cheaper than $(elements[i]).attr('checked', 'checked'); which happens every time.
Did you profile this? What is taking too long, getting the elements or looping over them? The only way to really speed up code is to profile and fix the slow parts.
FWIW, I would try
var elements = $("#profile-list").find("input[type=checkbox].email-checkout").get();
...
and see what happens.
Add an onlclick on the checkbox
$("#profile-list input[type=checkbox].email-checkout").click(function() {
var obj = $(this);
obj.hasClass("checked") ? obj.removeClass("checked") : obj.addClass("checked");
});
s = $("input[type=checkbox].email-checkout.checked");

Categories