Table Navigation and row selection - javascript

I have an HTML table which contains about 1000 rows and 26 columns. I am using this jQuery plugin to navigate between rows and make a selection.
My first problem is that the plugin is working fine, but—even using the latest version (0.6.1)—it's very slow when working with 1000 rows.
My second problem is that I want to create a JSON object representing the selected row from the table. I wrote a function that does this, but again it's too slow on such a big table. The following code works, but I want to optimise it:
$(document).bind("keyup", function(event) {
var jsonText = "";
var i = 0;
var td_size = $("tr.selected td").size();
jsonText += "{";
for (i = 0; i < td_size; i++) {
if (i < td_size - 1) {
if (i == 0) {
// Get link URL.
jsonText += "\"" + $("thead tr th").eq(i).text() + "\":\"" + $("tr.selected td").eq(i).find("a").attr("href") + "\",";
} else {
jsonText += "\"" + $("thead tr th").eq(i).text() + "\":\"" + $("tr.selected td").eq(i).text() + "\",";
}
}
else {
jsonText += "\"" + $("thead tr th").eq(i).text() + "\":\"" + $("tr.selected td").eq(i).text() + "\"";
}
}
jsonText += "}";
$('#content').html('').append(jsonText);
});
Any suggestions please?

One thing you can do is optimize your jQuery selectors to help the Sizzler work faster...
instead of biding on keyup of all document, how about keyup of a specific tr?
$("tr.selected td").size(); // slow
$("table").find(".selected").find("td"); // probably faster
Save the selected tr outside the loop, you're asking the sizzler to find your object 26 times by looping 1000 rows!
$("thead tr th").eq(i) // on every loop element? slow, try saving the information before the keyup event, they are not going anywhere are they?
So probably something like this would be faster:
var $allTrs = $("tr");
var $allHeads = $("thead tr th");
$allTrs.bind("keyup", function(event) {
var jsonText = "";
var i = 0;
var $t = $(this),
$alltds = $t.find("td"),
td_size = $alltds.length();
jsonText += "{";
$.each($alltds, function(i){
jsonText += "\"" + $allHeads.eq(i).text() + "\":\"";
if (i == 0){ // you have a strange condition, will leave it up to u
// append link
jsonText += $(this).find("a").attr("href"); // i remove "" for better readability
}else{
// append text
jsonText += $(this).text();
}
});
jsonText += "}";
$('#content').text(jsonText); // cheaper than html
});
I have not tested this yet.
You can also create a json object directly (wouldn't affect how fast though), like this
var mynewjson = {};
Then inside a loop:
mynewjson[name] = value;

Related

InnerHTML doesn't work - Advanced function

I'm beginner in JS. But, after many hours, i'm really close to the wanted result.
I declare my JS Function in head part
function getPrice(price) {
var tabPrice = price.split("");
var html = "";
var virguleIndex = null;
for (var index = 0; index < tabPrice.length; ++index) {
var priceNumber = tabPrice[index];
if (priceNumber == ',') {
virguleIndex = index;
html += "<span class='p-c'>" + priceNumber + "</span>";
} else if (priceNumber == '-') {
html += "<span class='p-d'>" + priceNumber + "</span>";
} else if (index > virguleIndex && virguleIndex != null) {
html += "<span class='p-" + priceNumber + " p-small'>" + priceNumber + "</span>";
} else {
html += "<span class='p-" + priceNumber + "'>" + priceNumber + "</span>";
}
}
var div = document.getElementsByClassName('price');
div[0].innerHTML = html;
}
and my div in body part
<div class="price"></div>
I made some test - And my function getPrice works perflectly
https://image.noelshack.com/fichiers/2018/02/4/1515663887-functionwork.jpg
Some, the only fail (I think) is that the innerHTML don't work and don't write de var html content in div class price.
I haven't idea yet after many (many) hours of looking.
Can you help me ?
Thanks in advance,
Ludovic
By going through your image it is clear your DOM is not ready. So Please call your function inside this Block.
(function() {
// your page initialization code here
// the DOM will be available here
//Call Your function inside this block. it will work ex. getPrice("100");
})();
Some news (I worked on this few hours), I check for the dom charging. I tried (thank for you answer) the call function / transpose the code and the end / forcing the function after the dom loading (with document.addEventListener("DOMContentLoaded", function(event) {)
Console log still working. But my div still empty :/
Thanks again !

Bad html formatting with jQuery.html()

I have something that I can't understand and i'm struggling with that for 2 days.
For the story, I'm using VICOPO api to get zipcode/city (France only I think).
The thing is that the code I'm generating is not really good interpreted by jQuery (or maybe I'm doing it wrong)
Here is the code:
$('#postcode').val($('#postcode').val().toUpperCase());
if ($('#postcode').val().length == 5)
{
var $ville = $('#postcode');
$.vicopo($ville.val(), function (input, cities) {
if(input == $ville.val() && cities[0]) {
if (cities.length == 1)
$('#city').val(cities[0].city);
else
{
var html = '';
html += '<div style=\'text-align:center\'>';
for (var i=0; i<cities.length; i++)
{
var v = cities[i].city;
// --- HERE IS MY PROBLEM ---
html += '<p onclick=\'alert(\'' + v + '\');\'>' + v + '</p>';
}
html += '</div>';
console.log(html);
$('#multi_ville').html(html);
}
}
});
When I inspect the elements in the multi_div this is what I get:
<p onclick="alert(" billey');'>BILLEY</p>
<p onclick="alert(" flagey-les-auxonne');'>FLAGEY-LES-AUXONNE</p>
etc ....
And when I inspect the console log, all looks correct:
<p onclick='alert('BILLEY');'>BILLEY</p>
<p onclick='alert('FLAGEY-LES-AUXONNE');'>FLAGEY-LES-AUXONNE</p>
<p onclick='alert('VILLERS-LES-POTS');'>VILLERS-LES-POTS</p>
etc ....
If someone have an idea or what I'm doing wrong, it would cool.
(may I mention, this code is in a smarty tpl file surrounded with the {literal} tag)
Try to create self closed tags via jquery and then append them to #multi_ville, here is an example:
// create div element
var div = $('<div/>', {
'style' : 'text-align:center'
});
for (var i=0; i<cities.length; i++)
{
var v = cities[i].city;
// create p element with click event and then append it to div
$('<p/>').on('click', function() {
alert(v);
}).text(v).appendTo(div);
}
$('#multi_ville').append(div);
EDIT It seems that my code above always alert the last city when we click on a element, that's because alert takes the value that v variable has at the time it runs, to solve this we can use let statement:
let v = cities[i].city;
Or a function:
for (var i=0; i<cities.length; i++) {
var v = cities[i];
createPTag(v, div);
}
function createPTag(v, div) {
$('<p/>').on('click', function() {
alert(v);
}).text(v).appendTo(div);
}
Instead of
html += '<p onclick=\'alert(\'' + v + '\');\'>' + v + '</p>';
try this:
html += '<p onclick="alert(\'' + v + '\');">' + v + '</p>';
Here's some info on when and how to use double/single quotes.
EDIT:
Also, check the else on this if statement:
if (cities.length == 1)
You need a closing curly bracket (}) to close in the else. It should be added directly after this line:
$('#multi_ville').html(html);

Changing the content of all <pre> tags using JavaScript

I want to know how I change all the pre tags inside a document...
I'm using this:
var preContent = document.getElementById('code').innerHTML;
but this only changes the content of 1 pre tag... the one with the ID 'code'.
If you can show me how i can change all the pre tags using JavaScript I appreciate
Here's all the code:
window.onload = function () {
var preContent = document.getElementById('code').innerHTML;
var codeLine = new Array();
var newContent = '<table width="100%" border="1" '
+ 'cellpadding="0" cellspacing="0" >';
codeLine = preContent.split('\n');
for (var i = 0; i < codeLine.length; i++) {
newContent = newContent + '<tr><td class="codeTab1" >'
+ i.toString() + '</td><td class="codeTab2">'
+ codeLine[i] + '</td></tr>';
}
newContent = newContent + '</table>';
document.getElementById('code').innerHTML = newContent;
}
PS: This is to make a look like a normal compiler with numbers before the line
PPS: Each pre tag will have a different content and I want the same script to change it (if possible).
You can use getElementsByTagName:
var preElements = document.getElementsByTagName('pre');
for(var i = 0; i < preElements.length; ++ i)
{
var element = preElements[i];
/* modify element.innerHTML here */
}
First problem in you code . No two elements in a document can have same id .
So you can change it easily with jquery . look at the code .
$('pre').html("what ever text you want to show ");
Or with javascript you can do like this :
var x = document.getElementsByTagName('pre');
for(var i = 0; i < x.length; ++ i)
{
x.innerHTML = "what ever text you want to show";
}

Jquery / Javascript - most efficient way to build a select menu?

I'm using jquery and trying to tune my select menu builder to run much quicker.
I was using each and append, however I've since switched to a standard for loop and currently trying to convert my options from using append to concatenated string appended to my select option using .html(). I seem to be at a loss trying to convert my var option object back to an html string. Could someone please tell me what I might be doing wrong.
$.selectMenuBuilder = function(json) {
var myselect = $("#myselect");
var list = "<option value=\"\">> Select Account Number</option>";
var l= json.funding.length;
for(var i=0;i<l; i++) {
var funding = json.funding[i];
var option = $("<option value=\"" + funding.id + "\">" + funding.accountNumber + "</option>")
if(someLogic) {
option.attr("selected", "selected");
}
//Having trouble here converting option object back to html.
list += option.html();
}
list += "<option value=\"addnew\">+ New Account Number</option>";
myselect .html(list);
}
You can totally do away with using jQuery for creating the option elements (unless theres some other untold reason you're using it).
i.e. Instead of
var option = $("<option value=\"" + funding.id + "\">" + funding.accountNumber + "</option>")
if(someLogic) option.attr("selected", "selected");
You can do:
list += "<option value=\"" + funding.id + "\" "+ (someLogic?'selected':'') +">" + funding.accountNumber + "</option>"
Secondly, $(option).html() will return the innerHTML of the option element, not including the option tag name. For doing this in a cross-browser fashion, you can wrap the option in an outer element and use its innerHTML instead.
i.e.
$(option).wrap('<select/>').parent().html() will give you what you want.
If you want to keep the for loop but want something that looks a bit cleaner, try this:
function menuBuilder( json ) {
var list = [],
$select = $('#myselect'),
i = 0,
l = json.funding.length,
funding;
for ( ; i < l; i++ ) {
funding = json.funding[ i ];
list.push(
'<option '+ somelogic ? 'selected' : ''+' value='+ funding.id +'>'+
funding.accountNumber +
'</option>'
);
}
$select.append(
'<option>Select Account Number</option>'+
list.join('') +
'<option value="addnew">New Account Number</option>'
);
}
You can create elements more efficiently like this:
$.selectMenuBuilder = function (json) {
var myselect = $("#myselect");
var l = json.funding.length;
for (var i = 0; i < l; i++) {
var funding = json.funding[i];
var opt = $("<option/>", {
value: funding.id,
html: funding.accountNumber,
selected: somelogic ? true : false //Pre-select option
});
myselect.append(opt);
}
}
efficiency with pure JavaScript
example jsfiddle
selectMenuBuilder = function(json) {
var myselect = document.getElementById("myselect"),
listItem = document.createElement("option"),
l = json.funding.length,
someLogic = false; // placeholder
listItem.innerText = "> Select Account Number";
myselect.appendChild(listItem);
for (var i = 0; i < l; i++) {
var funding = json.funding[i];
var listItem = document.createElement("option");
if (someLogic) {
listItem.setAttribute("checked", "checked");
}
listItem.setAttribute("value", funding.id);
listItem.innerText = funding.accountNumber;
myselect.appendChild(listItem);
}
listItem = document.createElement("option")
listItem.setAttribute("value", "addnew");
listItem.innerText = "+ New Account Number";
myselect.appendChild(listItem);
}

Fetching results from LinkedIn API through javascript

First of all thank you for reading this. I am having some trouble fetching the data given by the Linkedin sign-in API with javascript. Here is the script:
<script type="text/javascript">
function onLinkedInAuth() {
IN.API.Profile("me").fields(["firstName","lastName","headline","summary","location","educations","skills"]).result(displayProfiles);
}
function displayProfiles(profiles) {
member = profiles.values[0];
document.getElementById("name").value = member.firstName +" "+ member.lastName;
document.getElementById("pos").value = member.headline;
document.getElementById("city").value = member.location.name;
document.getElementById("sum").value = member.summary;
var i=0;
do {
var oldHTML = document.getElementById('para').innerHTML;
var newHTML = oldHTML + "<tr><td>" + member.educations.values[i].schoolName + "</td></tr>";
document.getElementById('para').innerHTML = newHTML;
i++;
}
while(i<=1);
var v=0;
do {
var oldHTML = document.getElementById('tara').innerHTML;
var newHTML = oldHTML + "<tr><td>" + member.skills.values[v].skill.name + "</td></tr>";
document.getElementById('tara').innerHTML = newHTML;
v++;
}
while(member.skills.values[v].skill.name);
document.getElementById("educ").value = member.educations.values[1].schoolName;
document.getElementById("skills").value = member.skills.values[0].skill.name;
}
</script>
It's a very basic script to get the user infos and, among it, the educational and professional background of the user. The thing is that member.educations.values[i].schoolName and member.skills.values[v].skill.name can have multiple values and I want to gather them all.
It works as long as the specified fields are not empty but then it outputs an error saying that member.skills.values[v] is undefined and it does not run the second loop.
I know the error is really basic but I'm not that great in javascript.
Thanks for your help anyways, have a good day!
You should check the length of the returned values and then loop through them as needed. Something along the lines of:
var educations = member.educations;
if(educations._total > 0) {
for(var i = 0; i < educations._total; i++) {
document.getElementById("educ").value += (i > 0) ? ', ' : '';
document.getElementById("educ").value += educations.values[i].schoolName;
}
}

Categories