JavaScript selectAll\deselectAll checkboxes function doesn't work on IE8 - javascript

I have a Webscript (.js file) developed for an Alfresco application. It handles a button that displays a form aimed at selecting members which have subscribed to an Alfresco space, in order to send them a mail.
All the checkboxes are generated dynamically with the subscribers names.
You can check any member you want and you also have a special checkbox that enables you to select or deselect all the members.
This specific checkbox works properly on Chrome and Firefox.
However, when you check it on Internet Explorer 8, none of the members are selected or deselected, whether they names are check or not.
Here is the code sample of the form generation and of the onClick functions triggered when you check the checkbox :
updateMembersList : function TS_updateMembersList(containerId)
{
var div = Dom.get(containerId);
div.innerHTML = "<div class=\"memberDiv\">" +
"<input type=\"checkbox\" id=\"selectDeselectAllCb\" checked=\"true\" onchange=\"YAHOO.Bubbling.fire('selectDeselectAllChanged')\" class=\"memberCb\"/>" +
"<label for=\"selectDeselectAllCb\" class=\"memberLabel\">" +
this.msg('label.selectDeselectAll') + "</label>" +
"</div>";
for (var i=0; i<this.members.length; i++)
{
var member = this.members[i];
var avatar = Alfresco.constants.URL_CONTEXT + "/components/images/no-user-photo-64.png";
if (member.authority.avatar && member.avatar != "")
{
avatar = Alfresco.constants.PROXY_URI + member.authority.avatar + "?c=force";
}
div.innerHTML += "<div class=\"memberDiv\">" +
"<input type=\"checkbox\" id=\"cb_" + member.authority.userName + "\" checked=\"true\" onchange=\"YAHOO.Bubbling.fire('selectDeselectMemberChanged')\" class=\"memberCb\"/>" +
"<label for=\"cb_" + member.authority.userName + "\" class=\"memberLabel\">" +
member.authority.firstName + " " + member.authority.lastName + "</label>" +
"</div>";
}
},
selectDeselectAllChanged: function selectDeselectAllChanged(){
var selectDeselectAllCb = Dom.get('selectDeselectAllCb');
var checked = selectDeselectAllCb.checked;
console.log("Select All");
var cbs = YAHOO.util.Selector.query("input[id^='cb_']");
for (var i=0, j=cbs.length; i<j; i++)
{
var cb = cbs[i];
cb.checked = checked;
}
},
selectDeselectMemberChanged: function selectDeselectMemberChanged(){
var selectDeselectAllCb = Dom.get('selectDeselectAllCb');
var cbs = YAHOO.util.Selector.query("input[id^='cb_']");
var firstChecked;
if (cbs[0] != null){
firstChecked = cbs[0].checked;
}
for (var i=0, j=cbs.length; i<j; i++)
{
var cb = cbs[i];
if (cb.checked === firstChecked){
continue;
}
else{
selectDeselectAllCb.checked = false;
return;
}
}
selectDeselectAllCb.checked = firstChecked;
},
At the beginning, I thought that the query wasn't supported by IE8, but it's not the case.
Such a syntax is supported by IE7 and more recent versions.

Try removing console.log("Select All"); and replace it with Alfresco.logger.debug("Sellect All");
IE doesn't like console object.
Also, run your code on jslint - if you have an invalid json there somewhere, IE stops.
Also, try running IE in developer mode - set it up to show you script errors and you'll know where it stops.

I've solved the problem. I've replaced the onchange event handler by an onclick event handler. Indeed, onchange has a random behaviour on Internet Explorer, whereas onclick works fine in most of the case.
Thanks for the help.

Related

Passing argument to on click event of dynamically generated element

I am trying to pass arguments to onclick event of dynamically generated element. I have already seen the existing stackoveflow questions but it didn't answer my specific need.In this existing question , they are trying to access data using $(this).text(); but I can't use this in my example.
Click event doesn't work on dynamically generated elements
In below code snippet, I am trying to pass program and macroVal to onclick event but it doesn't work.
onClickTest = function(text, type) {
if(text != ""){
// The HTML that will be returned
var program = this.buffer.program;
var out = "<span class=\"";
out += type + " consolas-text";
if (type === "macro" && program) {
var macroVal = text.substring(1, text.length-1);
out += " macro1 program='" + program + "' macroVal='" + macroVal + "'";
}
out += "\">";
out += text;
out += "</span>";
console.log("out " + out);
$("p").on("click" , "span.macro1" , function(e)
{
BqlUtil.myFunction(program, macroVal);
});
}else{
var out = text;
}
return out;
};
console.log of out give me this
<span class="macro consolas-text macro1 program='test1' macroVal='test2'">{TEST}</span>
I have tried both this.program and program but it doesn't work.
Obtain values of span element attributes, since you include them in html:
$("p").on("click" , "span.macro" , function(e)
{
BqlUtil.myFunction(this.getAttribute("program"),
this.getAttribute("macroVal"));
});
There are, however, several things wrong in your code.
you specify class attribute twice in html assigned to out,
single quotes you use are not correct (use ', not ’),
quotes of attribute values are messed up: consistently use either single or double quotes for attribute values
var out = "<span class='";
...
out += "' class='macro' program='" + program + "' macroVal='" + macroVal + ;
...
out += "'>";
depending on how many times you plan to call onClickTest, you may end up with multiple click event handlers for p span.macro.

Dynamic HTML table with Javascript checkboxes puzzle - how to access checkbox.checked from outside of the function?

Before I begin, I should mention I am using Javascript but I'm not using JQuery.
I have a function which obtains data from a site and displays it in an HTML table.
I would like to add a checkbox to each row, and find if each one has been checked or not later (i.e. when a button is clicked), outside of the function that creates the table.
The reason for this is that the function that makes the table only runs once and can't check if the box is checked or not (the user hasn't had a chance to check any yet!).
Each checkbox relates to other data displayed on the same row, which I can access outside of _cb_findItemsAdvanced(root) by declaring the 'items' variable before the function begins. However, I can't seem to do this for checkboxes.
I can add normal checkboxes to the table with:
"<input type=checkbox...".
However, I can't seem to access them from outside of the function that makes the table (and calls for the data). I've tried:
document.form1.sharedCheckboxName
It didn't seem to work.
I have tried everything, from creating a global checkbox array and trying to specify
" + checkbox[i] + "
instead of
"<input type=checkbox...",
but it didn't work. I know my current code has just specified a variable of type checkbox, rather than what I want which is to populate the table with my existing, global, array of checkboxes.
Any help would be greatly appreciated, as I am lost! I hope you're not, after reading that! :-)
Here is my code:
var items;
var checkbox = [];
function _cb_findItemsAdvanced(root)
{
items = root.findItemsAdvancedResponse[0].searchResult[0].item || [];
var html = [];
html.push('<table width="100%" border="0" cellspacing="0" cellpadding="3"><form name="form1"><tbody>');
for (var i = 0; i < items.length; ++i)
{
var item = items[i];
var title = item.title;
var pic = item.galleryURL;
var viewitem = item.viewItemURL;
checkbox[i] = document.createElement('input');
checkbox[i].type = "checkbox";
checkbox[i].name = "name";
checkbox[i].value = "value";
checkbox[i].id = "id" + i;
if (null != title && null != viewitem)
{
html.push('<tr><td>' + '<img src="' + pic + '" border="0">' + '</td>' +
'<td>' + title + '</td>' + '<td> <input type = "' + checkbox[i].type + '" + </t></tr>');
}
}
html.push('</tbody></table>');
document.getElementById("results").innerHTML = html.join("");
}
if (checkbox[0].checked)
{
alert("HI"); //but nothing happens
}
since you are using html string forget about the checkboxes array.
your form should wrap the table not the other way around.
give your form an id
<form id="form1">
get the form and find all checkboxes
function findCheckedItems() {
var checkedItems = [];
var form = getElementById('form1');
var inputs = form.getElementsByTagName("input");
var checkboxIndex = 0;
for (var i = 0; i < inputs.length; i++) {
if (inputs[i].type.toLowerCase() === 'checkbox') {
if (inputs[i].checked) {
var data = item[checkboxIndex];
checkedItems.push(data);
// do whatever you like with the data
}
checkboxIndex++;
}
}
return checkedItems;
}

How do I execute an event using jQuery through an html object(button) created through Javascript?

I'm just new here. So here's where I'm stuck:
I created an html table using javascript. I have a button,which when clicked, will create set of tables with exactly the same structure but the objects(eg. button, text) inside those tables have different ID's. Now when I try to execute a click function using jQuery with a button on one of the produced tables, it won't work. How do I go around here? Thanks in advance!
Here's a sample function which creates the html table(with unique ID's) in javascript:
function CreateTables() {
var html = ' ';
var valPrompt = prompt("How many tables would you like to add?");
parseInt(valPrompt);
for (i = 1; i <= valPrompt; i++) {
html += "<table>" + "<tr>" + "<td>" + "Text goes here" + "</td>" + "<td>" + "<input type='text' id='txtTEXT" + i + "'/>" + "</td>" + "<td>" + < input type = 'button'
id = 'btnALERT" + i + "' / > +"</td>" + "</tr>" + "</table>"
}
document.getElementById('HtmlPlaceHolder').innerHTML = html;
}​
So, if we review the code, Sets of table with buttons(btnALERT) with unique ID's will be created if the function CreateTables is executed. In order to select the objects, I suppose I'll be using jQuery. So for example, if I bind a handler in btnALERT1(produced by CreateTables) say a click function in order to alert a simple "Hello", how will I do this? My code for this doesn't seem to work:
$(document).ready(function() {
$('#btnALERT1').click(function() {
alert("Hello");
});
});​
Use .live() (for older jquery versions - < v1.7):
$('#btnALERT1').live('click', function()
{
alert("Hello");
});
Or:
$(document).delegate('#btnALERT1', 'click', function()
{
alert("Hello");
});
Use .on() (for new jquery versions - >= 1.7):
$(document).on('click', '#btnALERT1', function()
{
alert("Hello");
});
I think you may want to use the method .on():
$(document).ready(function() {
$('#btnALERT1').on('click', function() {
alert("Hello");
});
});
For more information, check the online doc: http://api.jquery.com/on/
I would use a delegate on HtmlPlaceHolder to check for click events like so:
$("#HtmlPlaceHolder").on("click", "input[type=button]", function() {
alert($(this).attr("id"));
});
Also, I would change the button id scheme to btnALERT_1, so you can extract the ID number with a .split("_") method.
You have to attach the event handlers after you create the tables, not when the document is ready (the document should be ready anyways since the user is interacting with it).
You can do this with jQuery, sure, but have a look at the native methods - jQuery might be too bloated depending on what you will do and you will learn something about the DOM.
I've added some code below which lets you add a callback and shows some things you can get back easily. It is not exactly what you asked for, but a great start to finding your way in the DOM.
function CreateTables() {
var html = ' ';
var valPrompt = prompt("How many tables would you like to add?");
parseInt(valPrompt);
for (i = 1; i <= valPrompt; i++) {
html += "<table>" + "<tr>" + "<td>" + "Text goes here" + "</td>" + "<td>" + "<input type='text' id='txtTEXT" + i + "'/>" + "</td>" + "<td>" + < input type = 'button'
id = 'btnALERT" + i + "' / > +"</td>" + "</tr>" + "</table>"
}
var placeholder = document.getElementById('HtmlPlaceHolder').innerHTML = html;
placeholder.innerHTML = html;
placeholder.addEventListener('click', function (e) {
console.log(this, e);
}
}​

How can I append to a select drop down that lives on another page?

I'm working on creating a service that allows you to create team or user based challenges. Using HTML 5 specifications to design the page, I've run into a bit of an issue appending to a drop down list that resides in another page. The entirety of functionality lives within two pages, mainly by making AJAX calls to other pages. There's a little function that appends 2 properties of a team to a drop down list, but I can't seem to get it to work properly.
Code:
var teams = $.parseJSON(getAllTeams());
$('#multiPurpose').load('allTeams2.html #teamSelect');
for (i = 0; i < teams.length; i++) {
var team = $.parseJSON(getTeam(teams[i]));
if (team.ownerID === userID) {
$(
"<option value='" + team.teamID + "'>" + team.teamName
+ "</option>").appendTo('#teamSelection');
}
}
}
The #teamSelection is contained within the #teamSelect div. Any help would be great.
Adding a callback function within .load() will solve the problem. Basically, you're telling it to load everything within that div before running the for loop.
$('#multiPurpose').load(
'allTeams2.html #teamSelect',
function() {
for (i = 0; i < teams.length; i++) {
var team = $.parseJSON(getTeam(teams[i]));
if (team.ownerID === userID) {
$(
"<option value='" + team.teamID + "'>"
+ team.teamName + "</option>")
.appendTo('#teamSelection');
}
}
});

jQuery append not completing before next statement?

I have a survey-type form that's being populated from a web database on the client. I can populate the questions fine, but then I try to go through and trigger the click event where there is an existing answer (edit scenario), I'm finding that the new elements are not yet in the DOM so this doesn't work. Here's the code:
$(function() {
var db = openDatabase(...);
db.transaction(function(tx) {
tx.executeSql("select ....", [surveyId], function(tx, results) {
var items = "", answers = [];
for (var i = 0; i < results.rows.length; i++) {
var id = results.rows.item(i).id;
items += "<div><input type='radio' name='q-" + id + "' id='q-" + id + "-1' /><label for='q-"+id+"-1'>Yes</label><input type='radio' name='q-" + id + "' id='q-" + id + "-2' /><label for='q-"+id+"-2'>No</label></div>";
if (result.rows.item(i).answer) {
answers.push('#q-'+id+'-'+results.rows.item(i).answer);
}
}
$('#questions-div').append(items);
$.each(answers, function(i, e) { $(e).click(); });
});
});
});
Any tips how I can make this work, or better generally?
I think here:
answers.push('#q-'+id+'-'+result);
You meant to push this:
answers.push('#q-'+id+'-'+result.rows.item[i].answer);
Otherwise you're getting '#q-XX-[object Object]' as a selector, where I think you're after the 1 or 2 version of '#q-XX-1'.
I suspect this is actually a race condition. My bet is that if you execute your each statement after a tiny delay, things will work as expected. Is so, the reason for this is that you can't be 100% sure when the browser will actually get around to updating the DOM when you programmaticallly insert new elements. I'm not sure what the best solution would be: if you were attaching events, I'd say you should do it at the same time you are building the elements; but if you are triggering the clicks, I'm leaning toward just continually testing for the existance of the elements and then triggering the clicks as soon as you know they are there.
So I came up with a solution:
I replaced the line items += "<div> ...." with
var item = "<div><input type='radio' name='q-" + id + "' id='q-" + id + "-1' ";
if (results.rows.item(i).answer == 1) item += "checked ";
item += "/><label for='q-"+id+"-1'>Yes</label><input type='radio' name='q-" + id + "' id='q-" + id + "-2' ";
if (results.rows.item(i).answer == 2) item += "checked ";
item += "/><label for='q-"+id+"-2'>No</label></div>";
items += item;
... which means I no longer need the answers array or to trigger click events on the radio buttons.
I was hoping for something a bit neater, but this seems to work OK. Thanks #Nick Craver & #Andrew for helping me arrive at it!

Categories