Picking out specific individual controls out in javascript - javascript

So what I am trying to do here is copy an html table out of clubMemebers. Paste that table into two new places, and on the second "new" table called tblBody; set its first rows visibility to hidden, change the text in the cells to '' (nothing) and make its height = 0px... basically.
The problem is probably quite an obvious one to most people... they both are linked to a single table so a change to one will make a change to them all...
How can I separate these tables to do what I need to do? I've tried to search but all I came up with is copying tables to clipboard or excel.
Here bellow is the html and the javascript I am using.
<div id="DivHeaderRow"></div>
<div class="gridDiv" id="gridDiv" onscroll="OnScrollDiv(this)"></div>
<div id="DivFooterRow"></div>
<table style="width: 100%;" class="MemberTbl" runat="server" id="clubMembers" >
<tr class="Header" style="position:fixed;"></tr>
</table>
and the javascript:
function MakeStaticHeader(gridId, height, width, headerHeight, isFooter) {
var tblHead = document.getElementById(gridId);
var tblBody = document.getElementById(gridId);
if (tblHead) {
var DivHR = document.getElementById('DivHeaderRow');
var DivMC = document.getElementById('gridDiv');
var DivFR = document.getElementById('DivFooterRow');
//*** Set divheaderRow Properties ****
DivHR.style.height = headerHeight + 'px';
DivHR.style.position = 'relative';
DivHR.style.top = '10px';
DivHR.style.zIndex = '10';
DivHR.style.verticalAlign = 'top';
DivHR.style.overflow = 'hidden';
//*** Set divMainContent Properties ****
DivMC.style.position = 'relative';
DivMC.style.zIndex = '1';
//*** Set divFooterRow Properties ****
DivFR.style.width = (parseInt(width) - 16) + 'px';
DivFR.style.position = 'relative';
DivFR.style.top = -headerHeight + 'px';
DivFR.style.verticalAlign = 'top';
DivFR.style.paddingtop = '2px';
DivFR.style.overflow = 'hidden';
if (isFooter) {
var tblfr = tbl.cloneNode(true);
tblfr.removeChild(tblfr.getElementsByTagName('tbody')[0]);
var tblBody = document.createElement('tbody');
tblfr.style.width = '100%';
tblfr.cellSpacing = "0";
//*****In the case of Footer Row *******
tblBody.appendChild(tbl.rows[tbl.rows.length - 1]);
tblfr.appendChild(tblBody);
DivFR.appendChild(tblfr);
}
//****Copy Header in divHeaderRow****
var tblBodyRow = tblBody.rows[0];
tblBodyRow.style.visibilty = 'hidden';
tblBodyRow.style.height = '0px';
for(var i = 0, tblBodyRow; tblBodyCell = tblBodyRow.cells[i]; i++)
{
tblBodyCell.innerHTML = '';
}
DivHR.appendChild(tblHead.cloneNode(true));
DivMC.appendChild(tblBody.cloneNode(true));
}
}
function OnScrollDiv(Scrollablediv) {
document.getElementById('DivHeaderRow').scrollLeft = Scrollablediv.scrollLeft;
document.getElementById('DivFooterRow').scrollLeft = Scrollablediv.scrollLeft;
}
window.onload = function () {
MakeStaticHeader('clubMembers', 100, 400, 25, false)
}

Maybe your problem would be fixed changing your lines:
var tblHead = document.getElementById(gridId);
var tblBody = document.getElementById(gridId);
for:
var tblHead = document.getElementById(gridId).cloneNode(true);
var tblBody = document.getElementById(gridId).cloneNode(true);
However, maybe you could try with jquery to manipulate DOM elements... Then, with something like this could be enough (see Fiddle):
tableHtml = $('#clubMembers').html();
$('#DivHeaderRow').html(tableHtml);
$('#DivHeaderRow').find("tr").first().hide();
$('#gridDiv').html(tableHtml);

Related

Can't clone <template> to append to <div>

I create this template successfully with javascript:
I create the template in an async function:
this.createBoxes = async function() {
var row_counter = 0;
for (var i = 1; i < this.fake_data.length + 1; i++) {
var item_box = document.createElement("div");
item_box.style.flex = "0.5";
item_box.style.backgroundColor = "white";
item_box.style.display = "flex";
item_box.style.flexDirection = "column";
item_box.style.justifyContent = "flex-end";
item_box.id = "item_box_"+i;
var item_name = document.createElement("h3");
item_name.style.flex = "0.2";
item_name.style.backgroundColor = "orange";
item_name.style.alignSelf = "center";
item_name.innerText = this.fake_data[i - 1].name;
item_name.id = "item_name_"+i;
item_box.appendChild(item_name);
this_row = document.getElementsByClassName("row")[row_counter];
this_row.appendChild(item_box);
if(i % 2 == 0) {
var pool = document.getElementById("pool");
var inner_row = document.createElement("div");
inner_row.style.display = "flex";
inner_row.style.flexDirection = "row";
inner_row.style.flex = "0.5";
inner_row.style.justifyContent = "space-around";
inner_row.style.alignItems = "center";
inner_row.style.backgroundColor = "green";
inner_row.className = "row";
pool.appendChild(inner_row);
row_counter++;
}
else if(i == this.fake_data.length) {
return;
}
}
}
Then I do this:
this.createBoxes().then(function() {
var template = document.querySelector('#pool');
var clone = template.content.cloneNode(true);
document.querySelector(".app").appendChild(clone);
})
But as you can see from my screenshot, .app is empty. What am I doing wrong? I am using Cordova and I am assuming that it is able to use the template tag, I haven't been able to find anything saying I can't.
UPDATE
This happens:
When I do this:
this.createBoxes().then(function() {
var template = document.querySelector('#pool');
var clone = template.cloneNode(true);
document.querySelector(".app").appendChild(clone);
});
Using template.cloneNode successfully moves the <template> but this is obviously not what I want, I want to get the contents of the <template> and move them to .app container, not the whole <template>.
You should be cloning the template's .content instead, as demonstrated in the documentation.
var temp = document.getElementsByTagName("template")[0];
var clon = temp.content.cloneNode(true);
document.body.appendChild(clon);
Well, if cloning the node itself works, then the answer is pretty simple - just clone/append children of the template:
this.createBoxes().then(function() {
let template = document.querySelector('#pool');
let app = document.querySelector(".app");
for(let child of template.childNodes) {
let clone = child.cloneNode(true);
app.appendChild(clone);
}
});
Note that I have not tested this code - you may need to debug it as necessary.
I added a container to the template programmatically:
var pool = document.getElementById("pool");
var container = document.createElement("div");
container.style.flex = "1";
container.style.backgroundColor = "white";
container.style.display = "flex";
container.style.flexDirection = "column";
container.id = "container";
var row = document.createElement("div");
row.style.display = "flex";
row.style.flexDirection = "row";
row.style.flex = "0.5";
row.style.justifyContent = "space-around";
row.style.alignItems = "center";
row.style.backgroundColor = "green";
row.className = "row";
container.appendChild(row);
pool.appendChild(container);
Then instead of adding my content to the #pool <template>, I added it to #container, and then stored the #container node in a variable, and then imported that into .app:
var container_in_temp = document.querySelector('#pool>#container');
var targetContainer = document.querySelector('.app');
targetContainer.appendChild(document.importNode(container_in_temp, true));
So it ends up looking like this, with a container in .app which is actually kind of preferable structure wise :).

Inserting text after a certain image using javascript

In one function I have a loop that creates 10 images using the createElement();. In the other function I have another loop that contains info that I need to add text after each picture but my code adds it at the end of all 10 pictures I need them to be after every corresponding picture.
This is the function that displays the text:
function displayAlbum(json){
for (var x = 0; x<json.length;x++){
var span1 = document.createElement("span");
span1.innerText = json[x].album;
console.log(json[x].album);
var display = document.getElementById("results");
display.appendChild(span1);
}
}
I cant individually set the id of each image because i created them in js. Thanks for the help in advance and no jquery please
for (var x = 0; x<json.length;x++){
var image = document.createElement("img");
image.id = "picture";
image.width = 100;
image.height = 100;
image.src = json[x].cover;
var display = document.getElementById("results");
display.appendChild(image);
var a = document.getElementById("artist");
var y = document.getElementById("year");
var artist = document.getElementById("artist").selectedIndex;//index of value of the switch statement
var year = document.getElementById("year").selectedIndex;//index of value of the switch statement
var realYear = y[year].text;//Value of the selected text
var realArtist = a[artist].text;//Value of the selected text
var display = document.getElementById("Results");
}
This is my second loop. I want displayalbum to appear after every picture. I cannot combine them because of other complications in the code
Try to do something like that: plunker
function displayAlbum(){
for (var x = 0; x < 10 ; x++){ // change to json.length
var span1 = document.createElement("span");
span1.innerText = 'json[x].album';
span1.id = 'span'+x;
var display = document.getElementById("results");
display.appendChild(span1);
}
}
The loop where you are creating images, give a unique id to image like image.id = "picture" + x;
Then change displayAlbum() function to use corresponding image to place the span tag.
function displayAlbum(json){
for (var x = 0; x<json.length;x++){
var span1 = document.createElement("span");
span1.innerText = json[x].album;
console.log(json[x].album);
var display = document.getElementById("results");
var img = document.getElementById("picture" + x); // use unique id of img to access it
if(img.nextSibling) { // if img is not the last node in 'results'
display.insertBefore(span1, img.nextSibling);
} else { // if img is the last node in 'results'
display.appendChild(span1);
}
}
}
You can achieve your goal with single loop and using Figure and FigCaption element , specifically created for this kind of display image with its description
var json = [{cover:"https://upload.wikimedia.org/wikipedia/commons/thumb/d/da/Internet2.jpg/440px-Internet2.jpg", album:"test1"},{cover:"https://upload.wikimedia.org/wikipedia/commons/thumb/d/da/Internet2.jpg/440px-Internet2.jpg", album:"test2"}];
for (var x = 0; x<json.length;x++){
var fig = document.createElement("figure");
var figCap = document.createElement("figcaption");
figCap.innerText = json[x].album;
var image = document.createElement("img");
image.id = "picture";
image.width = 100;
image.height = 100;
image.src = json[x].cover;
var display = document.getElementById("results");
fig.appendChild(image);
fig.appendChild(figCap);
display.appendChild(fig);
}
<div id="results">
</div>

JavaScript / CSS overflow-x not stretching around floated elements

I'm trying to make a basic GUI for a JavaScript web app, that lets users use the web app on any device, without putting too much time and effort into making it too responsive. I figured I could easily use basic overflow properties for container divs, so the user can scroll to the desired button, rather than changing the layout completely for different screen resolutions.
I'm trying to make the top toolbar (File, Edit, Insert etc..) with an overflow-x set to scroll, which holds divs floated to the left. For some reason, the overflow-x does nothing, so some of the buttons are hidden. Why is this?
jsFiddle
// STYLE WINDOW
document.body.style.margin = "0px";
document.body.style.padding = "0px";
document.body.style.backgroundColor = "#66666A";
document.body.style.color = "#0099AA";
document.body.style.fontFamily = "calibri, sans-serif";
function getScrollbarWidth()
{var o = document.createElement('div');o.style.overflowY = "scroll";o.style.visibility = "none";var i = document.createElement('div');o.appendChild(i);document.body.appendChild(o);var r = o.offsetWidth-i.offsetWidth;o.parentNode.removeChild(o);return(r);}
function getScrollbarHeight()
{var o = document.createElement('div');o.style.overflowX = "scroll";o.style.visibility = "none";document.body.appendChild(o);var r = o.offsetHeight;o.parentNode.removeChild(o);return(r);}
// CREATE EDITOR TOOLBAR
toolbar = document.createElement('div');
toolbar.style.position = "fixed";
toolbar.style.top = "0px";
toolbar.style.left = "0px";
toolbar.style.width = "100%";
toolbar.style.height = 32+getScrollbarHeight()+"px";
toolbar.style.overflowX = "scroll";
toolbar.style.overflowY = "hidden";
toolbar.style.backgroundColor = "#33333A";
toolbar.buttons = {};
toolbar.addButton = function(buttonName){
var newButton = document.createElement('div');
newButton.style.width = "128px";
newButton.style.height = "16px";
newButton.style.float = "left";
newButton.style.paddingTop = "8px";
newButton.style.paddingBottom = "8px";
newButton.style.textAlign = "center";
newButton.style.fontSize = "15px";
newButton.style.color = ";DD8800";
newButton.innerHTML = buttonName;
this.buttons[buttonName] = newButton;
this.appendChild(newButton);
}
toolbar.addButton("File");
toolbar.addButton("Edit");
toolbar.addButton("Insert");
toolbar.addButton("Settings");
toolbar.addButton("Share");
toolbar.addButton("Help");
// CREATE EDITOR WINDOW SELECTOR
windowSelector = document.createElement('div');
windowSelector.style.position = "fixed";
windowSelector.style.top = 32+getScrollbarHeight()+"px";
windowSelector.style.left = "0px";
windowSelector.style.bottom = "0px";
windowSelector.style.width = 128+getScrollbarWidth()+"px";
windowSelector.style.overflowY = "scroll";
windowSelector.style.backgroundColor = "#33333A";
windowSelector.buttons = {};
windowSelector.addButton = function(buttonName,imageURL){
this.buttons[buttonName] = document.createElement('div');
this.buttons[buttonName].style.width = "128px";
this.buttons[buttonName].style.height = "64px";
this.buttons[buttonName].style.backgroundColor = "#22222A";
this.buttons[buttonName].style.borderTop = "1px solid #115588";
var buttonImage = document.createElement('div');
buttonImage.style.width = "32px";
buttonImage.style.height = "32px";
buttonImage.style.margin = "8px";
buttonImage.style.marginTop = "16px";
buttonImage.style.marginBottom = "16px";
buttonImage.style.float = "left";
buttonImage.style.backgroundImage = "url('"+imageURL+"')";
buttonImage.style.backgroundSize = "contain";
buttonImage.style.backgroundPosition = "center center";
this.buttons[buttonName].appendChild(buttonImage);
var buttonTitle = document.createElement('div');
buttonTitle.style.width = "72px";
buttonTitle.style.height = "16px";
buttonTitle.style.paddingTop = "24px";
buttonTitle.style.paddingBottom = "24px";
buttonTitle.style.paddingLeft = "8px";
buttonTitle.style.float = "left";
buttonTitle.style.color = "#77BBDD";
buttonTitle.style.fontSize = "14px";
buttonTitle.innerHTML = buttonName;
this.buttons[buttonName].appendChild(buttonTitle);
this.appendChild(this.buttons[buttonName]);
}
windowSelector.addButton("Sprites","");
windowSelector.addButton("Objects","");
windowSelector.addButton("Scripts","");
windowSelector.addButton("Rooms","");
windowSelector.addButton("Backgrounds","");
windowSelector.addButton("Sounds","");
windowSelector.addButton("Paths","");
windowSelector.addButton("Timelines","");
windowSelector.addButton("Constants","");
// CREATE APPLICATION SCRIPT
application = document.createElement('script');
document.body.appendChild(application);
document.body.appendChild(toolbar);
document.body.appendChild(windowSelector);
Elements will only overflow horizontally if they have no other choice. Usually this is a good thing, but in some cases... yeah.
floats will wrap. Instead, try using display:inline-block on the items, and white-space:nowrap on the container.
This will force the elements to overflow horizontally.

GridView Freeze Header

I am using this tutorial to freeze the header of the GridView. I did everything as explained in the tutorial but I got the following error in IE9 and I don't know why.
Error:
Line: 182
Error: Unable to get value of the property 'offsetWidth': object is
null or undefined
I defined the GridView in the Javascript code as show below:
<script type = "text/javascript">
var GridId = "<%=GridView1 %>";
var ScrollHeight = 300;
window.onload = function () {
var grid = document.getElementById(GridId);
var gridWidth = grid.offsetWidth;
var gridHeight = grid.offsetHeight;
var headerCellWidths = new Array();
for (var i = 0; i < grid.getElementsByTagName("TH").length; i++) {
headerCellWidths[i] = grid.getElementsByTagName("TH")[i].offsetWidth;
}
grid.parentNode.appendChild(document.createElement("div"));
var parentDiv = grid.parentNode;
var table = document.createElement("table");
for (i = 0; i < grid.attributes.length; i++) {
if (grid.attributes[i].specified && grid.attributes[i].name != "id") {
table.setAttribute(grid.attributes[i].name, grid.attributes[i].value);
}
}
table.style.cssText = grid.style.cssText;
table.style.width = gridWidth + "px";
table.appendChild(document.createElement("tbody"));
table.getElementsByTagName("tbody")[0].appendChild(grid.getElementsByTagName("TR")[0]);
var cells = table.getElementsByTagName("TH");
var gridRow = grid.getElementsByTagName("TR")[0];
for (var i = 0; i < cells.length; i++) {
var width;
if (headerCellWidths[i] > gridRow.getElementsByTagName("TD")[i].offsetWidth) {
width = headerCellWidths[i];
}
else {
width = gridRow.getElementsByTagName("TD")[i].offsetWidth;
}
cells[i].style.width = parseInt(width - 3) + "px";
gridRow.getElementsByTagName("TD")[i].style.width = parseInt(width - 3) + "px";
}
parentDiv.removeChild(grid);
var dummyHeader = document.createElement("div");
dummyHeader.appendChild(table);
parentDiv.appendChild(dummyHeader);
var scrollableDiv = document.createElement("div");
if(parseInt(gridHeight) > ScrollHeight){
gridWidth = parseInt(gridWidth) + 17;
}
scrollableDiv.style.cssText = "overflow:auto;height:" + ScrollHeight + "px;width:" + gridWidth + "px";
scrollableDiv.appendChild(grid);
parentDiv.appendChild(scrollableDiv);
}
</script>
So how I fix this problem?
You have written code incorrectly
Instead of
var GridId = "<%=GridView1 %>";
Change to
var GridId = "<%=GridView1.ClientID %>"; //<= Check this
When ASP.Net controls are rendered their Id gets mangled and to get the mangled on client side the notation is as shown above.
Hope this solves your problem.

Unexpected break in nested loop doesn't show up in debugger

The purpose of the code is to build a series of nested HTML using information in objects:
Here are the informational objects I created:
function branch(level,sciname,comname,parent,children){
this.level = level;
this.sciname = sciname;
this.comname = comname;
this.parent = parent;
this.children = children;}
var animalia = new branch(1,'Animalia','Animals',"",['chordata']);
var chordata = new branch(2,'Chordata','Chordates',animalia,['petromyzontida','actinopterygii']);
var actinopterygii = new branch(3,'Actinopterygii','Ray-finned Fishes',chordata,['siluriformes','scorpaeniformes','salmoniformes','percopsiformes','perciformes','osteoglossiformes','osmeriformes','lepisosteiformes','gasterosteiformes','gadiformes','esociformes','cyprinodontiformes','cypriniformes','clupeiformes','atheriniformes','anguilliformes','amiiformes','acipenseriformes']);
var petromyzontida = new branch(3,'Petromyzontida','Lampreys',chordata,['petromyzontiformes']);
And here is the script:
function CreateDiv(parent,child,z,width,height,top,left,bgcolor){
var parent_ = document.getElementById(parent);
var newdiv = document.createElement("div");
newdiv.setAttribute("id",child);
newdiv.style.zIndex = z;
newdiv.style.position = "absolute";
newdiv.style.width = width + "%";
newdiv.style.height = height + "%";
newdiv.style.top = top + "%";
newdiv.style.left = left + "%";
newdiv.style.backgroundColor = bgcolor;
parent_.appendChild(newdiv);}
function CreateTree(){
var firstdiv = document.createElement("div");
firstdiv.setAttribute("id","animalia");
document.getElementById("container1").appendChild(firstdiv);
var parent1 = "animalia";
var children1 = window[parent1].children;
var numbchildren1 = children1.length;
var rowcounter1 = 1;
var columncounter1 = 0;
for (i=0;i<numbchildren1;i++){
var child1 = children1[i];
var z1 = 2;
var columns1 = Math.ceil(Math.sqrt(numbchildren1));
var width1 = (100/columns1) - 2;
var rows1 = Math.ceil(numbchildren1/columns1);
var height1 = (100/rows1) - 2;
var top1 = rowcounter1*height1 - height1 + 1;
var left1 = columncounter1*width1 + 1;
var bgcolor1 = "#B43333";
CreateDiv(parent1,child1,z1,width1,height1,top1,left1,bgcolor1);
var numbchildren2 = window[child1].length;
if ((i/rowcounter1) == columns1){
rowcounter1 = rowcounter1 + 1;}
else {rowcounter1 = rowcounter1;}
if (columncounter1 == columns1){
columncounter1 = 1;}
else {columncounter1 = columncounter1 + 1;}
var rowcounter2 = 1;
var columncounter2 = 0;
console.log("before:" + columncounter2);
for (j=0;j<numbchildren2;j++){
console.log("after:" + columncounter2);
var child2 = children2[j];
var z2 = 3;
var columns2 = Math.ceil(Math.sqrt(numbchildren2));
var width2 = (100/columns2) - 1;
var rows2 = Math.ceil(numbchildren2/columns2);
var height2 = (100/rows2) - 1;
var top2 = rowcounter2*height2 - height2 + 1;
var left2 = columncounter2*width2 - width2 + 1;
var bgcolor2 = "#B48233";
CreateDiv(parent2,child2,z2,width2,height2,top2,left2,bgcolor2);}}}
I've run the code through a debugger dozens of times and I get no errors. Yet the script does not fully execute. I suspected an infinite loop but I fail to see why that would occur and after going over the code in great detail, I can find no real problems. I can tell where the code seems to break. There are two console.log() statements in the above code. The first console statement gets properly logged, but the second one does not. The debugger shows no errors (Firebug), but the code still fails to fully execute. Please help! And suggestions or criticism will be very welcome as I'm still learning some of the basics.
As a note: Eventually, I will add to this process to create several layers of nested elements, but wanted to get just the first couple layers right before I begin nesting things further as once I do that additional nesting should be relatively easy.
Compare
var children1 = window[parent1].children;
to
var numbchildren2 = window[child1].length;
I think the second one is missing a ".children" before the length. As Shaed, pointed out, numbchildren2 being incorrectly initialized was the most probable cause of the for loop not running, so you should have been investigating that.
I am not familiar with your syntax of window[elementID] to get an element, but I am pretty sure it does not work. Try using document.getElementById instead.
http://jsfiddle.net/M9jtt/

Categories

Resources