Nick Sloan Nick Sloan - 1 year ago 64
Javascript Question

How can I lie to the user about the value of a text input using plain old JavaScript?

The Problem

I am the very definition of evil, and as such, I take great pleasure in lying to my users.

Presently, I am seeking a way to mislead these dumb fools with respect to the content of text input boxes. I want to display a value in the input box, while submitting a different value entirely. Additionally, I'd like to reward those users who are brave enough to inspect the element's value property with an honest response.

Those wily supervillains at Google have already done this internally in their own browser: (view in Chrome. Play with the input values)

Here is the JavaScript:

window.addEventListener('DOMContentLoaded', function() {
var date = document.getElementById('date');
var time = document.getElementById('time');

var show_date = document.getElementById('show_date');
var show_time = document.getElementById('show_time');

var display_real_value = function() {
show_date.innerHTML = date.value;
show_time.innerHTML = time.value;


date.addEventListener('change', display_real_value);
time.addEventListener('change', display_real_value);
date.addEventListener('keyup', display_real_value);
time.addEventListener('keyup', display_real_value);

The Details

As you will see in that example, the displayed value is totally detached from what is actually in the value property. I actually need to be able to programmatically modify both.

Finally, I'd like to implement this without jQuery, and without adding any additional DOM elements, nor making any assumptions about the context it will appear in. Limiting support to evergreen browsers is acceptable, though support for older browsers would be nice.

The Use Case

Since I'll undoubtedly be told that this is a bad idea or asked what I intend to use this for, I'll answer that now: My intention is to make a polyfill for date and time inputs that work very very similarly to Chrome's implementation, and which can be styled and scripted without the user having to know anything about how the polyfill works.

The Best Idea So Far

I suspect I might get somewhere with getters and setters, and storing the actual value on a different property of the object, but I haven't had any luck meeting all of my criteria.

Additional Explanation

The reason I don't want to add new, hidden DOM elements is because when the user wants to script the date input they've added, they have to look for the value of the hidden input instead of the one they actually added. I'd like to make this work as transparently as possible so that it as simple as adding the script and forgetting about it.

Here are some bullet points on what I need to do:

  • Programmatically update the string displayed in the input. I've been using setRangeText for this.

  • Programmatically update the selected portion of the displayed input. I've been using setSelectionRange for this.

  • Retrieve the modified value using element.value on the original input element.

  • Submit the modified value when the form submits.

Maybe this just isn't possible. That's fine if that is the best answer, but I'm hoping there is something I haven't thought of.

Answer Source

Based on your replies to comments under the question, here's what I think you want to do:

When the programmer using your polyfill applies it to an element, hide that element (e.g., = "none";) and put your own element(s) in its place to provide your UI. This is fairly standard practice; look at select2, for instance.

When the user of the page updates the value via your UI, you put the appropriate value in the field you hid.

The programmer using your polyfill doesn't have to know how it works; he/she just reads the value from the original field (again, with code, or by submitting the form the field is in).

There's some knowledge that programmer has to have: He/she has to know that if he/she wants to set the value of the field using JavaScript after applying your polyfill to the field, he/she should do that through your API, not by setting the value of the field directly. This is because there's no reliable, cross-browser event triggered when JavaScript sets the value of a form field. While you could poll, looking for updates, frankly that seems unreasonable. (Although I suppose if you had a list of all of your special inputs in the DOM, and checked the entire list once every 100ms or so, the performance impact would be negligible. But if the programmer is using your polyfill, it shouldn't be a big deal to set values through your API. I suppose you could offer both options.)

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download