Javascript - get the form if of current control location - javascript

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.

Related

Fill an input field that is not of type text and that triggers events in CasperJS

I have to do automated tests on a website and I want to use CasperJS to learn. For proprietary reasons I can not give too much code.
Here is the example of the input that I am trying to fill:
<input data-bind="value: firstname, valueUpdate: ['blur'], css: {valid:(firstname.isValid() )} " title="" class="valid" aria-required="true" id="firstname" name="firstname">
As you can see, this input is not of type text and has no value attribute. Therefore, I can not use the casper.fill() method. Furthermore, if I enter the web page scope using evaluate() and change the input value using document.querySelector, the change will not be permanent as of the events attached to the text change on the input will not be triggered.
Here is my code:
this.waitForSelector('#memberTitle', function then(){
var testname = 'thisIsNotPermanent';
this.evaluate(function(testname){
document.querySelector('#firstname').value = testname;
}, testname);
});
If I capture the screen right after, I will see my text written in the input box. However, if I wait 500ms and take another capture, the text is gone as, I suppose, the events are triggered or just cleaned because it actually failed to trigger correctly.
The events attached to the input are of Blur, Change and Keypress.
Using CasperJS, how could I go to the lowest level possible to mimic a user using his keyboard and fully use the website's functionalities already in place?
The whole point of those tests are to work with what is in place. The idea is to not have to manually go through the JavaScript of the web site.
That's exactly what the casper.sendKeys(selector, keys) function is for which will send native keypresses and (hopefully) trigger the events on that text element:
this.waitForSelector('#memberTitle', function then(){
var testname = 'thisIsNotPermanent';
this.sendKeys('#firstname', testname);
}).wait(20, function(){
this.capture('screenshot.png');
});
<input> elements without a type attribute default to Text type.
This answer is here to complete the question from another angle. As Artjom B. mentionned, the correct way to fill an input and to trigger its events is by using the sendKeys() function. However, if you ever have a case, like mine, where the events will not trigger or will take a certain amount of time, know that you can trigger those manually.
If you use the firefox inspector tool, you will see that your input or tag will have an event attached to it marked as ev. If you select it, you will have a breakdown of all the events, in order, that are triggered.
You can see that the jQuery click() event will be called. In casperjs, from the evaluate scope you can now do this :
this.evaluate(function(){
$(".discard-answer").click();
})
From there, you can chain jQuery events, like in my case where I had to .blur().change().click();
It is important to know if the event is jQuery or not.
Hope this helps.

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.

Javascript Issue with IE 7 + 8

So I've been trying to get this script working in IE 7 & 8. The lack of support for getElementsByClassName was difficult to say the least, but i have filled support for that with a jQuery library.
My issue here is that the code shows no errors in any browser, yet the code does not run properly in IE. I've tested this in FF, Chrome, and Safari. All other browsers work fine, excluding IE.
I know semantics wise the code could be smaller (Trust me when get it working i will fix that.) But for now i need to figure out what is holding up IE.
jQuery(document).ready(function() {
var forms = jQuery('.form_item');
var firstFader = forms[4].getElementsByTagName('input');
var secondFader = forms[6].getElementsByTagName('input');
jQuery(firstFader[0]).click(function() {
jQuery('#nearSighted').hide('slow');
jQuery('#farSighted').show('slow');
jQuery('#astigmatism').hide('slow');
});
jQuery(firstFader[1]).click(function() {
jQuery('#nearSighted').show('slow');
jQuery('#farSighted').hide('slow');
jQuery('#astigmatism').hide('slow');
});
jQuery(firstFader[2]).click(function() {
jQuery('#nearSighted').hide('slow');
jQuery('#farSighted').hide('slow');
jQuery('#astigmatism').show('slow');
});
jQuery(secondFader[2]).click(function() {
jQuery('#presbyopia').show('slow');
jQuery('#cataracts').hide('slow');
});
jQuery(secondFader[3]).click(function() {
jQuery('#presbyopia').hide('slow');
jQuery('#cataracts').show('slow');
});
});
What this code does is take an array of all form items, then breaks two specific ones down into their individual input elements, when one of the elements is clicked it hides or shows a div that contains information about that specific condition. Any ideas?
Your click handlers aren't being called because your <input>s are styled display:none, i.e. they're hidden. Modern browsers are lenient because they see a <label for="id"> so they fire the click event as though it were the input itself (see http://jsfiddle.net/MMUyA/).
var firstFader = forms[4].getElementsByTagName('input')[0];
var secondFader = forms[6].getElementsByTagName('input')[0];
I see you're not actually clicking the input elements, but the label elements for those inputs.
It seems IE doesn't properly propagate the click event to the hidden input, therefor your .click() event never gets executed.
See also: IE - hidden radio button not checked when the corresponding label is clicked
The simple solution would to not bind the click() events to the input but to the label instead.
It looks to me like in IE7, the radio button input object has zero size and the label for it is what actually receives the click and displays the radio button. Perhaps you need to intercept clicks on the associated label in addition to the input field.

Javascript event for when a value is changed via 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>

How to simulate click on <input type="image" />?

when we submit a form using this type of input, the coordinates (x,y) are appended to the result.
it works if I dynamically create 2 hidden inputs, but I wanted something different.
Event or MouseEvent would be great, but I couldn't make it work
here's my current code: (it works fine)
var input = document.createElement("input");
input.type = "hidden";
input.name = "x";
input.value = posx;
my_form.appendChild(input);
input = input.cloneNode(false);
input.name = "y";
input.value = posy;
my_form.appendChild(input);
I'll give you an example of situation
Let's imagine that near to the image form element there is a plain text that says: Click in the image below in any position greater than 20 and lesser than 60
A normal person would read this and click normally.
But I need to, as a robot without hands, simulate the same click event
Without fully understanding what you are trying to do here (your question is a little vague, IMO), I have to ask this: Have you ever considered using jQuery or another javascript library/framework? I understand sometimes, for very simple sites, it's overkill. But, it might be worth it to relieve the headache of figuring this stuff out on your own.
From what I can understand, you are using an "image" form element to submit a form and you want to simulate a click on the image element to retrieve the x/y coordinates of something. I could be wrong. Could you be more explicit in your details?
I'll see if I can show you how to do it in jQuery when I know more about your problem.
I can't tell what you're trying to append the result to. The values in the form? This is automatic and requires no code (they come across and x and y, or elementname.x and elementname.y).
edited after comment:
You can avoid the node insert event by not making the elements at that time; ie add x and y to the form. Then on the event you can simply set their value. There are certainly different events you could bind this too, and I don't know your situation, but I made an example that uses an onClick event attached to the body of the page itself. You may want, instead, to bind specific onClick events to different clickable items and insert your own locations for them but in my case I submitted the location of the mouse on the page. If that's not helpful, make a comment about why and I'll see if I can mod it again.

Categories