Create link in an html table with javascript - javascript

I am using the following code to add columns dynamically to a html table:
var tblHeadObj = window.opener.document.getElementById("maintable").tHead;
var j=0;
while(j < fname.length)
{
if(tblHeadObj != null)
{
for(var h = 0; h < tblHeadObj.rows.length; h++)
{
var newTH = window.opener.document.createElement('th');
tblHeadObj.rows[h].appendChild(newTH);
//newTH.innerHTML='[th]row:'+h+'cell:'+(tblHeadObj.rows[h].cells.length-1)
}
}
var tblBodyObj = window.opener.document.getElementById("maintable").tBodies[0];
//for(var i = 0; i < tblBodyObj.rows.length; i++) {
var newCell=tblBodyObj.rows[0].insertCell(-1);
var newCell=tblBodyObj.rows[0].insertCell(-1);
// newCell.innerHTML = (tblBodyObj.rows[0].cells.length - 1)
newCell.innerHTML= fname[j];
j++;
}
Now i want to make columns as link.How can i do that?
Thanks

As others have noted, it is quite unclear what you mean by "make columns as link". However, we as a community have become accustomed to making guesses about the real problem and providing a solution based on that assumption. As we gain experience tackling more and more unclear questions, our ESP skill become more honed.
It appears that you are creating an HTML table via DOM methods. I will assume that you want to create a link within the created tablecell and here is my suggestion:
Use the same createElement method to create any elements you need. For instance, a link (anchor) can be created with the following code:
var link = document.createElement("a");
link.setAttribute("href", "http://www.microsoft.com")
link.className = "someCSSclass";
// For IE only, you can simply set the innerText of the node.
// The below code, however, should work on all browsers.
var linkText = document.createTextNode("Click me");
link.appendChild(linkText);
// Add the link to the previously created TableCell.
newCell.appendChild(link);
Alternatively, you can also set the innerHTML of the TableCell as #Anonymous has suggested.

If you're trying to put the cell contents into an anchor, then one way is to change
newCell.innerHTML= fname[j];
to
newCell.innerHTML= ''+fname[j]+'';
where whatever is a variable holding an appropriate string.
Beware that the contents of fname[j] are all inline (eg, not tables or blocks like div, headings, forms -- but form inputs are okay) or the anchor will be closed by most browsers prematurely. If need be, you could put the anchor only around parts of the cell's contents, but the easiest way to do that would depend on what the contents are.

This are all good but I needed an image in the link so here is that code:
cell[k] = document.createElement('td');
var link = document.createElement('a');
link.setAttribute('href', "http://www.ilovethismusic.com");
link.setAttribute('target', "_blank");
var newimg = document.createElement('img');
newimg.src = "http://www.ilovethismusic.com/Views/Images/bg_header.jpg";
newimg.alt = "imageMissing";
newimg.width = "95";
newimg.height = "45";
newimg.border = "0";
link.appendChild(newimg);
cell[k].appendChild(link);

Related

Change InnerHTML based on anchor click

I'm a little new to Web Development so I was hoping someone could answer this for me.
I'm building a prototype for a "Web Messenger" similar to Facebook messenger. I have a sidebar that I populate with a UL of anchor tags when the window loads and it looks like this. Here is the code for it
var toAdd = document.createDocumentFragment();
var newUL = document.createElement('ul');
newUL.id = 'menu-content';
newUL.className = 'menu-content collapse out';
for(var i = 0; i < 5; i++){
var newLI = document.createElement('li');
var newA = document.createElement('a');
newA.id = 'chat' + i;
newA.setAttribute('href', "#");
newA.innerHTML = "Chat" + (i + 1);
newLI.appendChild(newA);
newUL.appendChild(newLI);
}
toAdd.appendChild(newUL)
document.getElementById("menu-list").appendChild(toAdd);
I also have a Div at the top of the page which will display some details about the current chat, but for the time being will simply display the name of the chat, same as on the anchor tags.
Now based on another StackOverflow post the correct way to call a JS function from an anchor tag is
var c0 = document.getElementById("chat0");
//Set code to run when the link is clicked
// by assigning a function to "onclick"
c0.onclick = function(id) {
//Change Title Name here
//Do other stuff in the future
return false;
}
However I could have 20+ chats on the sidebar at any one time, so this seems like a lot of repetitive code to write.
Is there a better way to do this?
Give your chats a general class instead example chat then attach the click event to all the chat's in the same time using .getElementsByClassName().
So you could add className just after newA.id :
newA.id = 'chat' + i;
newA.className = 'chat';
Then attach the click event :
var chats = document.getElementsByClassName('chat');
for (var i=0; i < chats.length; i++) {
chats[i].addEventListener('click', chatClick, false);
}
function chatClick(){
//chat is clicked
//The 'this' object here refer to clicked element
}
You could use .addEventListener() instead of onclick.
NOTE : You can attach the click event directly after node creation :
for(var i = 0; i < 5; i++){
var newLI = document.createElement('li');
var newA = document.createElement('a');
newA.id = 'chat' + i;
newA.setAttribute('href', "#");
newA.innerHTML = "Chat" + (i + 1);
newA.addEventListener('click', chatClick, false); //Attach click event HERE
newLI.appendChild(newA);
newUL.appendChild(newLI);
}
Hope this help.
Yap sure. You can give them all a class and after load just use a simple jQuery code to bind onclick for all of them:
$('a.className').click(function() {
// Your code here
});
Now if the a tags are added after execution of the code you just simply need to call this again or bind to those elements manually.

Formatting a href link with appendChild, setAttribute, etc

I am attempting to populate a list with href links via javascript.
Here is an example of the html I would like to create:
<li> Complete blood count</li>
Where "#modal-one" displays a pop up.
I have used the following and several other iterations to try and create this dynamically:
<script>
var listItem = [];
function createTestList() {
var tests = results.tests; //an array to tests to populate list
var i;
var j;
for (i = 0; i < tests.length ; i++ ){
listItem[i] = document.createElement("li");
var node = document.createTextNode(tests[i].name);
listItem[i].appendChild(node);
listItem[i].setAttribute("href", "#modal-one");
addOnClick(i);
//var element = document.getElementById("div1");
//element.appendChild(listItem[i]);
document.body.appendChild(listItem[i]);
console.log(listItem[i]);
};
};
function addOnClick(j) { //this is separate to handle the closure issue
listItem[j].onclick = function() {loadModal(j)};
};
</script>
However, this code (and several others) produce:
<li href='#modal-one'>Complete Blood Count</li> //note missing <a>...</a>
It appears there are several ways to achieve this, but nothing seems to work for me...
You are never actually adding in an anchor tag. You are creating a list-item (li), but you are adding an href to that list-item rather than adding an anchor node to it with that href. As such, the browser just thinks you have a list-item with an href attribute.
Consider using the following instead:
<script>
var listItem = [];
function createTestList() {
var tests = results.tests; //an array to tests to populate list
var i;
var j; // Never actually used in function. Consider omitting
for (i = 0; i < tests.length ; i++ ){
// create the list item
listItem[i] = document.createElement("li");
// Create the anchor with text
var anchor = document.createElement("a");
var node = document.createTextNode(tests[i].name);
anchor.appendChild(node);
anchor.setAttribute("href", "#modal-one");
// Set the onclick action
addOnClick(i, anchor);
// Add the anchor to the page
listItem[i].appendChild(anchor);
document.body.appendChild(listItem[i]);
console.log(listItem[i]);
};
};
// Modified "addOnClick" to include the anchor that needs the onclick
function addOnClick(j, anch) { //this is separate to handle the closure issue
anch.onclick = function() {loadModal(j)};
};
</script>
A couple things to note:
I have modified your addOnClick() function because it is the anchor element that needs the onclick, not the list item.
I have added in the creation of an anchor element rather than simply creating a list item and adding the href to that.
I do not see creating a element, change code to:
var aNode=document.createElement("a");
aNode.innerText=tests[i].name;
aNode.setAttribute("href", "#modal-one");
listItem[i].appendChild(aNode);
You can change also click method, to use it on a not on li
function addOnClick(j) {
listItem[j].querySelector("a").addEventListener("click",function(e) {
e.preventDefault();//this prevent for going to hash in href
loadModal(j);
});
};
Okay. I missed the anchor tag. My bad...
Spencer's answer came close, but I had to make few changes to get it work in my instance.
The final working code (and honestly I am not sure why it works) is:
<script>
var listItem = [];
function createTestList() {
var tests = results.tests;
var i;
//var j;
for (i = 0; i < tests.length ; i++ ){
// create the list item
listItem[i] = document.createElement("li");
// Create the anchor with text
var anchor = document.createElement("a");
anchor.setAttribute("href", "#modal-one");
var node = document.createTextNode(tests[i].name);
anchor.appendChild(node);
// Set the onclick action
addOnClick(i);
// Add the anchor to the page
listItem[i].appendChild(anchor);
document.getElementById("demo").appendChild(listItem[i]); //added the list to a separate <div> rather than body. It works fine like this.
console.log(listItem[i]);
};
};
function addOnClick(j) { //this is separate to handle the closure issue
//didn't need the additional code beyond this
listItem[j].onclick = function() {loadModal(j)};
};
</script>
Thanks to all and Spencer thanks for the thoroughly commented code. It helps!!!

Javascript string.slice() with negative values

I am trying to hide or show divs based on the title of the page. This is only required because I can't figure out a better way of passing a value into the page.
Here's the current code in the HTML file:
function toggle(divId) {
var divArray = document.getElementsByTagName("div");
for(i = 0; i < divArray.length; i++){
if(divArray[i].id == divId){
if(divArray[i].style.display != 'none'){
divArray[i].style.display = 'none';
}else{
divArray[i].style.display = '';
}
}
}
}
function togglePayLink() {
var h1Array = document.getElementsByTagName("h1");
for(i = 0; i < h1Array.length; i++){
if(h1Array[i].id == 'Title'){
var title = h1Array[i].innerHTML;
title = title.slice(1);
title = title.slice(-4);
toggle('descr'+ title);
}
}
}
Also in the HTML file is a header with the page title. The %%GLOBAL_PageTitle%% is replaced in server side code that I don't have access to. However, the values will be "$100 Fee" (with different numbers).
<h1 id="Title" class="TitleHeading">%%GLOBAL_PageTitle%%</h1>
Finally, I have a set of hidden divs with id's in the format descr + a number, so if the page title is "$100 Fee" I want to show the div with the id "descr100".
<div id="descr100" style="display:none;width: 75%;"></div>
When the script above runs, I get no error (I'm using chrome's console), but the div does not show. I know the toggle function works because it was previously being used with only a single div on the page that had to be toggled. I wrote the togglePayLink function, which I assume is the issue, but I have no idea how to debug this. I was wondering if the dollar sign in the title could be causing issues, but I would think I would get an error if that were the case.
EDIT: Changed the togglePayLink function to use var instead of string, but I'm getting a typeError when slice() is called.
Going forward, you should probably just assign a unique class to the page using %%GLOBAL_PageTitle%%. This way you can show/hide elements using CSS.
<div class="page %%GLOBAL_PageTitle%%">
For pages that BigCommerce doesn't give access to the HTML of the h1 for each individual page (ex. Web Pages, Account, Cart), I usually run this script on page load to strip the page title of spaces and other characters, and assign a specific class to the page element.
var catName = $('.TitleHeading').text();
var catName = catName.replace(/ /g, '');
var catName = catName.replace(/'/g, '');
var catName = catName.replace(/&/g, '');
var catName = $.trim(catName);
$('.page').addClass(''+catName+'');
The way your doing it seems a bit over the top, but if it was setup this way by someone else, I understand.
The problem is here:
String title = h1Array[i].innerHTML;
In Javascript, all variables are set with var (except for functions, which can be set other ways). So it would be:
var title = h1Array[i].innerHTML;
Additionally, you probably have to define it outside the for loop, in which case you would omit the "var" when you are setting it in the for loop:
<script language="javascript">
var title;
function togglePayLink() {
var h1Array = document.getElementsByTagName("h1");
for(i = 0; i < h1Array.length; i++){
if(h1Array[i].id == 'Title'){
title = h1Array[i].innerHTML;
title = title.slice(1);
title = title.slice(-4);
toggle('descr'+ title);
}
}
}
</script>
Edit: If you only use it in the for loop, but use it in different iterations, then I'm not sure if it can be defined locally. I'd still define it globally, though.
title.slice(-4) was giving me the last four digits of the string instead of everything before the last four digits like I thought it would. toggling the non-existent 'descrFee' div was not doing anything.

Append multiple images to divs using javascript only

I created a small script that counts images that I uploaded/inserted to my html source code. After I inserted images script creates div containers for those images. If I gave three images, then script will create three divs with class name etc. I have css rule with that class name. This was create before any images were in that container. Everything works but I just can't append those newly images to newly created divs. Is there a way using JavaScript only?
Here is a code:
if (document.getElementsByClassName("Multimedia")[0].getElementsByTagName("IMG")) {
total_number_of_images = document.getElementsByClassName("Multimedia")[0].getElementsByTagName("IMG").length;
for (i = 0; i < total_number_of_images; i = i + 1) {
document.getElementsByTagName("IMG")[i].className = "Image_clip";
child = document.getElementsByTagName("IMG")[i];
image_container = document.createElement("DIV");
image_container.className = "Image_container_div";
document.getElementsByClassName("Multimedia")[0].appendChild(image_container);
document.getElementsByTagName("IMG")[i].style.opacity = "0.8";
}
}
I tried somthenig like this:
image_container.appendChild(child);
But then I can get only two images into container... my third is out and also without className. Without this code, I get className for every image
You should cache the reference to elements rather than querying DOM in loops.
If I understood correctly, Your code should look something like the following for wrapping each image in a container <div>:
var container = document.getElementsByClassName("multimedia")[0];
// if there is only one match, use an id instead ------------^ ?
var images = container.getElementsByTagName("img");
for (var i = 0; i < images.length; i++) {
var img = images[i];
img.className = "imageClip";
img.style.opacity = "0.8"; // Why not define this in imageClip class ..?
imageContainer = document.createElement("div");
imageContainer.className = "imageContainer";
imageContainer.appendChild(img);
container.appendChild(imageContainer);
}
This I get on Yahoo answer. Posted by YaYox: http://jsfiddle.net/ffxad4bq/4
function myFunction() {
var multimedia = document.getElementsByClassName("Multimedia")[0]
var imgs = multimedia.getElementsByTagName("IMG");
for (var i = 0; i < imgs.length; i++) {
imgs[0].className = "Image_clip";
imgs[0].style.opacity = "0.3";
multimedia.innerHTML += '<div class="Image_container_div">'+imgs[0].outerHTML+'</div>';
imgs[0].remove()
}
}
I realized what was the problem. I shouldn't itaret through images. Just leave it on zero because, when loops start, code append one image at a time. When second loop starts I don't have any more 3 images, but two, that is why one image always stays out because loop goes three times.

injecting arbitrary HTML string into document (javascript) - updated

Update: I just narrowed my problem to this:
Why doesn't this work:
var tmp = document.createElement('tbody');
tmp.innerHTML="<tr><td>hello</td></tr>";
tmp is getting the string hello. the tr and td html is lost (on FireFox).
Why is that? and how can I make such html injection work?
Original question:
I need to inject arbitrary HTML after a arbitrary element in arbitrary HTML documents.
I came across this method (inject the html string into dynamically generated div, get its firstchild element and insert it in the right place):
var tmp = document.createElement('div');
tmp.innerHTML = _injected_html;
var new_w = tmp.firstChild;
var parent = insertion_point.parentNode;
parent.insertBefore(new_w, insertion_point.nextSibling);
The problem is that this does not work when trying to inject table elements.
if the injected html is for example
"<tr> <td> table data </td> </tr>"
The _tmp.innerHTML = _injected_html; would not accept it (adding tr under div element).
Any idea how to make this work for any tag?
Are you testing in IE by any chance? Most likely it does work in other browsers.
Here's why
edit: Wait, you're inserting something into the table that looks like <div><tr><td>... that's not going to work. Why don't you replace the document.createElement('div') by document.createElement('tr'), and remove the <tr> tags from the _injected_html?
Something like this (tested in Firefox):
<script>
var i = 3;
function f() {
var table = document.getElementById('someTable');
var children = table.children[0].children;
var after = children[Math.round(Math.random() * (children.length - 1))];
var html = "<td>" + i++ + "</td>";
g(html, after);
}
function g(_injected_html, insertion_point) {
var tmp = document.createElement('tr');
tmp.innerHTML = _injected_html;
var new_w = tmp.firstChild;
var parent = insertion_point.parentNode;
parent.insertBefore(new_w, insertion_point.nextSibling);
}
</script>
<table id="someTable" onclick="f();">
<tr><td>1</td></tr>
<tr><td>2</td></tr>
</table>
The second line of f() is a little awkward, but it gets the first child of the table (which is a <tbody>, and then its children (the actual <tr>s).
<div><td><lol/>
..isn't valid HTML! Containers are required for table rows/cols/heads, list items, definition lists and so on. Could you somehow validate the HTML for proper containers before injecting it?
The following javascript will allow you to inject HTML/etc into the local page:
var example = "<p>test</p>"
document.body.appendChild(example);
That said, you will have to customize the code depending on what you are inserting.
For a table, you must insert tr's into tbody. When you write html
<table><tr><td>abc</td></tr></table>
IE, FF, Chrome, Safari at least (don't know about others directly) will modify this to be:
<table><tbody><tr><td>abc</td></tr></tbody></table>
Therefore, something like:
var tmp = document.createElement('tr');
tmp.innerHTML = "<td>def</td>";
var new_w = tmp.firstChild;
var parent = insertion_point.parentNode;
parent.insertBefore(new_w, insertion_point.nextSibling);
if insertion_point is a tr tag.
But honestly, with Jquery there are more elegant ways of going about this as christina toma notes.

Categories

Resources