Create <th> element with specific position in JavaScript - javascript

Assume I have 4 “th” elements on the page and on click of the button I need to create another “th” element but with specific position. For example if it’s 1997 it’ll be created in between 1995 and 2000 elements, and so on.
<table>
<tr>
<th>1990</th>
<th>1995</th>
<th>2000</th>
<th>2005</th>
</tr>
......
This is the code I have, but it creates new “th” at the very end.
var tblHeadObj = document.getElementById('<%=Me.GridView1.ClientID %>'); //table head
var newTH = tblHeadObj.rows[0].appendChild(document.createElement("th"))

LIVE DEMO
var doc = document,
ROW = doc.querySelectorAll("#myTable tr")[0],
BUTTON = doc.querySelector("#submit"),
INPUT = doc.querySelector("#setYear");
function isNumber(n) { // http://stackoverflow.com/questions/18082/validate-numbers-in-javascript-isnumeric
return !isNaN(parseFloat(n)) && isFinite(n);
}
function createYear(){
var VAL = parseInt(INPUT.value, 10); // GET INPUT VALUE
var TH = ROW.querySelectorAll("th");
if(isNumber(VAL)){ // MAKE SURE IT?S A NUMBER
for(var i=0; i<TH.length; i++){ // LOOP TH ELEMENTS
var y = parseInt( TH[i].innerHTML, 10 ); // GET YEAR
if(y>VAL){ // ONLY IF y>VAL
var newTH = doc.createElement("th"); // CREATE NEW TH
newTH.innerHTML = VAL; // INSERT VALUE INTO TH
ROW.insertBefore( newTH, TH[i]); // https://developer.mozilla.org/en-US/docs/Web/API/Node.insertBefore
break;
}
}
}else{
alert("PLEASE ENTER A YEAR");
}
}
BUTTON.addEventListener('click', createYear); // BUTTON CLICK

To insert html after the nth element using jquery:
$("th:eq(1)").after("<th>1997</th>");
...where 1 is your nth element.

check this out. you could use insertBefore()
https://developer.mozilla.org/en-US/docs/Web/API/Node.insertBefore

Related

Can't properly delete rows from a dynamically generated table using a button

I have the following code which is supposed to generate rows in a table where each row has its own content and delete button.
<!DOCTYPE html>
<html>
<head>
<title>table</title>
</head>
<body>
<input id="inputText">
<button onclick = "addRow()">Add text</button>
<table id = "table">
</table>
<script>
function addRow(){
var newRow = document.createElement("tr");
var col1 = document.createElement("td");
var col2 = document.createElement("td");
newRow.appendChild(col1);
newRow.appendChild(col2);
var button = document.createElement("button");
button.innerHTML = "delete";
button.onclick = function () {
var index = this.parentNode.parentNode.rowIndex;
document.getElementById("table").deleteRow(index);
}
col1.appendChild(button);
var enteredText = document.getElementById("inputText").value;
col2.innerHTML = enteredText;
document.getElementById("table").appendChild(newRow);
}
</script>
</body>
</html>
The problem is that no matter which delete button I press, it deletes the last row.
I tried using console.log(this.parentNode.parentNode) to see if it returns the right <tr> object, and it indeed does. But for some reason, the attribute rowIndex is -1 no matter what button is pressed; hence only the last row is deleted. Does it mean that each dynamically generated <tr> doesn't know its row index?
You can use HTMLTableElement.insertRow() function instead.
var newRow = document.getElementById("table").insertRow();
// newRow.rowIndex will return you the proper index
Here is a working fiddle
Update
It was a bug in the Webkit layout engine, (that moved to the forked Blink engine as well). This is why it works well in Firefox but not in earlier versions of Chrome (Blink) or Safari (Webkit).
The bug report is here, it's fixed now.
There are numerous way to achieve what you require. Here is another such example that is based on the code that you posted. Hopefully it will give you some further ideas.
(function() {
// create references to static elements, no need to search for them each time
var inputText = document.getElementById("inputText"),
butAdd = document.getElementById("butAdd"),
table = document.getElementById("table");
// a generic function for finding the first parent node, starting at the given node and
// of a given tag type. Retuns document if not found.
function findParent(startNode, tagName) {
var currentNode,
searchTag;
// check we were provided with a node otherwise set the return to document
if (startNode && startNode.nodeType) {
currentNode = startNode;
} else {
currentNode = document;
}
// check we were provided with a string to compare against the tagName of the nodes
if (typeof tagName === 'string') {
searchTag = tagName.toLowerCase();
} else {
currentNode = document;
}
// Keep searching until we find a parent with a mathing tagName or until we get to document
while (currentNode !== document && currentNode.tagName.toLowerCase() !== searchTag) {
currentNode = currentNode.parentNode;
}
// return the match or document
return currentNode;
}
// for deleting the current row in which delete was clicked
function deleteRow(e) {
// find the parent with the matching tagName
var parentTr = findParent(e.target, 'tr');
// did we find it?
if (parentTr !== document) {
// remove it
parentTr.parentNode.removeChild(parentTr);
}
}
// for adding a row to the end of the table
function addRow() {
// create the required elements
var newRow = document.createElement("tr"),
col1 = document.createElement("td"),
col2 = document.createElement("td"),
button = document.createElement("button");
// add some text to the new button
button.appendChild(document.createTextNode("delete"));
// add a click event listener to the delete button
button.addEventListener('click', deleteRow, false);
// append all the required elements
col1.appendChild(button);
col2.appendChild(document.createTextNode(inputText.value));
newRow.appendChild(col1);
newRow.appendChild(col2);
// finally append all the elements to the document
table.appendChild(newRow);
}
// add click event listener to the static Add text button
butAdd.addEventListener('click', addRow, false);
}());
<input id="inputText">
<button id="butAdd">Add text</button>
<table id="table"></table>

How to change only the *selected* text to uppercase, not the entire paragraph in which the selection exists

In Google docs, this function changes the selected text to black
function selectedFontColorBlack() {
// DocumentApp.getUi().alert('selectedFontColorBlack');
var sel = DocumentApp.getActiveDocument().getSelection();
var elements = sel.getRangeElements();
for (var i = 0; i < elements.length; i++) {
var element = elements[i];
// Only modify elements that can be edited as text; skip images and other non-text elements.
if(element.getElement().editAsText) {
var text = element.getElement().editAsText();
// Bold the selected part of the element, or the full element if it's completely selected.
if (element.isPartial()) {
text.setForegroundColor(element.getStartOffset(), element.getEndOffsetInclusive(), "#000000");
} else {
text.setForegroundColor("#000000");
}
}
}
}
This function changes the entire paragraph in which the cursor (or selection) exists to uppercase:
function uppercaseSelected() {
// DocumentApp.getUi().alert('uppercaseSelected');
var sel = DocumentApp.getActiveDocument().getSelection();
var elements = sel.getRangeElements();
for (var i = 0; i < elements.length; i++) {
var element = elements[i];
// Only modify elements that can be edited as text; skip images and other non-text elements.
if(element.getElement().editAsText) {
var text = element.getElement().editAsText();
text.setText(text.getText().toUpperCase());
}
}
}
I don't see any corresponding setText function that works on the selection's "offset", as does the setForegroundColor(Integer,Integer,String). (Both of these functions are in class Text.)
How can I change the actually selected text to uppercase, and not the entire paragraph in which the selection exists?
Thank you.
Try using the setAttributes(startOffset, endOffsetInclusive, attributes) method. Check out the documentation
[EDIT: my bad, i don't think that'll do it. I'll look a bit longer tho]
The gem hidden in the post that #Mogsdad is referring to is this: var selectedText = elementText.substring(startOffset,endOffset+1);. to be little more verbose on how this is used: you can use the string method substring on objects such as DocumentApp.getActiveDocument().getSelection().getSelectedElements()[i].getElement().editAsText().getText()
so, essentially, grab that substring, convert it to uppercase, delete the text in the range (selectedElement.getstartOffset,selectedElement.endOffsetInclusive) and insert the bolded text at selectedElement.getstartOffset
Tada! check it out:
function uppercaseSelected() {
// Try to get the current selection in the document. If this fails (e.g.,
// because nothing is selected), show an alert and exit the function.
var selection = DocumentApp.getActiveDocument().getSelection();
if (!selection) {
DocumentApp.getUi().alert('Cannot find a selection in the document.');
return;
}
var selectedElements = selection.getSelectedElements();
for (var i = 0; i < selectedElements.length; ++i) {
var selectedElement = selectedElements[i];
// Only modify elements that can be edited as text; skip images and other
// non-text elements.
var text = selectedElement.getElement().editAsText();
// Change the background color of the selected part of the element, or the
// full element if it's completely selected.
if (selectedElement.isPartial()) {
var bitoftext = text.getText().substring(selectedElement.getStartOffset(), selectedElement.getEndOffsetInclusive() + 1);
text.deleteText(selectedElement.getStartOffset(), selectedElement.getEndOffsetInclusive());
text.insertText(selectedElement.getStartOffset(), bitoftext.toUpperCase());
} else {
text.setText(text.getText().toUpperCase());
}
}
}
Started with the code from Google App script Document App get selected lines or words?, and made this almost a year ago. I'm happy if it helps you.
The "trick" is that you need to delete the original text and insert the converted text.
This script produces a menu with options for UPPER, lower and Title Case. Because of the delete / insert, handling more than one paragraph needs special attention. I've left that to you!
function onOpen() {
DocumentApp.getUi().createMenu('Change Case')
.addItem("UPPER CASE", 'toUpperCase' )
.addItem("lower case", 'toLowerCase' )
.addItem("Title Case", 'toTitleCase' )
.addToUi();
}
function toUpperCase() {
_changeCase(_toUpperCase);
}
function toLowerCase() {
_changeCase(_toLowerCase);
}
function toTitleCase() {
_changeCase(_toTitleCase);
}
function _changeCase(newCase) {
var doc = DocumentApp.getActiveDocument();
var selection = doc.getSelection();
var ui = DocumentApp.getUi();
var report = ""; // Assume success
if (!selection) {
report = "Select text to be modified.";
}
else {
var elements = selection.getSelectedElements();
if (elements.length > 1) {
report = "Select text in one paragraph only.";
}
else {
var element = elements[0].getElement();
var startOffset = elements[0].getStartOffset(); // -1 if whole element
var endOffset = elements[0].getEndOffsetInclusive(); // -1 if whole element
var elementText = element.asText().getText(); // All text from element
// Is only part of the element selected?
if (elements[0].isPartial())
var selectedText = elementText.substring(startOffset,endOffset+1);
else
selectedText = elementText;
// Google Doc UI "word selection" (double click)
// selects trailing spaces - trim them
selectedText = selectedText.trim();
endOffset = startOffset + selectedText.length - 1;
// Convert case of selected text.
var convertedText = newCase(selectedText);
element.deleteText(startOffset, endOffset);
element.insertText(startOffset, convertedText);
}
}
if (report !== '') ui.alert( report );
}
function _toUpperCase(str) {
return str.toUpperCase();
}
function _toLowerCase(str) {
return str.toLowerCase();
}
// https://stackoverflow.com/a/196991/1677912
function _toTitleCase(str)
{
return str.replace(/\w\S*/g, function(txt){return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase();});
}

How can I reference an element after I have appended it using javascript not jquery

I am doing some basic javascripting and am creating a 3 column table created by javascript sourced from an xml. The table is created by appending all the data in rows via javascript.
The first column has an input checkbox, created via javascript, that if ticked fetches a price from the third column on that row and adds all the prices of the rows selected to give a price total.
The problem I am having is I don't seem to be able to reference the appended information to obtain the information in the related price column (third column).
I have attached both the function I am using to create the table which is working and the function I am using to try and add it up which isnt working.
I found the following two articles Getting access to a jquery element that was just appended to the DOM and How do I refer to an appended item in jQuery? but I am using only javascript not jquery and would like a javascript only solution if possible.
Can you help? - its just the calculateBill function that isn't working as expected.
Thank you in advance
function addSection() {
var section = xmlDoc.getElementsByTagName("section");
for (i=0; i < section.length; i++) {
var sectionName = section[i].getAttribute("name");
var td = document.createElement("td");
td.setAttribute("colspan", "3");
td.setAttribute("class","level");
td.appendChild(document.createTextNode(sectionName));
var tr = document.createElement("tr");
tr.appendChild(td);
tbody.appendChild(tr);
var server = section.item(i).getElementsByTagName("server");
for (j=0; j < server.length; j++) {
var createTR = document.createElement("tr");
var createTD = document.createElement("td");
var createInput = document.createElement("input");
createInput.setAttribute("type", "checkbox");
createInput.setAttribute("id", "checkInput");
createTD.appendChild(createInput);
createTR.appendChild(createTD);
var item = server[j].getElementsByTagName("item")[0].innerHTML;
var createTD2 = document.createElement("td");
var createText = document.createTextNode(item);
createTD2.appendChild(createText);
createTR.appendChild(createTD2);
var price = server[j].getElementsByTagName("price")[0].innerHTML;
var createTD3 = document.createElement("td");
var createText2 = document.createTextNode("£" + price);
createTD3.appendChild(createText2);
createTR.appendChild(createTD3);
tbody.appendChild(createTR);
}
}
}
onload = addSection();
function calculateBill() {
var finalBill = 0.0;
var checkBox = document.getElementById("checkInput");
for (i=0; i < checkBox.length; i++) {
if (checkBox[i].checked) {
var parentTR = checkBox[i].parentNode;
var priceTD = parentTR.getElementsByTagName('td')[2];
finalBill += parseFloat(priceTD.firstChild.data);
}
}
return Math.round(finalBill*100.0)/100.0;
}
var button = document.getElementById("button");
button.onClick=document.forms[0].textTotal.value=calculateBill();
When you do x.appendChild(y), y is the DOM node that you are appending. You can reference it via javascript either before or after appending it. You don't have to find it again if you just hang on to the DOM reference.
So, in this piece of code:
var createInput = document.createElement("input");
createInput.setAttribute("type", "checkbox");
createInput.setAttribute("id", "checkInput");
createTD.appendChild(createInput);
createInput is the input element. You can reference it with javascript at any time, either before or after you've inserted it in the DOM.
In this piece of code:
var price = server[j].getElementsByTagName("price")[0].innerHTML;
var createTD3 = document.createElement("td");
var createText2 = document.createTextNode("£" + price);
createTD3.appendChild(createText2);
createTR.appendChild(createTD3);
tbody.appendChild(createTR);
You're creating a <td> element and putting a price into it. createTD3 is that particular <td> element.
If you want to be able to find that element sometime in the future long after the block of code has run, then I'd suggest you give it an identifying id or class name such that you can use some sort of DOM query to find it again. For example, you could put a class name on it "price" and then be able to find it again later:
var price = server[j].getElementsByTagName("price")[0].innerHTML;
var createTD3 = document.createElement("td");
createTD3.className = "price";
var createText2 = document.createTextNode("£" + price);
createTD3.appendChild(createText2);
createTR.appendChild(createTD3);
tbody.appendChild(createTR);
Then, you could find all the price elements again with:
tbody.querySelectorAll(".price");
Assuming tbody is the table where you put all these elements (since that's what you're using in your enclosed code). If the table itself had an id on it like id="mainData", then you could simply use
document.querySelectorAll("#mainData .price")
to get all the price elements.
FYI, here's a handy function that goes up the DOM tree starting from any node and finds the first node that is of a particular tag type:
function findParent(node, tag) {
tag = tag.upperCase();
while (node && node.tagName !== tag) {
node = node.parentNode;
}
return node;
}
// example usage:
var row, priceElement, price;
var checkboxes = document.querySelectorAll(".checkInput");
for (var i = 0; i < checkboxes.length; i++) {
// go up to the parent chain to find out row
row = findParent(checkboxes[i], "tr");
// look in this row for the price
priceElement = row.querySelectorAll(".price")[0];
// parse the price out of the price element
price = parseFloat(priceElement.innerHTML.replace(/^[^\d\.]+/, ""));
// do something here with the price
}

How to permute 2 cells of a table

I'd like to do a small function that would permute 2 cells of a table with jQuery (or PHP/Ajax).
Let's say I have the following table:
<table class="table">
<tr>
<td class="btn" data-cellN="1">
01
</td>
<td class="btn" data-cellN="2">
02
</td>
</tr>
<tr>
<td class="btn" data-cellN="3">
05
</td>
<td class="btn" data-cellN="4">
06
</td>
</tr>
</table>
How to select 2 cells and permute them?
EDIT:
I made my way through the function thanks to your advice, nevertheless. It is working the first time bug I got a weird bug coming from the c1 c2 c3 variables, I don't know why,
could anyone help me to finish my function please?
Here is my Javascript: (it is wrapped in a doc ready)
var nbbuttonclicked=0; // to trigger the movecell function after the second button was clicked
var count=0; //Number of tinme we moved a cell
var table = {
c1:null,
c2:null,
c3:null,
check: function(){
$('td').on('click', function(){ //When the user click on a button we verify if he already clicked on this button
if( $(this).hasClass('btn-info') ) {
//If yes, then remove the class and variable c1
$(this).removeClass('btn-info');
table.c1=0;
nbbuttonclicked--;
}else{
//if no, then add a class to show him it is clicked and remember the value of the cell
$(this).addClass('btn-info');
if( typeof table.c1 === 'undefined' || table.c1===null) {
table.c1 = $(this);
console.log('c1:'+table.c1.html());
}else{
table.c2 = $(this);
console.log('c2:'+table.c2.html());
}
nbbuttonclicked++;
if( nbbuttonclicked==2 ) {
table.movecell(table.c1,table.c2); // we trigger the function to permute the values
}
}
});
},
movecell: function(c1, c2){
//We reset that variable for the next move
nbbuttonclicked=0;
//we move the cells
table.c3=c1.html();
c1.html(c2.html());
c2.html(table.c3)
c1.removeClass('btn-info');
c2.removeClass('btn-info');
table.c1=table.c2=table.c3=c1=c2=null;
},
// movecell: function(c1, c2){
// We check if the cells.html() are = to data-cellN. If yes, you won
// foreach()
// },
// var row = $('table tr:nth-child(1)')[0];
// moveCell(row, 0, 3);
};
table.check();
and here is a sample:
http://jsbin.com/exesof/2/edit
Try this code:
var cell0,
cell1,
next,
row0,
row1;
$('td').on('click', function() {
if(!cell0) {
cell0 = this;
row0 = cell0.parentNode;
return;
} else if(!cell1) {
cell1 = this;
row1 = cell1.parentNode;
// === Switch cells ===
next = cell0.nextSibling;
row1.insertBefore(cell0, cell1);
row0.insertBefore(cell1, next);
// ====================
row0 = row1 = cell0 = cell1 = next = null;
}
});
Working example you can try here: http://jsbin.com/irapeb/3/edit
Click one of the cells, than another one and see they are switched :)
This code will move the 4th td (referenced as cell[3]) on place of the first cell (cell[0]) in the first row (and the 1st becomes the 4th):
function moveCell(row, c1, c2) {
var cell = row.cells;
arr = [c1, c2].sort(),
c1 = arr[1],
c2 = arr[0];
row.insertBefore(row.insertBefore(cell[c1], cell[c2]).nextSibling, cell[c1].nextSibling);
}
var row = $('table tr:nth-child(1)')[0];
moveCell(row, 0, 3);
http://jsfiddle.net/2N2rS/3/
I wrote this function to simplify process. It uses native table methods.
Modifying the number of row (:nth-child(1)) and indexes of the table cells you can permute them as you need.
with jQuery, you can do it with:
$(document).ready(function() {
$("table.table tbody tr td:first-child").each(function(index, element) {
// this and element is the same
$(this).insertAfter($(this).next());
});
});
Assuming you don't ommited the tbody element (which is automatically added by some browser as default behaviour)
working example
If you want to do the process when clicking on the first cell, you just have to use on with click event instead of each.
$(document).ready(function() {
$("table.table tbody tr td:first-child").on('click', function(clickEvent) {
$(this).insertAfter($(this).next());
});
});
This can be done in pure javascript:
Fetch clicked sell count;
Fetch data of both cells, when they are selected;
Replace cell values with the opposite ones;
Store new values in DB via ajax call.
Now it's up to you to write the script.

How to get all elements inside "div" that starts with a known text

I have a div element in an HTML document.
I would like to extract all elements inside this div with id attributes starting with a known string (e.g. "q17_").
How can I achieve this using JavaScript ?
If needed, for simplicity, I can assume that all elements inside the div are of type input or select.
var matches = [];
var searchEles = document.getElementById("myDiv").children;
for(var i = 0; i < searchEles.length; i++) {
if(searchEles[i].tagName == 'SELECT' || searchEles.tagName == 'INPUT') {
if(searchEles[i].id.indexOf('q1_') == 0) {
matches.push(searchEles[i]);
}
}
}
Once again, I strongly suggest jQuery for such tasks:
$("#myDiv :input").hide(); // :input matches all input elements, including selects
Option 1: Likely fastest (but not supported by some browsers if used on Document or SVGElement) :
var elements = document.getElementById('parentContainer').children;
Option 2: Likely slowest :
var elements = document.getElementById('parentContainer').getElementsByTagName('*');
Option 3: Requires change to code (wrap a form instead of a div around it) :
// Since what you're doing looks like it should be in a form...
var elements = document.forms['parentContainer'].elements;
var matches = [];
for (var i = 0; i < elements.length; i++)
if (elements[i].value.indexOf('q17_') == 0)
matches.push(elements[i]);
With modern browsers, this is easy without jQuery:
document.getElementById('yourParentDiv').querySelectorAll('[id^="q17_"]');
The querySelectorAll takes a selector (as per CSS selectors) and uses it to search children of the 'yourParentDiv' element recursively. The selector uses ^= which means "starts with".
Note that all browsers released since June 2009 support this.
Presuming every new branch in your tree is a div, I have implemented this solution with 2 functions:
function fillArray(vector1,vector2){
for (var i = 0; i < vector1.length; i++){
if (vector1[i].id.indexOf('q17_') == 0)
vector2.push(vector1[i]);
if(vector1[i].tagName == 'DIV')
fillArray (document.getElementById(vector1[i].id).children,vector2);
}
}
function selectAllElementsInsideDiv(divId){
var matches = new Array();
var searchEles = document.getElementById(divId).children;
fillArray(searchEles,matches);
return matches;
}
Now presuming your div's id is 'myDiv', all you have to do is create an array element and set its value to the function's return:
var ElementsInsideMyDiv = new Array();
ElementsInsideMyDiv = selectAllElementsInsideDiv('myDiv')
I have tested it and it worked for me. I hope it helps you.
var $list = $('#divname input[id^="q17_"]'); // get all input controls with id q17_
// once you have $list you can do whatever you want
var ControlCnt = $list.length;
// Now loop through list of controls
$list.each( function() {
var id = $(this).prop("id"); // get id
var cbx = '';
if ($(this).is(':checkbox') || $(this).is(':radio')) {
// Need to see if this control is checked
}
else {
// Nope, not a checked control - so do something else
}
});
i have tested a sample and i would like to share this sample and i am sure it's quite help full.
I have done all thing in body, first creating an structure there on click of button you will call a
function selectallelement(); on mouse click which will pass the id of that div about which you want to know the childrens.
I have given alerts here on different level so u can test where r u now in the coding .
<body>
<h1>javascript to count the number of children of given child</h1>
<div id="count">
<span>a</span>
<span>s</span>
<span>d</span>
<span>ff</span>
<div>fsds</div>
<p>fffff</p>
</div>
<button type="button" onclick="selectallelement('count')">click</button>
<p>total element no.</p>
<p id="sho">here</p>
<script>
function selectallelement(divid)
{
alert(divid);
var ele = document.getElementById(divid).children;
var match = new Array();
var i = fillArray(ele,match);
alert(i);
document.getElementById('sho').innerHTML = i;
}
function fillArray(e1,a1)
{
alert("we are here");
for(var i =0;i<e1.length;i++)
{
if(e1[i].id.indexOf('count') == 0)
a1.push(e1[i]);
}
return i;
}
</script>
</body>
USE THIS I AM SURE U WILL GET YOUR ANSWER ...THANKS

Categories