Any way to do "real-time" unit conversion in web application - javascript

I want to build a website that allows the user to convert Hz to bpm (note however that my question concerns all sort of unit conversion). I am using PHP and am hosting my website on Apache.
So, I was wondering if it was possible to "bind" an input field to an HTML element, like we do in WPF developement where you can bind an input area to a WPF element, and apply some sort of data conversion so if the user types 12 bpm, the bound element will automaticly and immediately display 0.2 Hz. If the user then adds a "0" so 120 bpm will be automaticly and immediately converted to 2 Hz.
The effect I am trying to describe can also be noted on this very forum : as I type my question, I can see a "real-time" final version of my text.
How is this achieved? Is there any way to do it with PHP? I know of AJAX but I would really prefer to avoid using Javascript to hold my math functions. Correct me if I am wrong but I think this could be accomplished with Node.js? Should I consider migrating to Node?

With just the DOM and JavaScript, you can use the input event on a text field to receive an immediate callback when its value changes as the result of user action:
document.querySelector("selector-for-the-field").addEventListener("input", function() {
// Code here to do and display conversion
}, false);
Example (centigrade/Celsuis to Fahrenheit):
var f = document.getElementById("f");
document.querySelector("#c").addEventListener("input", function() {
var value = +this.value;
if (!isNaN(value)) {
value = (value * 9) / 5 + 32;
f.innerHTML = value;
}
}, false);
<div>
<label>
Enter centigrade:
<input type="text" id="c">
</label>
</div>
<div>
Fahrenheit: <span id="f"></span>
</div>
Stepping back, yes, there are dozens of libraries and frameworks that provide MVC/MVVM/MVM/whatever-the-acronym-is-this-week in the browser. A short list of current popular ones: React, Angular, Vue, Knockout, ... Note that these are not magic, they're just code written in JavaScript (or something like TypeScript or Dart or CoffeeScript that compiles to JavaScript) that use the DOM the covers.

I will give you an example of real-time "inches to cm" conversion.
Note for this example to work, you will need to include jQuery.
HTML:
<div>
<label>Inches</label>
<input type="text" id="user_input" />
</div>
<div>
<label>Centimeters</label>
<input type="text" id="result" readonly />
</div>
JAVASCRIPT:
$(document).ready(function(){
$('#user_input').on('propertychange input keyup', function(){
var thisVal = $(this).val();
$('#result').val(thisVal * 2.54);
});
});
Fiddle: https://jsfiddle.net/captain_theo/t10z01cm/
You can expand that for any type of conversion.
Check my updated fiddle that includes Hz to bpm also:
https://jsfiddle.net/captain_theo/t10z01cm/1/
Cheers, Theo

Related

Network gear scripts

As a long time network engineer, Javascript has been a challenge to say the least. I am looking to use HTML & Javascript to create a template used to make network gear configurations. The HTML portion is very basic. Just a form with input fields and a button:
<body>
<form id="form1">
<label for="siteCode">Site Code: </label>
<input type="text" id="siteCode" name="name" placeholder="ex. HEN" required="required"/><br>
A button is used to call a Javascript function named "makeConfig"
I am running into an issue when it tries to get the "siteCode" ID from the HTML:
var siteCode = document.getElementById("siteCode");
function makeConfig() {
var myWindow = window.open("", "MsgWindow", "width=1000,height=850");
myWindow.document.write("service nagle<br>no service pad<br>service tcp-keepalives-in<br>service tcp-keepalives-out<br>");
myWindow.document.write("service timestamps debug datetime localtime show-timezone<br>service timestamps log datetime localtime show-timezone");
myWindow.document.write("service password-encryption<br>service compress-config<br>!<br>");
myWindow.document.write("hostname P" + siteCode + "A01M01UAA<br>!<br>");
}
The last line always generates a null value for siteCode. I would think this is simple, but I am drawing a blank. Thank you in advance for any help!
siteCode will be a reference to the DOM (Document Object Model) node of the element; which contains a bunch of objects and properties that you probably don't want to print.
Instead; you probably want the the text that the user has entered into it. For that; you could do something like
myWindow.document.write("hostname P" + siteCode.value + "A01M01UAA<br>!<br>");
Notice we are getting it's value (siteCode.value); rather than just the raw element.
For something like this; another common mistake is that the JavaScript may be running before the rest of the page has loaded; and therefore the element may simply not have loaded yet. However, since you've put it in a function; I'm assuming that's not what happening here; and you're running it only when the user presses a button; etc. If not; that may be something to check.

Input field limit 9 char and after 3 char automaticly ads "-"

<input id="myText" type="text" placeholder="XXX-XXX-XXX" /></input>
<script type="text/javascript">
document.getElementById("myText").value.substr(0, 9).match(/.{1,3}/g).join("-");
</script>
There are a few problems with your current JavaScript. First, your script will only run once when the page is loaded, meaning any input you enter into myText after that will never be processed. Consider binding to an event of myText - for example, the onkeyup event.
Another problem is that your JavaScript doesn't take into account existing dashes when splitting the value of myText into 3-character parts - this results in undesirable behaviour, where more and more dashes will be added to the value, at seemingly random positions.
Lastly, as mentioned by Tushar in the comments, you need to set the value of myText to the new, processed value you create. Otherwise this value ends up being unused and discarded, and your code appears to do nothing.
Putting this all together, the fixed code might look like:
var textInput = document.getElementById("myText");
textInput.onkeyup = function()
{
var dashlessInput = textInput.value.replace(/-/g, "");
textInput.value = dashlessInput.substr(0, 9).match(/.{1,3}/g).join("-");
};
<input id="myText" type="text" placeholder="XXX-XXX-XXX" /></input>
Hope this helps! Let me know if you have any questions.
For future reference - try to clearly state what your question by explaining what you want to achieve, and specifically indicating what problems you're facing. This way, you're more likely to attract good answers rather than downvotes.

Multi-step form

i'm having a problem on how should i implement/build my form. here's the overview.
the first step of the form is to fill up the "Responsibility Center". however, the user can add multiple responsibility center. then the next step would be - each responsibility center added should have one or many "account codes". at the end of the form, before submitting it, all the data should be editable.
the result should be like this:
|**responsibility center**||**account codes**|
| center 1 || account code 1 |
| || account code 2 |
| center 2 || account code 1 |
etc..
i just need some idea on how the form should be built/implemented.
EDIT 1
This is what i've tried
1st step
2nd step
result
EDIT 2
i already know how to add multiple rows (like on the 2nd step) and i can implement that already on the first to the 1st step. so here are my questions:
how can i add account codes per responsibility center?
if what i've tried is not a practical way to implement it, then how should i do it?
Unfortunately, I began writing this answer before you posted the pics of your app. The ideas are still relevant, but I would have tailored my example more to what you are doing. Sorry about that.
I would use jQuery and AJAX to get the job done. jQuery to handle insertion of new elements to the DOM, and for field validation; AJAX to verify that no account codes are duplicated between RCs, or what have you. Personally, I would also use AJAX to handle the form submission instead of using the more traditional <form action= method=> because it gives greater control over the process and doesn't whisk the user off to another page before I am ready. However, it is easiest to describe the <form> example, and you can first build that and then change it over to using AJAX if you want.
The example from here is assuming a blank slate (i.e. I had not seen your sample app before writing this):
First, in your jQuery/javascript, you need a counter to keep track of each RC added. This can be in the <head> tags of your HTML/PHP, or it can be stored in a separate file. If you click on my name and look at other AJAX answers I've given, you'll see many useful examples.
<script type="text/javascript">
$(document).ready(function() {
var ctr = 0;
});
</script>
In your HTML, you need a DIV into which you will append each RC DIV. You also need a link/button/whatever for user to initiate creation of a new RC. This would be a brief form, even just [RC Title] and [Account Code] with a link/button/whatever to create another [Account Code] field and a [Done/Submit] button.
HTML:
<div id="container">
<form action="yourprocessorfile.php" method="POST" id="myform"></form>
</div>
<input type="button" id="mybutt" value="Add New RC" />
JAVASCRIPT/jQuery (again, inside the (document).ready() section above):
$('#mybutt').click(function() {
ctr++;
var str = 'RC TITLE:<br><input id="RC-"'+ctr+' class="RC" type="text"><br>ACCOUNT CODE<br><input id="AC-"'+ctr+' class="AC" type="text"><br>';
$('#myform').append(str);
});
When user presses [Done], use jQuery again to check that each [Account Code] field has been completed.
$('#done').click(function() {
$('.RC').each(function() {
if ($(this).val() == '') {
alert('Please complete all fields');
$(this).focus();
return false;
}
});
$('.AC').each(function() {
if ($(this).val() == '') {
alert('Please complete all fields');
$(this).focus();
return false;
}
});
$('#myform').submit();
});
Edit 2 / Question 1:
You can add new account codes linked to an RC by:
You need to somehow assign a unique data element to the RC, such as an incrementing ID
have a link for adding the new AC
use jQuery to get the ID of the nearest RC element
use .split() to split-off the numerical portion (assign to a var)
use that number when creating your AC
$('.add_AC').click(function() { //Note I used a class, so you can have a link for each RC
var num = $(this).parent().attr('id').split('-')[1];
var str = '';
});
In the above example:
==> Because I used a class, it will fire whenever ANY element with that class is clicked. Of course, when you create the button, you must add that class to the button def, as:
<input type="button" class="add_AC" value="Add Account Code" />
num ==> uses chained jQuery methods to, one-after-another, get the number portion of the RC's id.
$(this) ==> whichever [Add Account Code] button/link/whatever was clicked on.
.parent() ==> This may or may not be correct for your situation. This is the part where we traverse the DOM to find the RC element's ID code, which would look like this: RC-3. You will need to experiment with:
.parent().parent()
.sibling()
.parent().sibling()
.closest()
.prev() or .next()
Play with these selectors, with Dev Tools window opened. It should only take a handful of minutes to find your RC element -- or ask another question and post your HTML.
.attr('id') ==> Obviously, returns the text of the ID, in our case RC-3
.split('-')[1] ==> Creates an array with RC on one side (zero), and 3 on the other (1)
Hopefully this all gives you some idea of where to begin...

How to identify if user is typing in RTL or LTR language?

I want imitate google's input,
It automatically change input's typing direction based on the language you're typing in.
How can I identify if user is typing in RTL or LTR language?
It must work cross-browser.
You should use the attribute dir="auto"
e.g.
<html dir="auto">
This way the browser will look at the first strongly typed character and adjust the text automatically.
For reference, here is the W3C documentation on this: http://www.w3.org/International/tutorials/new-bidi-xhtml/qa-html-dir
If you want to mimic Google's directionality recognition algorithm, you will need to listen to input change, recognize whether the character inserted was RTL or LTR (or neutral) and change the textbox's dir="" attribute accordingly.
Google's algorithm, for the most part, seems to calculate the majority of strong characters in the string and decide the directionality from that. If you type RTL it will switch the context to RTL, and if you then switch to LTR for the same paragraph, it may switch the context again to LTR if those characters outnumber the RTL ones.
For comparison, Facebook uses a direction algorithm as well, but it is slightly different - it seems to use the first strong character to decide the direction of the paragraph rather than the overall number.
(For the record, Google also seems to have several algorithms for this; Gmail behaves slightly differently than Google Hangouts which is different than how the input in Google search is aligning itself. In these things, there are mostly no "right" or "wrong" answers but rather what fits your use case)
Whichever method you choose to implement, you first need to identify what the user is typing. There are several ways to do this, but I would recommend the following:
Read a little about Unicode BiDirectional Algorithm (especially about "strong" type characters) http://unicode.org/reports/tr9/
Find a good way to identify strong characters in your context. An example of a regex to do that can be found in MediaWiki's Language file (where group 1 is LTR and group 2 is RTL): https://github.com/wikimedia/mediawiki/blob/6f19bac69546b8a5cc06f91a81e364bf905dee7f/languages/Language.php#L174
You can create a JavaScript method that listens to the user's input, uses the regex above to identify which strong character is used (either by first character or by counting them all, whichever works best for your use and scale) -- and change the textbox's dir="" attribute accordingly.
Make sure you later display the submitted text with the correct alignment later, so you may have to either use something to store the alignment you picked or to re-recognize whenever you render it. Either way, don't forget that the display needs the same dir="" attribute as well.
Too late but maybe it can help someone one day.
This function will add direction attribute to the input field based on the first inputed character, and when user clears input text the function will detect the new language of text again.
$.fn.set_input_direction = function()
{
$(this).off('keypress').on('keypress',function(e){
_this = $(this);
setTimeout(function()
{
if(_this.val().length > 1){
return;
} else {
var rtl_regex = /[\u0591-\u07FF\uFB1D-\uFDFD\uFE70-\uFEFC]/;
var is_rtl = rtl_regex.test(String.fromCharCode(e.which));
var direction = is_rtl ? 'rtl' : 'ltr';
_this.css({'direction' : direction});
}
});
});
};
To use it:
$('input').set_input_direction();
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<html>
<head>
<script>
function checkRTL(s) {
var ltrChars = 'A-Za-z\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02B8\u0300-\u0590\u0800-\u1FFF' + '\u2C00-\uFB1C\uFDFE-\uFE6F\uFEFD-\uFFFF',
rtlChars = '\u0591-\u07FF\uFB1D-\uFDFD\uFE70-\uFEFC',
rtlDirCheck = new RegExp('^[^' + ltrChars + ']*[' + rtlChars + ']');
return rtlDirCheck.test(s);
};
// BIND KEYPRESS
var input = $('input').on('keypress', keypress)[0];
function keypress(e) {
// need to wait for the character
setTimeout(function () {
var isRTL = checkRTL(String.fromCharCode(e.charCode)),
dir = isRTL ? 'RTL' : 'LTR';
input.style.direction = dir;
}, 0);
}
</script>
</head>
</body>
<h1>Auto Direction
<sup>(RTL | LTR)</sup>
</h1>
<input type="text" onkeypress="keypress()" placeholder="Type something…" />
</body>
</html>

Simple Maths with jQuery - division

I've got two inputs in a div that I want to divide one by the other.
<div>
<input type="number" id="a"> / <input type="number" id="b">
<input type="submit">
<p class="result">RESULT HERE</p>
</div>
How can the maths of this be done with jquery?
It really depends when you want the calculation to take place, but the maths itself is incredibly simple. Just use the standard division operator, /:
var num1 = $("input[label='a']").val(),
num2 = $("input[label='b']").val(),
result = parseInt(num1, 10) / parseInt(num2, 10);
$(".result").text(result);
I guess it also depends if you only want to support integer division (that's why I've used parseInt - you could use parseFloat if necessary).
Also, as mentioned in the comments on your question, label is not a valid attribute. A better option would be to use id, or if you need to use an arbitrarily named attribute, use HTML5 data-* attributes.
Update based on comments
As you have stated that you want the code to run when a button is clicked, all you need to do is bind to the click event:
$("#someButton").click(function() {
//Do stuff when the button is clicked.
});
You're mixing your markup with your logic. You can't divide HTML elements with each other they are for structural presentation only. Instead, you have to pull their values with javascript, apply the math, and update the HTML with the resulting value.

Categories

Resources