Trying to get currency converter to work using jQuery - javascript

I'm working on a project using jQuery to make a currency converter. I'm getting the currency info from an api service and loading it up in a table with multiple currencies. After which, I want to be able to enter a number in one input and make the other inputs produce the correct currency according to the entered input.
As you can see in the following code, I'm trying to make the keyup function work on everything but the input of which the numbers are being entered at that moment.
My output result from the function is also incorrect.
If anyone can point out the very obvious mistake I'm making here that would be very helpful!
JS:
function parseCurrency(data) {
var container = $('.currency-data');
var iskInput = $('<tr>' +'<td>' + '<strong>ISK</strong>' +
'</td> ' + '<td>' + 'Íslensk króna' +
'</td>' + '<td></td>' + '<td>' + '1' + '</td>' +
'<td>' + '<input value="1000" class="input-value"></input>' + '</td>' +
'</tr>');
iskInput.prependTo(container);
$.each(data.results, function (key, currency){
var row = [];
row = $('<tr></tr>');
row.append('<td>' + '<strong>' + currency.shortName + '</strong>' + '</td>');
row.append('<td>' + currency.longName + '</td>');
row.append('<td>' + currency.changeCur + '</td>');
row.append('<td>' + currency.value + '</td>');
var input = $('<input class="input-value"></input>');
input.val((1000/currency.value).toFixed(2));
var td = $('<td></td>');
input.appendTo(td);
td.appendTo(row);
container.append(row);
})
var inputValue = $('.input-value');
var inputActive = $('.input-value:focus')
$.each(data.results, function (key, currency) {
inputValue.not(inputActive).keyup( function () {
inputValue.val((inputValue.val()/currency.value ).toFixed(2));
});
})
}
HTML:
<form name="converter"></div>
<h4>Collecting data from: m5 A bank Lb</h4>
<div>
<table class="table table-striped">
<thead>
<tr>
<th>Obj1</th>
<th>Obj2</th>
<th>Obj3</th>
<th>Obj4</th>
<th>Obj5</th>
</tr>
</thead>
<tbody class="currency-data">
</tbody>
</table>
<div class="loader lead" style="display:none;">Loading...</div>
</form>

That's a bit strange for me, because you select all the input field which are NOT focused, and in the keyup eventhandler you just work with the inputValue variable, which contains the focused input element too. By the way, you shouldn't iterate two times on the data.results. As charlietfl commented before it does not make any sense to put the bindings to the iteration. That's a big mistake also.

A simple Method
<html>
<head>
<script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
<script>
function changeTo(toType){
if(toType=="Pound")
cvrate = 0.86;
else
cvrate = 0.78;
$(".currency_change").each(function (index, element) {
var og_val = $(this).data("og-value");
var cvd_val = (og_val*cvrate).toFixed(2);
return $(this).html(cvd_val);
});
}
</script>
</head>
<body>
<br /><span class="currency_change" data-og-value="1254">1254</span>
<br /><span class="currency_change" data-og-value="145">145</span>
<br /><span class="currency_change" data-og-value="54">54</span>
<br /><span class="currency_change" data-og-value="254">254</span>
<br /><span class="currency_change" data-og-value="147">147</span><br />
<button onClick="changeTo('Pound');">Conver To Pound</button>
<button onClick="changeTo('Euro');">Conver To Euro</button>
</body>
</html>

Related

Fields breaking after Upgrade to JQuery 3.5.1

I have a table that is created using javascript based on what is put in a list. This works fine in Jquery 3.4, but when I upgrade to 3.5 I am seeing this break.
HTML
<h5>Questions</h5>
<table id="questionTable" class="table q">
<thead>
</thead>
<tbody id="qTable"></tbody>
</table>
<div id="questionDiv">
<input type="button" value="Add Question" onclick="AddNewQuestion()" class="btn btn-primary"/>
</div>
<hr />
<div id="questionDiv">
<input type="submit" value="Submit" class="btn btn-primary" />
</div>
Javascript
<script type="text/javascript">
$(document).ready(function () {
$(function () {
AddCurrentQuestions();
});
});
var table = document.getElementById("qTable");
var rowCount = table.rows.length;
var counter = rowCount.length;
function AddCurrentQuestions() {
var status = #Html.Raw(Json.Encode(Model.isNull));
if (status == false) {
#{ Model.QuestionList.Add(new Performance_Planning.ViewModel.QuestionViewModel.Questions());}
var questionItems = JSON.parse('#Html.Raw(Json.Encode(#Model.QuestionList))');
for (var i = 0; i < questionItems.length - 1; i++) {
var qItem = questionItems[i];
var questionDetail = qItem.Question;
//Create fields
var qTextCell = "<td><textarea id='QuestionList_" + i + "_Question' name='QuestionList[" + i + "].Question' class='Questions' /></td>";
var indexCell = "<td style='display:none'> <input name='QuestionList.Index' type='hidden' value='" + i + "' /></td>";
var removeCell = "<td align='center'><input id='btnDelLine'" + i + "type='button' value='Remove' onclick=\"removeRow('" + i + "')\" class='btn btn-primary' /></td>";
var newRow = "<tr id='qLineItem" + i + "'>" + indexCell + qTextCell + removeCell + "</tr>";
//Add row to table
$('#qTable').append(newRow);
//Add Values
$('#QuestionList_' + i + "_Question").val(questionDetail)
counter = i;
};
} else {
counter = 0;
AddNewQuestion();
}
};
function AddNewQuestion() {
#{ Model.QuestionList.Add(new Performance_Planning.ViewModel.QuestionViewModel.Questions());}
counter++;
//Create field
var indexCell = "<td style='display:none'> <input name='QuestionList.Index' type='hidden' value='" + counter + "' /></td>";
var qTextCell = "<td><textarea id='QuestionList_" + counter + "_Question' name='QuestionList[" + counter + "].Question' class='Questions' /></td>";
var removeCell = "<td align='center'><input id='btnDelLine'" + counter + "type='button' value='Remove' onclick=\"removeRow('" + counter + "')\" class='btn btn-primary' /></td>";
var newRow = "<tr id='qLineItem" + counter + "'>" + indexCell + qTextCell + removeCell + "</tr>";
$('#qTable').append(newRow);
};
function removeRow(id) {
var rowId = "qLineItem" + id;
var row = document.getElementById(rowId);
row.parentNode.removeChild(row);
};
</script>
}
What I end up seeing is that the remove button is treated as text in 3.5.1 but this doesn't occur with 3.4. I am unsure how to solve this issue or if I will need to figure out another way to write this page.
When I view the webpage and inspect the field I see it do the following:
<textarea id="QuestionList_0_Question" name="QuestionList[0].Question" class="Questions">
"</td><td align='center'><input id='btnDelLine'0type='button' value='Remove' onclick="removeRow('0')" class='btn btn-primary' /></td></tr></tbody></table>"
The textarea element should have a separate close tag. It is not allowed to self-close. So this is not valid HTML:
<textarea />
But this is:
<textarea></textarea>
Apparently, jQuery 3.5 is more strict in this. An inspection of the 3.5 changelog reveals that this is a consequence of the security fix they applied:
The main change in this release is a security fix, and it’s possible you will need to change your own code to adapt. Here’s why: jQuery used a regex in its jQuery.htmlPrefilter method to ensure that all closing tags were XHTML-compliant when passed to methods. For example, this prefilter ensured that a call like jQuery("<div class='hot' />") is actually converted to jQuery("<div class='hot'></div>"). Recently, an issue was reported that demonstrated the regex could introduce a cross-site scripting (XSS) vulnerability.
The HTML parser in jQuery <= 3.4.1 usually did the right thing, but there were edge cases where parsing would have unintended consequences. The jQuery team agreed it was necessary to fix this in a minor release, even though some code relies on the previous behavior and may break. The jQuery.htmlPrefilter function does not use a regex in 3.5.0 and passes the string through unchanged.
One can see how before 3.5, jQuery would actually change <textarea /> to <textarea></textarea> on the fly, thereby fixing the error you made. But now with version 3.5 jQuery no longer does that, and so your HTML remains invalid, leading to an unintended rendering where everything after <textarea /> ends up as content to that text area element.

get dynamic <td> value with $.ajax()

I have an $.ajax() request working properly, but i need to get 4 values(name, clientid, url, id) of < td >. $.val() doesn't work, because it only works on inputs.
I need to get the name, client Id , url and id from dynamically appended rows. I need those values so, when I click on the edit button of the selected row, it saves the changes I made.
How should I get the value? with $.html()? $.text()?
HTML
<div class="row">
<div class="col-md-12 overflow-table">
<table class="table" id="table">
<thead class="head-color thead-inverse">
<tr>
<th style="border-top-left-radius: 10px; border-left:1px solid transparent;">NAME</th>
<th>CLIENT-ID</th>
<th>URL</th>
<th style="border-top-right-radius: 10px; border-right:1px solid transparent;">ACTIONS</th>
</tr>
</thead>
<tbody id='table-redirect'>
<tr class='lightgrey'>
</tr>
<tr class='lightgrey'>
</tr>
<tr class='lightgrey'>
</tr>
<tr class='lightgrey'>
</tr>
</tbody>
</table>
</div>
</div>
JavaScript:
//change table content
$(document).on('click', '#editButton', function(e) {
var url = "http://mobisteinlp.com/redirect/redirect";
var name = $('#name1').val();
console.log(name);
var clientId = $('#client_id1').val();
console.log(clientId);
var redirectUrl = $('#url1').html();
console.log(redirectUrl);
var id = $('#hidden').val()
console.log(id);
var formData = new FormData();
formData.append('name1', name);
formData.append('client_id1', clientId);
formData.append('url1', redirectUrl);
formData.append('id', id);
console.log('test');
$.ajax({
url: url + "/editRedirect",
type: "POST",
dataType: "json",
data: formData,
contentType: false,
cache: false,
processData: false,
success: function(obj) {
var name, clientId, redirectUrl, id;
var rows = '';
$("tbody").empty('');
for (i = 0; i < obj.length; i++) {
rows += "<tr class='lightgrey'><th contenteditable='true'>" + obj[i].name + "</th><td>" + obj[i].client_id + "</td><td contenteditable='true' >" + obj[i].url + "</td><td><button type='button' id='editButton' class='btn btn-info'" + obj[i].client_id + "'><img class='col-md-2 edit nopad float-right' src='http://mobisteinlp.com/redirect/public/img/edit.svg'></button><a href='http://mobisteinlp.com/redirect/public/click.php/?id='" + obj[i].id + "'><img class='col-md-2 link nopad float-right' src='http://mobisteinlp.com/redirect/public/img/copy.svg'></a></td></td></tr>";
console.log('sucess!');
console.log(obj);
}
$("#table").append(rows);
},
error: function() {
console.log('error');
}
}); //END /editRedirect $.ajax()
}); //END $(document).on('click','#change',function(e)
The .text() method will return just the text within the element.
The .html() method will return the text, plus any HTML which might be contained within the element.
e.g. if your <td> looked like this for any reason:
<th class="clientID"><span>12345</span></th>
Then:
$(".clientID").text(); will return 12345
$(".clientID").html(); will return <span>12345</span>
So for your purposes you should use .text() to get just the actual text content to send to the server.
You can check all this in the jQuery documentation easily, as well, and by your own tests.
Now, to get a value within the specifically clicked row, you need to restrict by the row context in the markup. In the "click" event, this will be the button that was clicked, which is within the <tr>. The corresponding data is also within the <tr>.
So you can use the <tr> as the nearest element which encloses both the button and the data. Then if you give each <td> a class corresponding to what it represents (client ID, url, etc) as I've done above, you can do something like:
var tr = $(this).closest("tr"); //get the parent tr
var clientID = tr.find(".clientID").text(); //get the client ID text within the tr
var url = tr.find(".url").text(); //same for url, etc...
Lastly, your button clicks won't work properly because you're duplicating IDs. It will only ever work for the first button.
Change <button type='button' id='editButton' class='btn btn-info' to <button type='button' class='btn btn-info editButton' (use a class instead of an id)
and change $(document).on('click', '#editButton', function(e) { to $(document).on('click', '.editButton', function(e) { (simply, # is changed to .)
1) you appending multiple row with duplicate id . id should be unique for each element . just use class name instead of id .
2) appending one th and extra td
<th contenteditable='true'>" + obj[i].name + "</th>
Updated code with class name
` <tr class='lightgrey'>
<td contenteditable='true' class="name">" + obj[i].name + "</td>
<td class="client_id">" + obj[i].client_id + "</td>
<td contenteditable='true' class="url" >" + obj[i].url + "</td>
<td>
<button type='button' class='btn btn-info editButton'" + obj[i].client_id + "'>
<img class='col-md-2 edit nopad float-right' src='http://mobisteinlp.com/redirect/public/img/edit.svg'>
</button><a href='http://mobisteinlp.com/redirect/public/click.php/?id='" + obj[i].id + "'>
<img class='col-md-2 link nopad float-right' src='http://mobisteinlp.com/redirect/public/img/copy.svg'></a>
</td>
</tr>`
Jquery :
Setup class name for each td and traverse and access it easily like this
`$(document).on('click', '.editButton', function(e) {
var tr = $(this).closest("tr");
var client_id = tr.find(".client_id").text();
var url = tr.find(".url").text();
var name = tr.find(".name").text();
});`
Get the different between these commands, then you can fix your by yourself
The following used to retreive data from a value attribute(normally input tags).
//Here id is id name of your element
$('#id').val();
If you want to get the data from a element you need to use
1. This will return the text inside the element.
$('#id').text()
2. This will return the html inside the element.
$('#id').html()
Hope it helps you.
Try It...
$("#ObjectsTable").find("tr:gt(0)").remove();
var arr = $.parseJSON(data);
$.each(arr, function(index,value) {
$('#ObjectsTable')
.append($("<tr>" +
"<td>" + value.ID + "</td>" +
"<td>" + value.Model + "</td>" +
"<td>" + value.Type + "</td>" +
"<td>" + value.Color + "</td>" +
"<td>" + value.Price + "</td>" +
"</tr>"));
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
<table id="ObjectsTable" class="responstable">
<tr>
<th>ID</th>
<th>Model</th>
<th>Type</th>
<th>Color</th>
<th>Price</th>
</tr>
</table>

dynamically increase row size of HTML table in javascript

I am new to JavaScript and just learning the basics of it. I am doing a sample program and crated a javascript program to show some data in a html page inside div. but it is not dynamic. I have some values like name, addess, age and status of few staff and while log in with a user name showing the above details in html page. this is a simple program.
What i want to do is, i want to dynamically increase the size of the div or table where i can display details of use like address, age, status etc.. if some user has more details then i want to add that in the html page. how can i do it ??
in home.jsp i have the following code.
<table>
<div id="name1" width:400px;"></div>
<div id="address1" width:400px;"></div>
<div id="age1" width:400px;"></div>
<div id="status1" width:400px;"></div>
</table>
this is the function i use in home.js
function(json)
{
var content= $('#name1').replaceWith('<tr><td> Name: ' + json.name + '<tr><td>');
var content= $('#address1').replaceWith('<tr><td> Name: ' + json.address + '<tr><td>');
var content= $('#age1').replaceWith('<tr><td> Name: ' + json.age + '<tr><td>');
var content= $('#status1').replaceWith('<tr><td> Name: ' + json.status + '<tr><td>');
}
First you need to do a loop and in that
You have to use append() ex.
$( "#your_div_id" ).append( "<tr><td> your_label: ' + json.your_values + '<tr><td>'" );
Reference Link
First you need to change you HTML like,
<table>
<tr id="name1"></tr>
<tr id="address1"></tr>
<tr id="age1"></tr>
<tr id="status1"></tr>
</table>
And if your json is valid then you can use append() like,
$('#name1').append('<td> Name: ' + json.name + '</td>');
$('#address1').append('<td> Address: ' + json.address + '</td>');
$('#age1').append('<td> Age: ' + json.age + '</td>');
$('#status1').append('<td> Status: ' + json.status + '</td>');
Live Demo
You must read JQuery api Document.
url : http://api.jquery.com/append/
maybe you used .append(), .toAppend(), .prepand(), .after() etc..
code example(.after())
$('#table' tr:last).after('<tr><th width="10%">' + //your code here // + '</th></tr>');

jquery toggling elements for editing

Hi im trying to create an edit script in jquery that changes p content to input fields, and lets people edit them and then revert back to content.
my code:
<div class="addressblock">
<div class="data">
<p name="bedrijfsnaam">company name</p>
<p name="tav">to whom</p>
<p name="adres">street and number</p>
<p name="postcode">1234AB</p>
<p name="woonplaats">city</p>
<p name="land2" >Land</p>
</div>
Edit
</div>
Jquery =
$(document).ready(function () {
$(".editinv").click(function() {
var editid = $(this).attr("id");
var edit_or_text = $(this).attr("name");
if(edit_or_text == "edit"){
$(this).closest('div').find('p').each(function(){
var el_naam = $(this).attr("name");
var el_content = $(this).text();
$(this).replaceWith( "<input type='text' name='"+el_naam+"' id='" + el_id + "' value='"+el_content+"' />" );
});
$(".editinv").replaceWith( "<a href='#_' class='editinv' name='done' id='"+editid+"'>Done</a>" );
}
if(edit_or_text == "done"){
$(this).closest('div').find('input').each(function(){
var el_naam = $(this).attr("name");
var el_content = $(this).attr("value");
$(this).replaceWith( "<p name='"+el_naam+"' id='" + el_id + "'>'"+el_content+"' </p>" );
});
$(".editinv").replaceWith( "<a href='#_' class='editinv' name='edit' id='"+editid+"'>Bewerken</a>" );
}
});
});
When clicking on edit it changes perfectly to input fields and changes the edit button to a done button. A click on the done button is never registered though, while the class is the same.
Anyone got any ideas?
Thanks in advance!
EDIT: I created a JSfiddle of the problem http://jsfiddle.net/hBJ5a/
ITs quite simple, why doesn't the element accept a second click and revert back after already being changed?
Note that if you change the name of all the <p> tags to the same name, and try to revert them back, there is no way that javascript will know which value should go where.
You should add an additional parameter to your <p> tags that will indicate the type.
e.g.
<p data-type="text" name="bedrijfsnaam">compname</p>
when changed will turn into:
<input type="text" name="bedrijfsnaam" data-type="edit" value="compname" />
when you click the button to change back, you should simply use the same function you are currently using to change the <p>'s into <input>'s, but then reverse the order.
e.g.
function inputToParagraph() {
var inputs = $('input[data-type="edit"]');
inputs.each(function() {
$(this).replaceWith('<p data-type="text" name="'+$(this).attr('name')+'">'+$(this).attr('value')+'</p>');
});
}
ofcourse you should have other actions linked to your submit, an ajax request probably to update the database as well.
NOTE
Not tested, but do know that the function above, if all the attr's are specified will work.
It will directly replace the inputs with P tags with given attributes.
You will have to make sure when you make the <p>'s into <input>'s, you will have to make sure the inputs get the correct attributes as well.
<!DOCTYPE html>
<html>
<head>
<title>Test</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<script type="text/javascript" src="http://code.jquery.com/jquery-2.0.3.min.js"></script>
<script type="text/javascript">
var clickHandler = function() {
var editid = $(this).attr("id");
var edit_or_text = $(this).attr("name");
if (edit_or_text == "edit") {
$(this).closest('div').find('p').each(function() {
var el_id = $(this).attr("id");
var el_naam = el_id; //$(this).attr("name");
var el_content = $(this).text();
$(this).replaceWith("<input type='text' name='" + el_naam + "' id='" + el_id + "' value='" + el_content + "' />");
});
$(".editinv").replaceWith("<a href='#_' class='editinv' name='done' id='" + editid + "'>Done</a>");
}
else /* if (edit_or_text == "done") */ {
$(this).closest('div').find('input').each(function() {
var el_id = $(this).attr("id");
//var el_naam = el_$(this).attr("name");
var el_content = document.getElementById(el_id).value;
// Attribute "name" not allowed on element "p" at this point
//$(this).replaceWith("<p name='" + el_naam + "' id='" + el_id + "'>'" + el_content + "' </p>");
$(this).replaceWith("<p id='" + el_id + "'>" + el_content + "</p>");
});
$(".editinv").replaceWith("<a href='#_' class='editinv' name='edit' id='" + editid + "'>Bewerken</a>");
}
document.getElementById("00001").onclick = clickHandler;
}
$(document).ready(function() {
document.getElementById("00001").onclick = clickHandler;
});
</script>
<style type="text/css">
</style>
</head>
<body>
<div class="addressblock">
<div class="data">
<!-- Attribute "name" not allowed on element "p" at this point -->
<p id="bedrijfsnaam">company name</p>
<p id="tav">to whom</p>
<p id="adres">street and number</p>
<p id="postcode">1234AB</p>
<p id="woonplaats">city</p>
<p id="land2">Land</p>
</div>
Edit
</div>
</body>
</html>
Tested with Firefox 24.0 / Linux
try out jquery editable plugin
demo: http://www.appelsiini.net/projects/jeditable/default.html

How to fetch the id of dynamically generated textboxes?

How is it possible to get the id of the dynamically generated textboxes using jquery?. I need to fire the TextChanged event for the corresponging textbox. There is no method reference for the textboxes in the code behind.How can i refer to any method in the codebehind on firing the event. Somebody please help. I dont know jquery much. The entire script im using is as as follows:
<script type="text/javascript">
$(init);
function init()
{
$('#test').droppable(// Div Control
{
drop: handleDropEvent
});
$('a').each(function(idx, item) {
$(item).draggable({ cursor: 'move', helper: 'clone' })
});
}
$(function() {
$("#draggable").draggable(); //Nothing to do with this div
});
function handleDropEvent(event, ui)
{
var draggable = ui.draggable;
document.getElementById('test').innerHTML += addColumn(draggable.attr('text')) + '<br>';
}
function addColumn(column)
{
var iHtml;
// This code will generate a checkbox and a textbox. I need to fire the event of thus generated textboxes.
iHtml = '<div id="dv' + column + '" width="100px;" height="20px;" padding: "0.5em;"> ' + '<span title="ToolTipText">' + '<input type="checkbox" id="cb' + column + '" value="' + column + '" /> <label for="cb' + column + '">' + column + '</label></span><input type="text" runat="server" id="aln' + column + '"> </div>';
return iHtml;
}
</script>
There's two ways: keep the generated element, or generate an ID when you generate your new element.
a) keep the generated element
This requires that you don't use innerHTML, but create the element (with document.createElement, or with jQuery's $), and then you can use the element directly (no need to call it by ID any more). For instance, with jQuery:
var container = $('#container');
var myDiv = $('<div id="myDiv"/>');
var myCheck = $('<input type="checkbox"/>');
myDiv.append(myCheck);
container.append(myDiv);
b) generate the ID
container.innerHTML = '<div id="myDiv"><input type="checkbox" id="myCheck"/></div>';
// and after this you can get them by ID:
var myCheck = $('#myCheck');
I would just add a class to the textbox in your iHtml then use .live() event
replace your iHtml with this
iHtml = '<div id="dv' + column + '" width="100px;" height="20px;" padding: "0.5em;"> ' + '<span title="ToolTipText">' + '<input type="checkbox" id="cb' + column + '" value="' + column + '" /> <label for="cb' + column + '">' + column + '</label></span><input class="myclass" type="text" runat="server" id="aln' + column + '"> </div>';
then add the live event
$('.myclass').live('change', function() {
alert(' Live handler called.');
});
here is a WORKING DEMO

Categories