Dynamically changing innerText's start without eval() - javascript

I have some code (several batches) that look like this:
1 <div id="backgrounds" class="centery">Backgrounds
2 <div id="bk1" class="attr">Background 1
3 <div class="container">
4 <!-- Lots more HTML here /-->
5 </div>
6 </div>
7 </div>
I have a JS function I wrote (changefirstCharacters) that will return the script to change line 2 to read:
2 <div id="bk1" class="attr">Some text I specify
But because I want this to only execute when an event listener fires, it only outputs the code, rather than evaluating it. As a result, my event listener contains a line like this:
eval(changeFirstCharacters('bk1', "'" + document.getElementById('background1').value + "'"));
Where background1 is a select box.
How can I re-write changeFirstCharacters to not need eval, but still work only when called?
changeFirstCharacters() code
function changeFirstCharacters(id, newText) {
return 'document.getElementById(\"' + id + '\").innerHTML = ' + newText + ' \+ document.getElementById(\"' + id + '\").innerHTML.substr(' + document.getElementById(id).innerText.length + ', document.getElementById(\"' + id + '\").innerHTML.length \-' + document.getElementById(id).innerText.length + ')';
}

I don't see what's so dynamic about that statement. The only reason we need eval is when code is dynamically generated, but neither newText nor id changes the produced code. Therefore, the following ought to work:
document.getElementById(id).innerHTML = newText +
document.getElementById(id).innerHTML.substr(document.getElementById(id).innerText.length,
document.getElementById(id).innerHTML.length - document.getElementById(id).innerText.length);
Called by (without adding quotes around the second argument):
changeFirstCharacters('bk1', document.getElementById('background1').value)
Also that first code calls getElementById(id) five times, which is not only a performance hit, it's rather ugly. You might want to rewrite it as:
var el = document.getElementById(id);
el.innerHTML = newText + el.innerHTML.substr(el.innerText.length,
el.innerHTML.length - el.innerText.length);

Related

addeventlistener to indexed element

I have a list of elements. However, the length of this list varies between trials. For example, sometimes there are 6 elements and sometimes there are 8. The exact number is detailed in an external metadata.
To display this variable list, I've written:
var html = '';
html += '<div id="button' + ind + '" class="buttons">';
html += '<p>' + name + '</p></div>';
display_element.innerHTML = html;
If I were to 'inspect' the elements in my browser, they would appear to have IDs of button0.buttons, button1.buttons, etc.
Now I am trying to attach event listeners to each element but my code is not working so far. Different forms of broken code below:
document.getElementById("button' + ind + '").addEventListener("click", foo);
$("#button' + ind + '").click(foo);
document.getElementById("button").addEventListener("click", foo);
$("#button").click(foo);
Any help would be very appreciated! Thanks.
You wrong at concat string update it as
document.getElementById("button" + ind).addEventListener("click", foo);
var html = '';
var ind = 1;
var display_element = document.getElementById("test");
html += '<div id="button' + ind + '" class="buttons">';
html += '<p>' + name + '</p></div>';
display_element.innerHTML = html;
document.getElementById("button" + ind).addEventListener("click", foo);
function foo(){
alert('click');
}
<div id="test"></div>
Use "document.getElementsByClassName" get all botton elements then foreach to add click function.
document.getElementsByClassName('buttons').map( element => { element.addEventListener("click", foo) })
To answer the question of why neither of those uses of document.getElementById() are working for you, you are mixing your quotes incorrectly. "button' + ind '" evaluates to exactly that, rather than evaluating to "button0", "button1", etc. To make your code more readable, and to avoid similar quote mixing issues, I would recommend looking into template literals https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals
With modern JS if you want to execute the same function you won't require to add an id to each button.
Just use the class added to the buttons like this:
document.querySelectorAll('.buttons').forEach(button => {
button.addEventListener('click',foo);
});
Then use the event parameter in that function to get the target node & execute whatever you want. You can also add data attributes in those buttons to use while executing that function.

How to hard code text which are coming from javascript messages

Our application is been internationalized and being changed to different languages. For that reason we have to hard code all the messages. How can we do that for messages in javascript ?
This is how we are doing in html messages.
<span th:text="#{listTable.deletedFromTable}">deleted</span>
How do we hard code for javascript messages.(update the table)
$('#TableUpdate-notification').html('<div class="alert"><p>Update the Table.</p></div>');
You will need to put the messages in the DOM from the start, but without displaying them. Put these texts in span tags each with a unique id and the th:text attribute -- you could add them at the end of your document:
<span id="alertUpdateTable" th:text="#{listTable.updateTable}"
style="display:none">Update the Table.</span>
This will ensure that your internationalisation module will do its magic also on this element, and the text will be translated, even though it is not displayed.
Then at the moment you want to use that alert, get that hidden text and inject it where you need it:
$('#TableUpdate-notification').html(
'<div class="alert"><p>' + $('#alertUpdateTable').html() + '</p></div>');
You asked for another variant of this, where you currently have:
$successSpan.html(tableItemCount + " item was deleted from the table.", 2000);
You would then add this content again as a non-displayed span with a placeholder for the count:
<span id="alertTableItemDeleted" th:text="#{listTable.itemDeleted}"
style="display:none">{1} item(s) were deleted from the table.</span>
You should make sure that your translations also use the placeholder.
Then use it as follows, replacing the placeholder at run-time:
$successSpan.html($('#alertTableItemDeleted').html().replace('{1}', tableItemCount));
You could make a function to deal with the replacement of such placeholders:
function getMsg(id) {
var txt = $('#' + id).html();
for (var i = 1; i < arguments.length; i++) {
txt = txt.replace('{' + i + '}', arguments[i]);
}
return txt;
}
And then the two examples would be written as follows:
$('#TableUpdate-notification').html(
'<div class="alert"><p>' + getMsg('alertUpdateTable') + '</p></div>');
$successSpan.html(getMsg('alertTableItemDeleted', tableItemCount));

encodeURIComponent not working with Twitter button

I'm currently trying to make an app that tweets out the quote that's currently in the text bubble. However, when I use this line of code,
<a class="twitter-share-button" href="https://twitter.com/intent/tweet?text" + encodeURIComponent(quote.quote + ' - ' + quote.author);>Tweet</a>
It doesn't take me anywhere. Is there any way I could get this working or would I need to use an external Twitter button?
Thanks!
CodePen Link: http://codepen.io/Jelani/full/rOmrOJ/
You can't embed javascript in your markup like that. One approach you could take would be to add some code to your randomQuote function like this:
var randomQuote = function() {
... // current code
var text = quote.quote + ' - ' + quote.author;
$('.twitter-share-button').attr('href', "https://twitter.com/intent/tweet?text="+encodeURIComponent(text));
}
Another approach would be to move your quote variable declaration out of the randomQuote function and set an onclick on the twitter-share-button
<a class="twitter-share-button" onclick="goTweet()">Tweet</a>
that calls a function that does something like:
function goTweet() {
var text = quote.quote + ' - ' + quote.author;
window.location.href = "https://twitter.com/intent/tweet?text=" + encodeURIComponent(text);
}

How to get the total of the list ordered, with Javascript

I'm making a code of a online delivery webpage, and I having a hard time trying to figure out how to output the total of the list ordered by the user.
function ListOrder(){
document.getElementById('order').innerHTML += "<div id=\"YourOrders\">" + + document.getElementById('FoodName').value + document.getElementById('quantity').value + document.getElementById('Totality').value + "</div><br>";}
Edited: I want to know how I can get the sum of the total price. So, I placed a parseInt between the document.getElementById('Totality').value . It looks like this now,
function ListOrder(){
document.getElementById('order').innerHTML += "<div id=\"YourOrders\">" + + document.getElementById('FoodName').value + document.getElementById('quantity').value + parseInt(document.getElementById('Totality').value) + "</div><br>";}
Can someone help me make a function or something for that? Javascript only, please. I'm still kinda new at it.
function ListOrder(){
document.getElementById('order').innerHTML +=
"<div id=\"YourOrders\">" +
parseInt(document.getElementById('FoodName').value) +
parseInt(document.getElementById('quantity').value) +
parseInt(document.getElementById('Totality').value) +
"</div><br>";
}
the kernel of your code should look like the following (double + operator deleted, reformatted):
function ListOrder(){
document.getElementById('order').innerHTML +=
"<div id=\"YourOrders\">" + (
document.getElementById('FoodName').value
+ document.getElementById('quantity').value
+ document.getElementById('Totality').value
)
+ "</div><br>"
;
}
You've phrased your question in a way that suggests you wish to output an order list assembled from the content of all (html) elements with certain ids.
this won't work reliably:
Ids should be document unique.
The Js functions you use do not iterate over lists.
instead, proceed along the following lines (which assume that you import jquery, a cross-browser dom-handling and ajax library (which you should use anyway :)):
function ListOrder(){
var e_orders = $("<div id=\"YourOrders\">");
$("#order").append(e_orders);
$(".FoodName").each ( function ( idx_fn, e_fn ) {
$(e_orders).append(
$("<div/>").append(
$(e_fn).val()
+ $(e_fn).nextAll('.quantity').val()
+ $(e_fn).nextAll('.Totality').val()
);
);
$(e_orders).append("<br>");
});
return e_orders;
}
The code template assumes that the source data are elements with value attributes being marked with css classes quantity, Totality and 'FoodName``, that these elements are siblings and unique within a container element for each item incl. quantity information. It should be flexible enough to be tailored to your actual needs and html structure.

jQuery: trying hook a function to the onclick when page loads

I have seen a similar question, HERE and have tried that, but I can't seem to get it working.
Here is my code for dynamically generating table rows.
for (var contribution = 0; contribution < candidate.contributions.length - 1; contribution++) {
var id = candidate.contributions[contribution].donor_id;
var uid = candidate.contributions[contribution].user_id;
$("#history-table").append(
"<tr onclick='" + parent.viewEngine.pageChange('public-profile', 1, id, uid) + ";>" +
"<td class='img-cell'>" +
"<img class='profile-avatar-small' src='/uploads/profile-pictures/" +
candidate.contributions[contribution].image + "' alt='' /></td><td class=''>" +
"<h2>" + candidate.contributions[contribution].firstname +
" " + candidate.contributions[contribution].lastname + "</h2></a><br/><br/>" +
"<span class='contribution-description'>" + candidate.contributions[contribution].contribution_description + "</span></td>" +
"<td><h3>$" + formatCurrency(candidate.contributions[contribution].contribution_amount) + "</h3></td></tr>");
}
This still executes the click event as soon as the page loads, which is not the desired behavior. I need to be able to click the tr to execute the click event.
Pass the whole thing as a string:
"<tr onclick='parent.viewEngine.pageChange(\'public-profile\', 1, " + id + ", " + uid + ");>" // + (...)
But, as you are using jQuery, you should be attaching the click handler with .on().
(I really don't recommend using inline event handlers like that, especially when you're already using jQuery, but anyway...)
The problem is that you need the name of the function to end up in the string that you are passing to .append(), but you are simply calling the function and appending the result. Try this:
...
"<tr onclick='parent.viewEngine.pageChange(\"public-profile\", 1, " + id + "," + uid + ");'>" +
...
This creates a string that includes the name of the function and the first couple of parameters, but then adds the values of the id and uid variables from the current loop iteration such that the full string includes the appropriately formatted function name and parameters.
Note that the quotation marks around "public-profile" were single quotes but that wouldn't work because you've also used single quotes for your onclick='...', so you should use double-quotes but they need to be escaped because the entire string is in double-quotes.
I'm wondering if you might be better simplifying things a bit.
If your rows are being dynamically added, then try putting some kind of meta-data in the <tr> tag, e.g. something like this:
<tr id="id" name="uid">
Then try the following with your jQuery (v.1.7 required):
$('#history-table tr').on('click', function(){
parent.viewEngine.pageChange('public-profile', 1, this.id, this.name);
});
This will likely require modification depending on how your page rendering works but it's a lot cleaner and easier to read having been removed from your main table markup.
Well that's because you're executing the function, not concatenating it. Try:
onclick='parent.viewEngine.pageChange("public-profile", 1, id, uid);'
Take this ->
$("#contribution-" + uid).click(function(){
parent.viewEngine.pageChange('public-profile',1, id, uid);
});
And do two things:
1) Move it outside of the 'for' statement
As soon as the for statement is executed, the click function will be executed as well. The click function is not being supplied as a callback function in this for statement.
2) Change it to ->
$("tr[id^='contribution-'").on('click', function(){
var idString = $(this).attr("id").split("-"); //split the ID string on every hyphen
var uid = idString[1]; //our UID sits on the otherside of the hyphen, so we use [1] to selec it
//our UID will now be what we need. we also apply our click function to every anchor element that has an id beginning with 'contribution-'. should do the trick.
parent.viewEngine.pageChange('public-profile',1, id, uid);
});
This is my solution.

Categories

Resources