Setting ID for "n" buttons - javascript

//Display
for (var z=0; z<n; z++) {
document.write("<tr><td>"+ z + "</td>"); // Serial
document.write("<td>" + RandonValue + "</td>"); // Random Number
document.write('<td><button onclick="reply_click()" id="button-' + z + '">Click me</button></td></tr>'); //onClick
}
//Set ID
function reply_click(clicked_id){
alert(clicked_id);
}
Somehow I got undefined for all of them.
The replay_click is only for checking, I want to change that when I have different IDs.

Your z variable is the counter in this case which you can use for your id, keep in mind you can't have an ID starting with a number.
document.write('<td><button onclick="somefunction" id="button-' + z + '">Click me</button></td></tr>');

I have created a fiddle for you. Check it. I hope it fulfills the requirements :)
https://jsbin.com/doxusi/edit?html,js,output
<table id="mytable"></table>
var html = '';
var random = 5;
for (var i = 1; i <= random; i++) {
html += '<tr>' +
'<td>' + i + '</td>' +
'<td>Some Number</td>' +
'<td><button id="id_' + i + '">Button ' + i + '</button></tr></td>';
}
document.getElementById('mytable').innerHTML = (html);

You can inject your z variable like this, also putting double quotes (best practice:
document.write('<td><button onclick="somefunction(this)" id="mycell-' + z + '">Click me</button></td></tr>');
Note that you better pass this to your function, so inside that function you can reference that id:
function somefunction(elem) {
alert('you clicked ' + elem.id);
}

Related

this.id is not working to detect which link is clicked in href

I am new to javascript and I am creating a bookstore using the google API. I have a small issue which I couldn't figure out. In the below piece of code that I saw from example code of google api bookstore function, I am trying to create href for the title of the book and pass its selfLink to the destination page i.e book-description.html.
When I put alert(this.id) on onclick It works, but for a normal method get(this) it does not work. I do not need an alertbox I want to take the id of the link clicked in href and pass it to another html.
handleResponse(response) {
for (var i = 0; i < response.items.length; i++) {
var item = response.items[i];
var a = item.volumeInfo.title;
var selfL = item.selfLink;
//var b = a.link("book-description.html");
var image = item.volumeInfo.imageLinks.smallThumbnail;
document.getElementById("content").innerHTML += "</br>" + "</br>" + "<br>" + "<img src =" + "'" + image + "'" + " class='im'/>";
document.getElementById("content").innerHTML += "<h4 class='right'>" + "<a href = 'book-description.html'id = " + "'" + selfL + "'" +
"onclick ='get(this);'>" + a + "</a></h4>";
function get(e) {
var link = e.id;
localStorage.setItem("Link", link);
}
document.getElementById("content").innerHTML += "<h4 class='right'>" + "AUTHOR:" + item.volumeInfo.authors + "</h4>";
document.getElementById("content").innerHTML += "<h5 class='right'>" + "PUBLISHER:" + item.volumeInfo.publisher + "</h5>";
var rating = item.volumeInfo.averageRating;
if (rating) {
document.getElementById("content").innerHTML += "<h5 class='right' id='rating'>" + rating + "</h5>";
} else {
document.getElementById("content").innerHTML += "<h5 class = 'right' id ='rating'>Not Rated Yet</h5>";
}
//document.getElementById("content").innerHTML += "<br>" + "<br>" + "<br>" + item.volumeInfo.publisheddate;
}
}
There are a number of problems with your code, but specifically in answer to your question; your function get is scoped so it is only available within the function handleResponse. For it to be accessible from an onclick it must be in page scope.
Simply move this
function get(e) {
var link = e.id;
localStorage.setItem("Link", link);
}
Into the head of your page
In programming there is the concept of DRY (Don't repeat yourself). So store a reference to document.getElementById("content") and reuse that variable.
var content = document.getElementById("content");
content.innerHTML = ...
You're missing some spaces in your output html. This may work in some browsers, others will struggle
<a href = 'book-description.html'id=
Should have a space between the end of one attribute and the start of another
<a href='book-description.html' id=
And for heaven sake, sort out the concatenation of your strings. You dont need a + if its just a simple string
document.getElementById("content").innerHTML += "</br>" + "</br>";
should be
document.getElementById("content").innerHTML += "</br></br>";

Assign to each user a color

I am currently creating a web-chat and whenever a message is displayed in the chat-box, the user that sent the message is displayed and identified with a color. For every user I create a class and assign a value to the color style with the above function.
newHTML = '';
$.each(data, function(index, element) {
$('.user_' + element.senderId).attr("style","color:" + randColor());
newHTML = newHTML + '<div id="boxMsg"><b><span class="user_' + element.senderId + '">'
+ element.senderId + '</b></span></br>' + element.message + '&nbsp&nbsp<span class="dateMsg">' + dateTime.substring(11, 16) + '</span></div>';
});
$('#chatbox').append(newHTML);
},
A JSON protocol is used to extract all the information concerning the message displayed on the chat. But still it doesn't work and all the usernames are black. Do you know what am I doing wrong?
Thanks in advance for your replies!
EDIT: thanks to #Evan I solved the first part and the function to assign a random color works. But still, only the first and the third member of the chat color changes. The others are still black. Anyway, I leave the code for the function randColor().
function randColor(){
var letters = '0123456789ABCDEF'.split('');
var color = '#';
for (var i = 0; i < 6; i++ ) {
color += letters[Math.floor(Math.random() * 16)];
}
return color;
};
EDIT.2: I have corrected the function to reflect more the one I am working on.
for (var i = 0; i <= nUsers.length; i++ )
should be
for (var i = 0; i < 6; i++ )
to form a hex color. It should always be 6 (or 3 for short hex colors).
Try to use .attr("style",properties)
If you need to change de background color use the property "background-color":
$('.user_' + element.senderId).attr("style","background-color:" + randColor());
Or, if you need to change de font color use the property "color":
$('.user_' + element.senderId).attr("style","color:" + randColor());
You have error in your HTML-->
var newHTML = '';
newHTML = newHTML + '<div id="boxMsg"><b><span class="user_' + element.senderId + '">' + element.senderId + '</b></span></br>' + element.message + '&nbsp&nbsp<span class="dateMsg">' + dateTime.substring(11, 16) + '</span></div>';
$('#chatbox').append(newHTML);
The "bold" tag closes before the span.
Fix it -->
newHTML = newHTML + '<div id="boxMsg"><b><span class="user_' + element.senderId + '">' + element.senderId + '</span></b></br>' + element.message + '&nbsp&nbsp<span class="dateMsg">' + dateTime.substring(11, 16) + '</span></div>';
Other then that, you can call the randomColor when you build the HTML, instead calling it after with jquery... (and you won't need a special class)-->
newHTML = newHTML + '<div id="boxMsg"><b><span style="color:'+randColor()+'">' + element.senderId + '</span></b></br>' + element.message + '&nbsp&nbsp<span class="dateMsg">' + dateTime.substring(11, 16) + '</span></div>';
I managed to solve the issue and correctly assign a color to each user. This is how the final code looks like:
function randColor(){
var letters = '0123456789ABCDEF'.split('');
var color = '#';
for (var i = 0; i < 6; i++ ) {
color += letters[Math.floor(Math.random() * 16)];
}
return color;
};
userColor = [];
userColor.push(randColor());
$('.user_' + element.senderId).css("color", userColor);
// Create box messages of the other users
var dateTime = element.timestamp;
newHTML = '<div id="boxMsg"><b><span class="user_' + element.senderId +'" style="color:'+ userColor +'">'+ element.senderId + '</span></b></br>'
+ element.message + '&nbsp&nbsp<span class="dateMsg">' + dateTime.substring(11, 16) + '</span></div>';
$('#chatBox').append(newHTML);
What I did was to create an array, store the obtained colors inside it and finally assign to each class of each user one element inside this array. Thanks to all of you for your answers!

Removing objects from an array onclick

I have a an array of items which holds item objects. I want to create a function that when I click on a certain item it is removed from the array. I know I need to use something like splice and I have implemented the following solution but it does the seem to work.
Can anyone tell me what am I doing wrong.
function updateView() {
for (var i = 0; i < storeItems.length; i++) {
output += "<a href='#' id='itemTitle' onclick='removeRecord(" + i + ");'>"
+ storeItems[i].title + " " + "\n" + "</a>";
}
function removeRecord(i) {
storeItems.splice(i, 1);
var newItem = "";
// re-display the records from storeItems.
for (var i = 0; i < storeItems.length; i++) {
newItem += "<a href='#' onclick='removeRecord(" + i + ");'>X</a> "
+ storeItems[i] + " <br>";
};
document.getElementById('foods').innerHTML = newItem;
}
I think this the error is in the line below:
output += "<a href='#' id='itemTitle' onclick='removeRecord(" + i + ");'>" + storeItems[i].title + " " + "\n" + "</a>";
Because it does not recognise the "onclick" event even when I try to do a test with a simple alert.
Can anyone tell me what am I doing wrong. Also if you think you need more information to answer this question please let me know.
Thank you in advance.
Try ...
storeItems = storeItems.splice(i, 1);
WRONG: Basically, you have to assign the spliced array to something.
UODATE:
Here's the way I would do it ... tested in jsFiddle:
var storeItems = [{
title: "Dog"
}, {
title: "Cat"
}, {
title: "Bird"
}];
var foods = document.getElementById('foods');
foods.addEventListener('click', function(e) {
var index = e.target.getAttribute('value');
storeItems.splice(index, 1);
// re-display the records from storeItems.
updateView();
});
function updateView() {
var output = "";
for (var i = 0; i < storeItems.length; i++) {
output += "<a href='#' class='item' value='" + i + "'>" + storeItems[i].title + " " + "\n" + "</a>";
}
document.getElementById('foods').innerHTML = output;
}
updateView();
HTML:
<div id='foods'></div>
This effectively takes the onclick event off of the anchor tag (you could have them on any type of tag at this point) and I also reused your updateView code in the Listener so that it only needs maintained in one location.

Get variable from loop

I have a loop which is creating table:
for(m=1; m<7; m++){
document.getElementById('content').innerHTML +=
('<tr>' +
'<td>' + m + '</td>' +
'<td><input type="checkbox" id="switch'+m+'"><label class="switch" for="switch'+m+'">Button ' + m + '</label></td>' +
'</tr>')
}
In every row in second TD is button which must be assigned to every row. Each button has his own row. I want to alert m from the first TD exactly when i click button from that row. I mean if i will click button is switch2 i will get alert from m "2".
Here is the button code i tried:
var buttons = "#switch" + m
$(function() {
$(buttons).button();
$(buttons).click(function(){
alert(m);
});
});
This is not working because all of the buttons alerting last value from loop = 6.
I know it is confused but i hope you uderstand. Really appreciate your help
Change it to this:
$(function() {
var localM = m;
$(buttons).button();
$(buttons).click(function(){
alert(localM);
});
});
The problem is the alert binds to the variable m not the value of m. By allocating a local variable inside the closure you capture the value of m at that point in the loop.
you can also bind event another way, for sample
$("tr > td > input[type=checkbox]").function(e){
alert(event.target.id);
//OR
alert(this.id);
});
if you can add any class attribute in element
Then this is safe
$("tr > td > input[type=checkbox].switch").function(){
alert(event.target.id);
});
There is so many ways to do this. Here's one:
<script type="text/javascript" src="http://code.jquery.com/jquery-1.11.0.min.js"></script>
<script type="text/javascript">
$(document).ready(function()
{
// Populate Form
for (var m = 1; m <= 7; m++)
{
$('#content').append('<tr>' +
'<td>' + m + '</td>' +
'<td><input type="checkbox" class="clickMe" id="switch'+m+'"><label class="switch" for="switch'+m+'">Button ' + m + '</label></td>' +
'</tr>');
}
// Handle Click
$('.clickMe').click(function()
{
alert('You clicked on : ' + $(this).attr('id')); // alerts "switchN" e.g. switch1
// or //
alert('You clicked on : ' + $(this).attr('id').replace('switch', '')); // // alerts "N" e.g. 1
});
});
</script>
<table id="content"></table>
Here's a bit of a refactor (minus the button() plugin):
var $content = $('#content');
for (var m = 1; m < 7; m++) {
$content.append(
'<tr>' +
'<td>' + m + '</td>' +
'<td>' +
'<input type="checkbox" id="switch' + m + '">' +
'<label class="switch" data-num=' + m + ' for="switch' + m +'">Button ' + m + '</label>' +
'</td>' +
'</tr>'
);
}
$('label.switch').click(function(e) {
e.preventDefault();
alert($(this).data('num'));
});
JSFIDDLE

Creating dynamic html with json taking too much time

I am working on preparing some dynamic html with jquery and json object. but the problem is that when my json object has around 1500 rows it takes ages to load.
is there a way to load the thing faster.
Some code.
$(jQuery.each(jsonObject.AvailableColumns, function (i, l) {
if (type == "manual") {
innerList1 += '<li newText="" valueFormat="' + l.ValueFormat + '" scaleID="' + l.ScaleID + '" scaleType="' + l.ScaleType + '" hasWeights="' + l.HasWeights + '" customColumnType="' + l.CustomColumnType + '" class="" id="li_' + controlId + '"><span id="span_' + controlId + '" title = "' + l.QuestionText + '">' + getDisplayString(l.QuestionText) + '</span><a class="actionLeft"></a></li>';
}
else if (type = "exportall") {
innerList2 += CreateLiWithSpans('li_' + controlId, l.QuestionText, true, false, l.ScaleID, l.ScaleType, l.HasWeights, l.CustomColumnType, l.ValueFormat);
}
controlId++;
}));
$("#itemList").html(innerlist1);
EDIT : createliwithspan method
function CreateLiWithSpans(id, html, isLeft, isAddAll, scaleID, scaleType, hasWeights, customColumnType, valueFormat, newText) {
var ancClass = isLeft ? 'actionRight' : 'actionLeft';
var liObject = "";
if (newText == null) {
newText = "";
}
if (isLeft) {
liObject = '<li newtext="' + newText + '" valueFormat="' + valueFormat + '" scaleID="' + scaleID + '" scaleType="' + scaleType + '" hasWeights="' + hasWeights + '" customColumnType="' + customColumnType + '" class="" id="' + id + '"><span id="span_' + id + '" title = "' + html + '">' + getDisplayString(html) + '</span><span style="margin:0 10px 0 20px;pagging:0"><input title = "' + (newText == "" ? html : newText) + '" type="text" id="' + id + 'displayText" value="' + (newText == "" ? html : newText) + '" /><span style="color:Red; width:100%;" id="' + id + 'displayTextError"></span></span><span style="float:left">' + CreateDropDown('ddl_' + id, valueFormat, hasWeights) + '</span><a class="' + ancClass + '"></a></li>';
}
else {
liObject = '<li newtext="' + newText + '" valueFormat="' + valueFormat + '" scaleID="' + scaleID + '" scaleType="' + scaleType + '" hasWeights="' + hasWeights + '" customColumnType="' + customColumnType + '" class="" id="' + id + '"><span id="span_' + id + '" title = "' + html + '">' + getDisplayString(html) + '</span><a class="' + ancClass + '"></a></li>';
}
return liObject;
}
You can use for loop instead of jQuery.each, that will be faster. Store the itemCount before the loop, and use that:
itemCount = jsonData.items.length;
for(var i = 0; i < itemCount; i++ ) {
...
You can also use use an array instead of string concatenation, like so:
var innerList = [];
... // inside the loop
innerList.push(CreateLiWithSpans('li_' + controlId, l.QuestionText, true, false, l.ScaleID, l.ScaleType, l.HasWeights, l.CustomColumnType, l.ValueFormat));
... // after the loop
$("#itemList").html(innerList.join(''));
This will be faster in IE, I'm not sure about other js engines.
These two methods will not make a significant difference, so you should try implementing a client side pagination from json. (Not by hiding and showing divs, by rendering only visible page into the DOM).
Instead of waiting for the loop to end to append your data, why not actively append the data as you process it. This will allow the user to get immediate feedback instead of waiting for the whole thing to process. Other than this, I'd stick with my original comment to page the data.
$(jQuery.each(jsonObject.AvailableColumns, function (i, l) {
if (type == "manual") {
$("#itemList").append( '<li newText="" valueFormat="' + l.ValueFormat + '" scaleID="' + l.ScaleID + '" scaleType="' + l.ScaleType + '" hasWeights="' + l.HasWeights + '" customColumnType="' + l.CustomColumnType + '" class="" id="li_' + controlId + '"><span id="span_' + controlId + '" title = "' + l.QuestionText + '">' + getDisplayString(l.QuestionText) + '</span><a class="actionLeft"></a></li>');
}
else if (type = "exportall") {
$("#itemList2").append(CreateLiWithSpans('li_' + controlId, l.QuestionText, true, false, l.ScaleID, l.ScaleType, l.HasWeights, l.CustomColumnType, l.ValueFormat));
}
controlId++;
}));
Try replacing jQuery.each with a plain old for...in loop. Using jQuery.each adds overhead that you don't need.
Don't concatenate strings inside your loop. Instead, .push them onto an array variable and use .join('') to build the string all at once at the end.
You may need to eliminate CreateLiWithSpans as a separate function in order to fully implement (2).
Changing from using jQuery.each to a standard javascript for loop should speed it up a bit. Make sure that you save the length to a variable like this though:
for(var i = 0, len = jsonObject.AvailableColumns.length; i < len; i++){
var l = jsonObject.AvailableColumns[i];
// Continue with rest of code
}
Probably won't be a huge increase but every little helps.
Also try lowering the number of function calls you make as these have added overhead (not usually an issue, but in a large loop it can help). Unless the code is shared between functions try doing it inline and see how much that speeds it up.

Categories

Resources