I'm kinda new to scripting and all and just wanted to know if anyone could help me edit my code to hide the whole table from the start and then just display the rows that match the keyword.
Right now what the code does is:
You enter a keyword in an inputbox
The script searches through a table looking for rows matching the keyword.
Hide all other rows.
But i would like it to work another way, but don't really know how to.
What i would like it to do is:
Display the inputbox only on the page.(Table is hidden)
Display the results that match the keyword without displaying the whole table.
Code:
var TableSearch = function(searchBoxId, dataTableId, options) {
this.searchBox = document.querySelector('#' + searchBoxId);
this.dataTable = document.querySelector('#' + dataTableId);
this.options = options;
}
TableSearch.prototype = {
init: function(searchBoxId, dataTableId, options) {
// defaults options
var settings = {
firstRowHeader: true,
highlightCss: "style='background-color:yellow'",
noResultsText: null
};
if (this.options) {
for (var key in settings) {
// Update settings if valid option and value was supplied.
if (this.options.hasOwnProperty(key) && (this.options[key] != null && this.options[key].toString() != '')) {
if (key == 'highlightCss') {
settings[key] = "class='" + this.options[key] + "'";
continue;
}
settings[key] = this.options[key];
}
}
}
this.options = settings;
this.searchBox.addEventListener('keyup', this.search.bind(this), false);
},
search: function(e) {
if(e.keyCode == 27) {
this.searchBox.value = ''; // Clear search on Esc
}
this.toggleNoResult('remove');
var keyword = this.escapeSpecialChars(this.searchBox.value);
var textSearchRegex = new RegExp(keyword, "ig"); // case in-sensitive
var rowDisplay, rowObj, rowHtml, match;
var firstRowIndex = (this.options.firstRowHeader == true) ? 1 : 0;
for (var rowIndex = firstRowIndex; rowIndex < this.dataTable.rows.length; rowIndex++) {
rowDisplay = '';
rowObj = this.dataTable.rows.item(rowIndex);
rowHtml = rowObj.innerHTML.replace(/<mark[^/>]*>/g,'').replace(/<\/mark>/g,''); // remove previous highlighting
if (keyword == '')
rowDisplay = 'table-row';
else {
match = rowHtml.replace(/<[^>]*>/g, '').match(textSearchRegex); // strip html tags and search for keyword
if(match) {
// Get unique matches: http://stackoverflow.com/a/21292834/1440057
match = match.sort().filter(function(element, index, array) { return index == array.indexOf(element); });
var tempHtml = rowHtml;
for (var i = 0; i < match.length; i++)
tempHtml = this.highlight(tempHtml, match[i]);
if (tempHtml.search(/<\/mark>/g) > -1) {
rowHtml = tempHtml;
rowDisplay = 'table-row';
}
else // Keyword did not match with any column content
rowDisplay = 'none';
}
else // Keyword did not match even in the row text content
rowDisplay = 'none';
}
rowObj.innerHTML = rowHtml;
rowObj.style.display = rowDisplay;
}
// Check if 'no results' row needs to be added
if (keyword != '' && this.options.noResultsText && this.dataTable.innerHTML.search(/style=\"display: table-row;\"/g) == -1)
this.toggleNoResult('add');
},
highlight: function(rowHtml, match) {
var row = document.createElement('tr');
row.innerHTML = rowHtml;
var textReplaceRegex = new RegExp(this.escapeSpecialChars(match), "g"); // case sensitive
var highlightMarkup = '<mark ' + this.options.highlightCss + '>' + match + '</mark>';
var cell = null;
var htmlOut = '';
for (var i = 0; i < row.cells.length; i++) {
cell = row.cells.item(i);
// Highlighting works only for direct text content, not nested tags.
// e.g. searching "blog" in <td>my blog</td> won't work.
if (cell.children.length == 0) {
if (cell.textContent.indexOf(match) > -1) {
// Match found in this cell, highlight it
htmlOut += '<td>' + cell.textContent.replace(textReplaceRegex, highlightMarkup) + '</td>';
continue;
}
}
htmlOut += '<td>' + cell.innerHTML + '</td>';
}
return htmlOut;
},
escapeSpecialChars: function(inStr) {
return inStr.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&");
},
toggleNoResult: function(mode) {
var noResultsRow;
if (mode == 'add') {
noResultsRow = this.dataTable.insertRow(this.dataTable.rows.length);
noResultsRow.setAttribute('id', 'noResultsRow');
var noResultsRowCell = noResultsRow.insertCell(0);
noResultsRowCell.setAttribute('colspan', this.dataTable.rows[0].cells.length);
noResultsRowCell.setAttribute('align', 'center');
noResultsRowCell.textContent = this.options.noResultsText;
}
else if (mode == 'remove') {
noResultsRow = this.dataTable.querySelector('#noResultsRow');
if (noResultsRow != null) {
this.dataTable.deleteRow(this.dataTable.rows.length - 1);
}
}
}
}
Thanks in advance :)
Related
I am having difficulty in selecting only elements that contain a certain value.
if (autoCostBatches) {
if ($('#noCostRecovery').attr('checked')) {
var tester= "";
for (var i = 0; i < autoCostBatches2.length; i++) {
tester = tester + autoCostBatches2[i].items + ", ";
}
var userString = tester.substring(0, tester.length - 2);
console.log(userString);
element = $('td:not(:contains(' + userString + '))');
if (element.length) {
elementParent = element.parent();
checkBox = elementParent.children('td').children('input');
checkBox.prop('checked', true);
}
}
} else {
for (var i = 0; i < autoCostBatches.d.batches.length; i++) {
element = $('td:not(:contains(' + autoCostBatches.d.batches[i].items + '))');
found = $.inArray(element, test) > -1;
if (element.children().length && found === false) {
elementParent = element.parent();
checkBox = elementParent.children('td').children('input');
checkBox.prop('checked', false);
}
}
}
here is the printed userstring to console and appears to be right.
and here are the elements in a table. Note that there is a td element containing 630316 and 632848 split by a comma. This to me looks correct but when I run the function all checkboxes are being checked which should not happen.
I am trying to swap two array in javascript. While the replacement comes to the last iteration, I am getting "NotFoundError: Node was not found" in the call of parent.replaceChild(item2,item1). Please help me what mistake I have committed.
function sortTable(col){
if($("loacte-resultsTable") == null || $("loacte-resultsTable") == undefined){
return false;
}
if (lastSort == col) {
// sorting on same column twice = reverse sort order
absOrder ? absOrder = false : absOrder = true
}
else{
absOrder = true
}
lastSort = col;
try{
var loacteResultsTable = $("loacte-resultsTable").getElementsByTagName("TBODY")[0];
var loacteResultsTableTR = loacteResultsTable.getElementsByTagName("TR");
allTR = loacteResultsTableTR;
} catch (e) {
return false;
}
// allTR now holds all the rows in the dataTable
totalRows = allTR.length;
colToSort = new Array(); //holds all the cells in the column to sort
colArr = new Array(); //holds all the rows that correspond to the sort cell
copyArr = new Array(); //holds an original copy of the sort data to match to colArr
resultArr = new Array(); //holds the output
allNums = true
allDates = true
//store the original data
//remember that the first row - [0] - has column headings
//so start with the second row - [1]
//and load the contents of the cell into the array that will be sorted
for (x=0; x < totalRows; x++){
var data = setDataType(allTR[x].childNodes[col].innerText);
if(typeof data!="undefined"){
colToSort[x] = setDataType(allTR[x].childNodes[col].innerText);
}else{
colToSort[x] = setDataType(allTR[x].childNodes[col].textContent);
}
colArr[x] = allTR[x];
}
//make a copy of the original
for (x=0; x<colToSort.length; x++){
copyArr[x] = colToSort[x];
}
//sort the original data based on data type
if (allNums){
colToSort.sort(numberOrder);
} else if (allDates){
colToSort.sort(dateOrder);
} else {
colToSort.sort(textOrder);
}
//match copy to sorted
for(x=0; x<colToSort.length; x++) {
for(y=0; y<copyArr.length; y++) {
if (colToSort[x] == copyArr[y]) {
boolListed = false
//search the ouput array to make sure not to use duplicate rows
for(z=0; z<resultArr.length; z++) {
if (resultArr[z]==y) {
boolListed = true
break;
}
}
if (!boolListed){
resultArr[x] = y
break;
}
}
}
}
//now display the results - it is as simple as swapping rows
for (x=0; x<resultArr.length; x++) {
//allTR[x].swapNode(colArr[resultArr[x]])
swapNodes(allTR[x],colArr[resultArr[x]]);
}
function swapNodes(item1,item2)
{
var itemtmp = item1.cloneNode(1);
var parent = item1.parentNode;
item2 = parent.replaceChild(itemtmp,item2);
parent.replaceChild(item2,item1);
parent.replaceChild(item1,itemtmp);
itemtmp = null;
}
}
The call to the sortTable method is from synch().This is the UI part coded in JS:
function synch(){
var loacteResults = $('loacte-results');
var loacteResultsTable = $('loacte-resultsTable');
tab = loacteResults.getElementsByTagName('TABLE')[0];
loacteResults.removeChild(tab);
var updatedResults =
'<table id="loacte-resultsTable" cellspacing="0" cellpadding="3" border="1">' +
'<thead class="thead">' +
'<tr>' +
'<th>Site ID</th>' +
'<th>Store Name</th>' +
'<th>Agent Code</th>' +
'<th>Address</th>' +
'<th>City, State</th>' +
'<th>Phone</th>' +
'<th>Hours</th>' +
'<th>Deleted</th>' +
'<th width="65px;">Priority <img src="images/sort_up_down.gif" onclick="javascript:sortTable(8)" style="cursor: pointer;"/></th>' +
'<th width="115px;">Est.Dist.(miles) <img src="images/sort_up_down.gif" onclick="javascript:sortTable(9)" style="cursor: pointer;"/></th>' +
'</tr>' +
'</thead>' ;
if(tr == '')
updatedResults = updatedResults + '<tbody><tr><td colspan="10">No Stores to display</td></tr></tbody></table>';
else
updatedResults = updatedResults + '<tbody>' + tr + '</tbody></table>';
loacteResults.innerHTML = updatedResults;
}
In the third parent.replaceChild line item1 is no longer is on the page, since it has been replaced with item2.
Your code broken down:
function swapNodes(item1,item2)
{
var itemtmp = item1.cloneNode(1); //create a copy of item 1
var parent = item1.parentNode; //set a reference to the parent
item2 = parent.replaceChild(itemtmp,item2); //replace item2 with the copy of item1 and store the old child in item2
parent.replaceChild(item2,item1); //replace item1 with item2
parent.replaceChild(item1,itemtmp); //this line is redundant. <-- item1 no longer is on the page.
itemtmp = null;
}
I have a unique problem that I hope someone can help with. I have a page that pulls data from a controller with AJAX and presents it to this function to construct a table:
// make rows in table from json data
function makeTableRows() {
if (jsonTableData != null) {
tbl = null;
tbl = createTable('tableResults');
// constructHeader(tbl, 'left', jsonTableData[0]);
newHeader(tbl, 'left', jsonTableData[0]);
var totalItems = jsonTableData.length;
var topItem;
topItem = 0;
if ((lastItem + perpage) > totalItems) {
topItem = totalItems;
$(".btnNext").prop('disabled', true);
}
else {
topItem = lastItem + perpage;
}
for (var i = lastItem; i <= topItem - 1; i++) {
makeTableRow(tbl, jsonTableData[i], 'left', true, 'showTourDetails(' + jsonTableData[i]["TransactionID"] + ',' + i + ')', 0);
}
$("#divSearchResults").html(tbl);
makePagesLabel();
makeTableFooter(tbl);
}
}
the function inside the separate file is this:
function constructHeader(table, alignment, firstRow) {
if (firstRow != null) {
var thead = document.createElement('thead');
table.appendChild(thead);
var tr = document.createElement('tr');
for (var key in firstRow) {
var header = key.match(/[A-Z][a-z]*/g);
var newHeader = '';
for (var i = 0; i <= header.length - 1; i++) {
newHeader += header[i] + ' ';
}
var th = document.createElement('th');
var text = document.createTextNode(newHeader);
th.appendChild(text);
th.style.textAlign = alignment;
th.style.cursor = 'pointer';
th.setAttribute('title', "Sort by " + newHeader);
th.onclick = function () {
var rows = $(table).find('tbody').find('tr').toArray().sort(comparer($(this).index()));
this.asc = !this.asc;
if (!this.asc) {
rows = rows.reverse();
}
for (var j = 0; j < rows.length; j++) {
$(table).append(rows[j]);
}
$(table).find('tbody').find('tr:even').css("background-color", "#dae5f4");
$(table).find('tbody').find('tr:odd').css("background-color", "#b8d1f3");
};
tr.appendChild(th);
}
thead.appendChild(tr);
}
}
Basically the function creates a sort process for the header of each column. After the sort of the column, I want to reapply the zebra striping that is applied with the class of the table. If I don't try to reapply I end up with the striping all messed up. Now, the problem is that if I copy the function into the .cshtml page and give it the name of 'newheader', the re-striping works fine. It does not work in the separate JS file and I cannot figure out why. Anyone have any clues?
var a = document.querySelectorAll('.post .content div');
var b = a[7].childNodes;
for(i=0;i<b.length;i++){
var exp = /(\b(https?|ftp|file):\/\/[\-A-Z0-9+&##\/%?=~_|!:,.;]*[\-A-Z0-9+&##\/%=~_|])/ig;
if(b[i].nodeType === 3){
var ahref = document.createElement('a');
ahref.className="easyBBurlFetch";
ahref.href=b[i].nodeValue.replace(exp,'$1');
ahref.innerText=b[i].nodeValue.replace(exp,'$1');
b[i].parentNode.insertBefore(ahref,b[i]);
b[i].parentNode.removeChild(b[i].nextSibling);
}
}
Someone gave me the answer as I had this code though it wasn't working correct. Though I have the issue now if my text is like so:
This is just a test so click here www.youtube.com which then becomes
www.youtube.com%20which%20then%20becomes
It doesn't event keep the first line of text, I just need to parse the url while keeping the surrounding text.
In need the output to save the actual surrounding text but parse the urls that are inside the text to html anchor tags <a> so that they can then be clickable and actually follow through to a real website and not have unnessarcy text inside it from what my user was writing about. Thank you
UPDATE
I've got closer to making this work-- But I'm having a problem with the first text in the string is saying Undefined I've been debugging this and can't seem to figure out why this is happening. Here is code
var a = document.querySelectorAll('.post');
var b = a[0].childNodes;
var textArray;
var ahref;
for (i = 0; i < b.length; i++) {
var exp = /(\b(https?|ftp|file):\/\/[\-A-Z0-9+&##\/%?=~_|!:,.;]*[\-A-Z0-9+&##\/%=~_|])/ig;
if (b[i].nodeType === 3) {
var newHTML;
textArray = b[i].textContent.split(" ");
for (var j = 0; j < textArray.length; j++) {
if (textArray[j] !== "" && validURL(textArray[j])) {
ahref = document.createElement('a');
ahref.href = (/^(http:\/\/|https:\/\/)/).test(textArray[j]) ? textArray[j] : "http://" + textArray[j];
ahref.innerText = textArray[j];
ahref.className = "easyURLparse";
textArray[j] = ahref;
}
newHTML+= textArray[j].outerHTML ? textArray[j].outerHTML + " " : textArray[j] + " ";
}
var div = document.createElement('div');
div.innerHTML = newHTML;
newHTML = "";
b[i].parentNode.insertBefore(div, b[i]);
b[i].parentNode.removeChild(b[i].nextSibling);
}
}
function validURL(str) {
var pattern = new RegExp("([a-zA-Z0-9]+://)?([a-zA-Z0-9_]+:[a-zA-Z0-9_]+#)?([a-zA-Z0-9.-]+\\.[A-Za-z]{2,4})(:[0-9]+)?(/.*)?");
if (!pattern.test(str)) {
return false;
} else {
return true;
}
}
Testing Code
Just need to figure out the undefined and why it's adding it
this regexp will do the job
exp = /href="(\b(https?|ftp|file):\/\/[\-A-Z0-9+&##\/%?=~_|!:,.;]*[\-A-Z0-9+&##\/%=~_|])"/ig;
var a = document.querySelectorAll('.post');
var b = a[0].childNodes;
var textArray;
var ahref;
for (i = 0; i < b.length; i++) {
var exp = /(\b(https?|ftp|file):\/\/[\-A-Z0-9+&##\/%?=~_|!:,.;]*[\-A-Z0-9+&##\/%=~_|])/ig;
if (b[i].nodeType === 3) {
var newHTML;
if (validURL(b[i].textContent)) {
textArray = b[i].textContent.split(" ");
for (var j = 0; j < textArray.length; j++) {
if (textArray[j] !== undefined && textArray[j] !== "" && validURL(textArray[j]) && textArray[j] !== null) {
ahref = document.createElement('a');
ahref.href = (/^(http:\/\/|https:\/\/)/).test(textArray[j]) ? textArray[j] : "http://" + textArray[j];
ahref.innerText = textArray[j];
ahref.className = "easyURLparse";
textArray[j] = ahref;
}
newHTML += textArray[j].outerHTML ? textArray[j].outerHTML + " " : textArray[j] + " ";
}
var div = document.createElement('div');
div.innerHTML = newHTML;
div.className = "easyDiv";
b[i].parentNode.insertBefore(div, b[i]);
b[i].parentNode.removeChild(b[i].nextSibling);
}
newHTML = "";
}
}
function validURL(str) {
var pattern = new RegExp("([a-zA-Z0-9]+://)?([a-zA-Z0-9_]+:[a-zA-Z0-9_]+#)?([a-zA-Z0-9.-]+\\.[A-Za-z]{2,4})(:[0-9]+)?(/.*)?");
if (!pattern.test(str)) {
return false;
} else {
return true;
}
}
By taking the textNodes and splitting them into an array I can then change the url into an html element. Then taking the array elements seeing if there is outerHTML or not then placing it in a new string and replacing that textNode now with a workable link.
Working example
I am using a script that adds a fieldset to my form but I am having one glitch that I can not figure out and would appreciate any insight you can provide.
Here is the trouble:
The duplication of the fieldset works great.
I have another script which is creating a sum of the fields named "unitPrice" in the original fieldset. When I add a new fieldset with the new unitPrice fields do not get calculated into the sum. I am sure they are being renamed but what name would I use and how do I write it into the calculation so that I have a total of all of the unitPrice fields?
Thanks for your help.
Here is the Fieldset script:
<script>
function insertAfter(newElement, targetElement)
{
var parent = targetElement.parentNode;
if (parent.lastChild == targetElement)
{
parent.appendChild(newElement);
}
else
{
parent.insertBefore(newElement, targetElement.nextSibling);
}
}
// Suffix + Counter
var suffix = ':';
var counter = 1;
// Clone nearest parent fieldset
function cloneMe(a)
{
// Increment counter
counter++;
// Find nearest parent fieldset
var original = a.parentNode;
while (original.nodeName.toLowerCase() != 'fieldset')
{
original = original.parentNode;
}
var duplicate = original.cloneNode(true);
// Label - For and ID
var newLabel = duplicate.getElementsByTagName('label');
for (var i = 0; i < newLabel.length; i++)
{
var labelFor = newLabel[i].htmlFor
if (labelFor)
{
oldFor = labelFor.indexOf(suffix) == -1 ? labelFor : labelFor.substring(0, labelFor.indexOf(suffix));
newLabel[i].htmlFor = oldFor + suffix + counter;
}
var labelId = newLabel[i].id
if (labelId)
{
oldId = labelId.indexOf(suffix) == -1 ? labelId : labelId.substring(0, labelId.indexOf(suffix));
newLabel[i].id = oldId + suffix + counter;
}
}
// Input - Name + ID
var newInput = duplicate.getElementsByTagName('input');
for (var i = 0; i < newInput.length; i++)
{
var inputName = newInput[i].name
if (inputName)
{
oldName = inputName.indexOf(suffix) == -1 ? inputName : inputName.substring(0, inputName.indexOf(suffix));
newInput[i].name = oldName + suffix + counter;
}
var inputId = newInput[i].id
if (inputId)
{
oldId = inputId.indexOf(suffix) == -1 ? inputId : inputId.substring(0, inputId.indexOf(suffix));
newInput[i].id = oldId + suffix + counter;
}
}
// Select - Name + ID
var newSelect = duplicate.getElementsByTagName('select');
for (var i = 0; i < newSelect.length; i++)
{
var selectName = newSelect[i].name
if (selectName)
{
oldName = selectName.indexOf(suffix) == -1 ? selectName : selectName.substring(0, selectName.indexOf(suffix));
newSelect[i].name = oldName + suffix + counter;
}
var selectId = newSelect[i].id
if (selectId)
{
oldId = selectId.indexOf(suffix) == -1 ? selectId : selectId.substring(0, selectId.indexOf(suffix));
newSelect[i].id = oldId + suffix + counter;
}
}
// Textarea - Name + ID
var newTextarea = duplicate.getElementsByTagName('textarea');
for (var i = 0; i < newTextarea.length; i++)
{
var textareaName = newTextarea[i].name
if (textareaName)
{
oldName = textareaName.indexOf(suffix) == -1 ? textareaName : textareaName.substring(0, textareaName.indexOf(suffix));
newTextarea[i].name = oldName + suffix + counter;
}
var textareaId = newTextarea[i].id
if (textareaId)
{
oldId = textareaId.indexOf(suffix) == -1 ? textareaId : textareaId.substring(0, textareaId.indexOf(suffix));
newTextarea[i].id = oldId + suffix + counter;
}
}
duplicate.className = 'duplicate';
insertAfter(duplicate, original);
}
// Delete nearest parent fieldset
function deleteMe(a)
{
var duplicate = a.parentNode;
while (duplicate.nodeName.toLowerCase() != 'fieldset')
{
duplicate = duplicate.parentNode;
}
duplicate.parentNode.removeChild(duplicate);
}
</script>
Here is the script I am using for the calculation:
<script type="text/javascript">
function myFunction(){
var the_fields = document.getElementsByName("unitPrice");
var the_sum = 0;
for (var i=0; i<the_fields.length; i++){
if (the_fields[i].value != ""
&& !isNaN(the_fields[i].value))
{
the_sum += Number(the_fields[i].value);
}
}
document.repairform.sum.value = (the_sum.toFixed(2));
}
</script>
I guess that you need to call "myfunction" each time a new field is being added.
When someone loads your page , the "myfunction" calculate the sum of the "existing" fields at the current. When you duplicate the fields you need to re-call "myfunction" so it will update the sum according to the new duplicated fields.