Javascript event for when a value is changed via javascript - javascript

So I know several varieties of this question have been asked in the past but I just want to see if anything has changed with html5 and everything.
Basically, I have web based forms that have events for when they change. (Via onchange, onclick, ect). Now these forms actually store their values in a javascript variable. I realize how I am doing this is different and I could just be checking the fields at a later time for the changes. However, because of the application I am building, having the immediate events is necessarily.
The problem I am having is that things like password managers (and I am assuming plugins like roboform) change the values of the form fields via javascript. When javascript changes these values, it doesn't fire the events that I am currently using.
Now I know that IE has a proprietary function called "propertychange". Firefox also has a similar function called "DOMAttrModified" (which I believe also is kind of supported in IE9 now). Each of these, I believe, would work because I could actively watch the value of the field and this event would be fired when javascript changes the value. However, both chrome and safari don't seem to have a similar function.
My main question is if I am missing anything that would allow this to work in chrome and safari (without using settimeout)? Also, is there going to be a way to do this in HTML5? It seems a little silly to me that there isn't a standard way to do this.
Lastly, is it possible to instead STOP things like lastpass from actually filling in your fields. I know you can put autocomplete="off" and they are supposed to not actually fill in those fields but that doesn't seem to be working with lastpass.

Firefox has a non-standard Object.watch() method that allows you to know when a property is changed from JavaScript - see https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Object/watch. From all I know, no other browsers chose to implement it because of performance implications.
For Chrome you are out of luck I think - they even chose to not implement DOM mutation events to get a better performance score. You can only resort to polling there - e.g. check the value every 100 milliseconds to see whether it changed. Safari supports DOMAttrModified but it might not fire in this scenario (depends on whether the password manager actually changes the attribute or only the property).

Both Safari and Chrome support DOMSubtreeModified, you can listen for it and then check for the specific attribute if the DOM subtree of the element doesn't get much changes otherwise.
Alternatively, you might try using Javascript setters (via Object.defineProperty).

Perhaps something like this (plain JS)
<script>
var tId=[];
window.onload=function() {
var inputs =document.getElementsByTagName("input");
for (var i=0, n=inputs.length;i<n;i++) {
if (inputs[i].className.indexOf("watch") !=1) {
inputs[i].onfocus=function() {
var id = this.id;
tId[id]=setInterval(
function(){
var fld = document.getElementById(id);
if (fld.value!=fld.defaultValue) fld.onchange()
},100);
}
inputs[i].onblur=function() {
var id = this.id;
clearInterval(tId[id])
}
}
}
}
</script>
<form id="form1">
<input type="text" name="field1" id="field1" value="" class="watch"/>
</form>

Related

How to modify input while typing and make Blazor see the changes

I have an input element. I added some filtering and modifying the text while typing using JavaScript keydown and keypress events.
For example - when an input accepts upper case characters, when you press just "a" (no shift, no caps lock), you get "A".
This works, however input value binding doesn't work at all. I just call preventDefault() on the JS event and that's it, binding is broken.
I tried to dispatch the event myself. I dispatched newly created KeyboardEvent and CustomEvent with type "change". Nothing works. I can modify input value in JS event handler, I see the changes in browser, however my C# doesn't.
How can I make this work? Do I have to invoke C# manually to update the binding, or is there another way?
The code should work just on latest Chrome / Firefox browsers, older browsers may be unsupported.
Why don't you do in in Blazor code? In you markdown:
<input type="text" #bind-value="MyParamenter" #bind-value:event="oninput" >
and in code
private string myParameter;
private string MyParameter
{
get => myParameter;
set
{
myParameter = value.ToUpper();
}
}
Maybe, this answers your question. In, short, when you want to handle the TextChanged event you could do something like this:
<MudTextField Label="Some Label Text"
T="string"
Value="person.FirstName"
ValueChanged="(value) => person.FirstName = value.ToUpper()"
Immediate="true" />
The "trick" is to split the #bind-value in two: Value and ValueChanged. Then in the ValueChanged you can do whatever you want with the power of C#.
Note that Blazor abstract the JS side from us, with some experience, I learned to stay away from JS side as much as possible when developing with Blazor and it saved me from a lot of headaches.

Keep cell color changed with checkbox on refresh

I have cells changing background color on checkbox check and I worked out how to keep the checkboxes checked on refresh (though looking back I don't think that works anymore), but I don't know how to keep the color change on refresh. I don't actually know Javascript at all and this is all from other questions but I want it to work. If I've done something completely wrong please correct me and don't assume I did it on purpose because I have absolutely no idea what I'm doing.
$(document).ready(function() {
$(".colourswitcher").click(function() {
if($(this).is(":checked")) {
$(this).closest("td").css("background","#ff3333");
}else {
$(this).closest("td").css("background","#202020");
}
});
});
$(function(){
var test = localStorage.input === 'true'? true: false;
$('input').prop('checked', test || false);
});
$('input').on('change', function() {
localStorage.input = $(this).is(':checked');
console.log($(this).is(':checked'));
});
Since you're new to javascript, I'm going to ask the dumb question: Have you included jQuery?
This code that you've pulled makes use of jQuery, a very useful library (not built-in to javascript) that has become so commonplace that people often don't even state its name when asking or answering a question involving it. But anytime you see that $ notation, you're probably dealing with jQuery.
You need to include the library file in your html file so it knows what those special symbols and syntax are:
<script src="http://code.jquery.com/jquery-2.1.1.min.js"></script>
If you're testing this stuff in Google Chrome, press F12 and view the developer console. You will see "undefined" errors in red when you are missing things like this.
Here's another answer assuming you have a better working knowledge than my first answer:
The first bit of your code runs when the html document has loaded and attaches an event listener to change the nearest cell background color accordingly when the checkbox is clicked. Note two things here though. 1) that behavior will be attached to all html elements with the class "colourswitcher", not just inputs. 2) that behavior assumes that what was clicked has a property "checked", which only a checkbox does.
The middle bit I presume is supposed to run once, when the page is first loaded, to get the saved state of the checkbox from localStorage. This bit could be moved into the document ready bit.
The third bit of your code attaches an event listener to every input element (not just checkboxes) such that every time one is clicked, a checked true/false state will be saved in localStorage.
localStorage is a convenient way to save information between browser refreshes. You can save anything you want, ie. localStorage.CandyCanes = 7 and that variable will be stored in the user's browser and can be recalled later. Note that your above code will only work as intended if there's a single checkbox, because you're using one slot, or one variable, in localStorage to save: localStorage.input.
That's all I'm going to elaborate on this for now. If this is more than you expected, then it's time to hunker down and learn, or get a professional involved.

How can I exclude controls from making form Dirty?

I'm using this: $('form').dirtyForms(); from https://github.com/snikch/jquery.dirtyforms to check if my form is dirty. However, on my page I have some dropdown's that are simply used for filtering (they should not make my form "dirty"). Right now when I select any of these drop down's it causes my form to become dirty. Using jquery.dirtyforms (I read their docs but do not see how), how do I exclude selectors (dropdowns, textboxes, etc.) maybe via a class name so that they do not mark the form as dirty.
I tried various things like assigning these dropdowns / filters a class called ignoreDirty then in my jquery I did this:
$('form').dirtyForms().ignoreClass('ignoreDirty');
This produces an error, so I must be doing something wrong.
Note I've also tried setting it via property:
$('form').dirtyForms({ ignoreClass : "ignoreDirty" });
But this still makes my form dirty for any control whose class name is still ignoreDirty
Please note these filters cause postbacks but lets say I go to my form and have not made a single change. I start clicking on these filters and the minute they post back this happens:
What can one say, the plugin code makes almost no sense to me :D However to make it quickly work for ignoring select boxes, you could replace its onSelectionChange with following
Original function
var onSelectionChange = function() {
$(this).dirtyForms('setDirty');
}
New version
var onSelectionChange = function () {
//this is the new line. self explanatory
if ($(this).hasClass($.DirtyForms.ignoreClass)) return;
$(this).dirtyForms('setDirty');
}
After this you should rely on the original developer for a proper fix. I just posted this as an answer because of space in comments
There seems to be 2 different issues here.
First of all, you are attempting to set the ignoreClass to ignoredirty. ignoredirty is the default value, so there is no reason to set it. However, if you do need to set it to something else, you can do so using the syntax:
$.DirtyForms.ignoreClass = 'my-ignore-class';
Secondly, in version 1.0.0 the ignoreClass only worked on Hyperlinks. This behavior has been amended to work with input and selection elements in version 1.1.0.
In version 1.2.0, you can now also set the ignoreClass to parent container elements to ignore input or clicks from any element within.

JavaScript return false not stopping form submission

We've got some code like this that has been working for some time. It's for a button that submits an html form, unless a nearby textbox is empty. I've taken this snippet directly from our code; I've changed the contents of the fields, but haven't deleted anything.
<input
type="image"
name="inputName"
id="inputId"
src="someImage"
alt="altText"
onclick="
javascript:var obj = document.all ? document.all["aTextInputFormFieldId"] :
document.getElementById("aTextInputFormFieldId");
if(obj.value.length == 0)
{
alert('It is 0!');
return false;
};"
style="someStyle" />
(The original code is all on one line, but linebreaks have been added here for clarity).
It seems to work perfectly in Firefox. But in IE, it fails in a way that I can't understand: if the input field (aTextInputFormFieldId) is empty, it puts up the alert, but then submits the form anyway after the user clicks the okay button on the alert.
When I did a view source on the entire page, and copied it locally, it seems to work perfectly; it either submits the form, or puts up the alert, and then refuses to submit.
My best current (but still lousy) theory is that one of the included JavaScript libraries is doing something funny, which would explain why it failed on the real site, but fails when I copy it locally (since I didn't grab the various libraries it's importing.) This makes logical sense, and I'll check it out by grabbing the libraries too, but I'm having a hard time imagining what these libraries could be doing to mess this up (or why)...they're just normal utility libraries like jquery, utility functions, etc.
So does anyone have a theory about what could be happening here?
You mentioned jQuery, jQuery can interfere with your form if it is doing anything through its submit() handler. Check to see if jQuery.submit() is bound to your form.
Usually when doing pure javascript it is not enough to return false. Depending on what you want to accomplish you might want to look at preventDefault or stopPropagation
When working with Internet Explorer be aware that the event object is not passed to the function but can be found in window.event instead.
Update
Internet explorer might want you to use event.returnValue = false; instead. In your case that would be window.event.returnValue = false; when targeting IE.
Good luck
Javascript protocol links have to be one line, ie. no new lines.
onclick="javascript:var obj = document.all ? document.all["aTextInputFormFieldId"] :document.getElementById("aTextInputFormFieldId"); if(obj.value.length == 0){alert('It is 0!'); return false;};"

Javascript - get the form if of current control location

I have a form and it has 4 input elements. if the user enters just two entries and clicks anywhere on the screen (out the form)...i would like to save the details..it is like auto-save.
I have id of my form..i want to compare with form id of the current control on the screen..so that i can ssave the data if both form ids are different..
could you please tell me how can i get the form id of current control location on screen (some times the control could be outside the forms..in that case form id of current cotrol location would null)... but how can i determine that in javascript.
please suggest...
Many Thanks in advance,
Jack.
That's an interesting question.
Well, if you didn't think a second (as I admittedly did), you would just hook on the blur event of the HTML <form> element in question.
<form onblur="autosave(this)">
However, the HTML <form> element doesn't support that event. Too bad.
I then thought about jQuery's new 1.4 focusout() event.
$('form').focusout(function() { autosave(this); });
Unfortunately that event get fired as well when you just jump (tab, click) to the next input field inside the same form. Not so nice, it'll probably be too expensive to autosave on every fieldjump. The same effect as with an $(':input').blur(function() { autosave(this.form); });.
I then tried the other way round using focusin():
$('form').focusin(function() {
$(this).addClass('focused');
});
$(':not(form)').focusin(function(e) {
if (!$(e.target).parents('form.focused').length) {
var form = $('form.focused').removeClass('focused');
autosave(form);
}
});
Strangely enough this works in IE only and not in the other browsers. It'll be another IE bug/quirk that focus is supported by all elements other than input elements.
Your best bet will probably be hooking on the click() event instead.
$('form').focusin(function() {
$(this).addClass('focused');
});
$(':not(form)').click(function(e) {
if (!$(e.target).parents('form.focused').length) {
var form = $('form.focused').removeClass('focused');
autosave(form);
}
});
This works fine. You can find here a live demo.
Note that I don't mean to push you jQuery (a JS library which insanely eases HTML DOM traversion and manipulation) through your throat or so, but I don't see nice ways in plain JavaScript to achieve this without writing 10 times as much as code here.

Categories