Magento - opcheckout.js - manually calling setAddress() during checkout - javascript

I've added PO Box filtering per this short tutorial:
http://inchoo.net/ecommerce/magento/prevent-po-boxes-in-shipping-address-field-on-checkout/comment-page-1/#comment-35117
Essentially, this simply calls my controller, does a preg_match on the 'street1' and street2' fields, and gives an alert if a PO Box address is entered, else it just calls shipping.save() and goes to the next step.
The problem is that if a user has a PO Box address saved (and this is not the default address), when you select the alternate address (with the PO Box), the hidden form fields aren't updated with the selected address, and the PO Box validation does not get called.
In an attempt to remedy this, I am firing shipping.setAddress(value) when the select element is changed:
jQuery("#shipping-address-select").change(function(){
var value = jQuery("#shipping-address-select option:selected").val();
shipping.setAddress(value);
});
This works almost entirely as expected, it sets the address to what I expect, and everything is nice and wonderful; however, a small glitch that occurs here is that after calling shipping.setAddress(value) (which performs an ajax call), the select element automatically will display the 'New Address' option after I've chosen an actual address. This is purely a visual glitch, as the correct address is used, but having it show 'New Address' will be confusing to users.
Is there a way to remedy this without resorting to modifying anything in opcheckout.js (where the Shipping class and setAddress() bits reside)?
-- edit --
This is Magento Professional - 1.11.1.0

While certainly not an optimal solution, in the meantime I have had to resort to updating the hidden form fields manually using:
jQuery("#shipping-address-select").on('change',function(){
var address = jQuery("#shipping-address-select option:selected").html().split(', ');
jQuery("#shipping\\:street1").val(address[1]);
jQuery("#shipping\\:street2").val(address[2]);
});
I am so proud of this code. /sarcasm.

Related

Simulate sending data to the text input field with JS

I have a task where I need to automate Sign in form authentication. For this example, I'll show you Tiktok authentication form (Mobile interface, not desktop. E-mail and password option)
If I enter text values into the fields programmatically, the Login button won't become active, and if I manually focus on the fields with a mouse click, the value disappears. These are two lines of code I run to put the value in:
let email_input = document.getElementsByName("email")[0];
email_input.value = 'sample#email.com';
I understand it needs to trigger a certain event to assign a value into it's JS model, but I can't figure out how to do it. I have tried sending change or input events onto this text field with no luck using this code:
let email_input = document.getElementsByName("email");
email_input[0].value = 'sample#email.com';
custom_event = new Event('input');
email_input[0].dispatchEvent(custom_event);
// tried also change, textInput like so:
custom_event = new Event('change');
email_input[0].dispatchEvent(custom_event);
But this does not seem to help.
So my goal is to put values into both fields Email and Password in the way it will be detected and Log in button would become active.
Any suggestion would be much appreciated
You should first focus needed input element and then execute document.execCommand with insertText command:
let email_input = document.getElementsByName("email");
email_input[0].focus();
document.execCommand('insertText', false, 'sample#email.com');
With this method input\textarea value modification should be captured by all major frameworks including Angular and Vuejs. This modification will be processed by frameworks the same way as if user pressed "Paste" option in browser main menu.
It all depends...
Who/what are you? A normal browser user? A bot? The browser author?
Because code like this is useless...
let email_input = document.getElementsByName("email")[0];
What document are you referring to? Who's document? Did you inject this instruction into the page and executed it?
You're not telling us where you're coming from, but anyway...
If you are the browser author, or you can run JavaScript macros from your browser (ie: the Classic browser) then you can do something like this...
var Z=W.contentWindow.document.querySelectorAll('input[type="password"]');
if(Z.length>0){
Z[0].value='password123';
Z=W.contentWindow.document.querySelectorAll('input[type="email"]');
if(Z.length>0){Z[0].value='email#abc.com';}
}
To automatically populate such fields, and if you also want you can SubmitButtonID.click() the submit button for as long as the isTrusted property is not tested by the website.
Continued...
Test if normal (non-custom) submit button exists and click...
Z=W.contentWindow.document.querySelectorAll('input[type="submit"]');
if(Z.length>0){
if(Z[0].hasAttribute('disabled')){Z[0].removeAttribute('disabled');} <--- Enable it if disabled
Z[0].click(); <--- automate click
}

Pre-loading text in textarea for user to edit and submit shows text briefly then blanks out. Why?

I'm writing an edit function (plain javascript & HTML / Chrome / Windows 10).
The data is in localStorage as a series of records, just 2 records in the toy code mentioned below.
I want the user to specify the number of the record to edit, then the code should pre-fill the textarea field with the retrieved content of that record. I want to allow the user to make changes and then press a Store button to store it back in localStorage.
My problem is that when I prefill the input field, I see the record content briefly and then the input field clears. I've tried .value and .defaultValue
editField.value = localStorage.getItem('jnl' + locStoreNo).replace(/(.*?) `\d*?`/, "$1");
and
editField.defaultValue = localStorage.getItem('jnl' + locStoreNo).replace(/(.*?) `\d*?`/, "$1");
the result is the same. (The regex is to hide a sequence number)
The code is in a JSFiddle here: https://jsfiddle.net/roygrubb/zxedbfqr/2/
That performs more or less the same - it shows the value briefly - but then does something different: It goes to a 404. I don't understand this either ¯_(ツ)_/¯
What I'm trying to do seems so basic, that I think I must be missing something blindingly obvious.
What have I missed? Thanks!
Whenever you've got a <form> that you want to handle through JavaScript, you have to ensure that the default form submission action does not happen. If the <form> does not have an "action" attribute, the default is to reload the current page.
By default, a <button> element will be assumed to have "submit" as its type. To prevent form submission, therefore, the simplest thing to do is make the button have "button" as its type.
That may not be all you need to do, depending on the details of the form. It may be necessary (or simply a good defensive move) to have a handler for the "submit" event on the form to prevent the default action.

Javascript execution order affecting autofill workaround

This question is specifically about a problem that I am having with our site's attempt to compensate for Chrome's insistence on performing autofill when it should not.
Please note: this question is not specifically about the autofill issue, which is well-documented over the course of several years. For example, here are some useful pages that cover that issue:
​Disabling Chrome Autofill​
​https://developer.mozilla.org/en-US/docs/Web/Security/Securing_your_site/Turning_off_form_autocompletion
Chrome autofills username into random text input
https://bugs.chromium.org/p/chromium/issues/detail?id=914451#c53
​https://github.com/alphagov/accessible-autocomplete/issues/325
Over the years we have used several solutions similar to the ones documented in the above articles, especially the first article.
As developers have developed workarounds, the Chrome team works to disable the workarounds. At present I don't know of any workaround that is effective any more. The Chromium team apparently believes that any form with a password field is a login form, and it does not want to easily allow the ability to edit passwords, while retaining the automatic obfuscation feature.
In any case, I re-iterate that I am not specifically focusing on the autofill problem, but rather some issues I am having countering it.
We have successfully countered the issue on some of our edit pages, but don't have a complete solution, due to the following issue, which is the heart of this question.
The issue is that because the fields in question are email adddress (username) and password, there is other javascript on the page, which is fairly complex. The purpose of that javascript is to help the user with such functions as the following:
Make sure that the entry meets certain basic validations.
Make sure that an email address is not already used in our database.
Make sure that the entry does not violate certain other policies, such as using first name, last name, etc. as a password.
Quite a ways back one of our measures that was in part to counter browser autofill was to make the email address and password fields hidden, and only displayed after the user clicks a button with a label like "Change Email Address". This had some beneficial user impact that I will not detail, but also stopped Chrome from autofilling.
Recently however, Chrome has started autofilling even the hidden fields. So when the button was clicked and the fields revealed, there was data populated into the email address. However, the data populated was the userid rather than an email address, because we allow logging using either userid or email address, and with certain Chrome settings, the userid was saved.
The next step in dealing with this "feature" was to add a line of jquery to clear the contents of that field when the button is clicked, and if the button is not clicked, to have the update routine ignore the bogus autofill.
The actual problem that is happening is that somehow, it appears that Chrome is inserting the value back into the DOM. Other works seems to show that Chrome will perversely and continually attempt to perform the autofill every time the DOM changes.
So here is the sequence of apparent events that I have not yet solved:
User visits his profile page.
Chrome autofills the hidden username.
User clicks "Change Email Address"
jquery uses val('') to clear the contents of the field.
There is an onblur validation on the email address field that should not be triggered yet, because the field is not blurred. In fact, the cursor is not yet even placed into the field--the user has to do that. The reason we know the validation occurs is because immediately we get an error message about the invalid email address because it is a userid format rather than an email address format.
There are two "impossible" things going on here.
A validation is occurring that seems there is no way it could be triggered.
We have cleared the field using jquery. But the the validation (which should not be happening) is still seeing the original autofilled and invalid content.
A theory that might explain this is that when the field is displayed, the focus quickly goes into that field before the javascript has had time to actually clear the DOM, and that the focus leaves the field before the eye can see that it went into the field, thus triggering the validation, again before the jquery has had its effect.
So the theory might be that the sequence of events is gain focus, lose focus, trigger the onblur validation, clear the field. This would produce the observed effect.
So the question specifics are the following:
What is causing the focus to be gained and lost?
Why is this happening before the clearing of the field, which happens when the fields are made visible?
Yet a further theory might be "javascript handles events not in the order that it appears, but rather some other predetermined order". I have seen some information about that, but I don't know how to control this to solve the problem.
Here are some code snippets. You will note that a number of the previously-working autofill blocking tactics are still in place:
onblur=ValidFirstField()
<input type="password" autocomplete="new-password" name="password1" id="password1" size="20" maxlength="$MAX_PASSWORD_LEN" onkeydown="clearMessage('pw_message'); displayMessage('pw_strength');" onkeyup="chkPass(this.value);" onblur="ValidFirstField(this, 'Password', $MIN_PASSWORD_LEN, $MAX_PASSWORD_LEN, ValidPasswordSafety, ['$companyname', '$fname', '$lname', '$email1', '$email2'], 'pw_message', ' not allowed; please choose another.', 1, 'password2' );" >
validation Please note: the line of code with fieldname + ' must be between ' is the validation that is triggered out of sequence:
function ValidFirstField(field1, fieldname, minlen, maxlen, cfunc, aProhibited, msg_field, bad_msg, common_msg, mark_field)
{
if (!field1.value.length)
{
return;
}
var login_prompt = document.getElementById('login-prompt');
if (login_prompt)
{
login_prompt.style.display = STYLE_NONE; /* clear in case set via ajax */
}
var msg = document.getElementById(msg_field);
msg.innerHTML = '';
var allowSubmit = true;
if (field1.value.length < minlen || field1.value.length > maxlen)
{
msg.innerHTML = fieldname + ' must be between ' + minlen + ' and ' + maxlen + ' characters: ' + field1.value.length;
allowSubmit = false;
field1.focus(); // TODO temporarily suppress to prevent focus/onblur race in IE
}
...
jquery that displays the fields and clears the content
$('#show-email').click(function()
{
chg_email_clicked = true;
$('#chg-email-clicked').val(1);
// alert('chg=' + chg_email_clicked);
$(this).hide();
// from https://stackoverflow.com/questions/15738259/disabling-chrome-autofill mike nelson
var $chrome_fake = $('.chrome-fake');
$chrome_fake.show();
window.setTimeout(function ()
{
$chrome_fake.hide();
},1);
$('#email1').val('');
// var testemail1 = document.getElementById('email1').value;
// alert(testemail1);
$('.hide-email').show();
});

How to trigger onchange method when field is being filled from JavaScript?

Problem is very simple. I am using certain API which is called when I click a button and some of the fields are being filled from a widget that I created
I use that widget at multiple places in my system
The problem is that when those fields are filled I need
#api.onchange('exmplple')
method to trigger them, but it doesn't (I would say it's a bug).
What would be the workaround or solution to trigger that method when those fields change whenever my widget works?
Update:
Sorry for the confusion that my question caused. I will try to explain what exactly I was thinking and why I only have tried server side things so far. The problem is that in any other situation python code api.onechange would work completely fine.
#api.onchange
def do_smth_when_country_changes(self):
if country_id = 133
self.lang = 'pl_PL'
elif:
.......more ifs
But I have fields which are filled from google maps (JavaScript code that I wrote).
<field name='autocomplete' widget='gmap_autocomplete' country_id='country_id'>
<field name='country_id'>
Here when i search for address with autocomplete field, and i click on one, country_id field will be filled with country. And Also there are some other field has to change value whenever country_id changes (for example res.partner field lang).
<field name='lang'/>
Since Python onchange method doesn't trigger country_id field I though that JavaScript would probably only thing that would solve my problem. So What I want to do is to access field coutry_id in specific form view (let's say only in view_partner_form) and when it changes access value of lag field and change it as well.

How to handle auto-focus on field elements when you try to update an object

We tend to position the cursor on the first element of all newly created objects (e.g. name field for user or the email id field on the login page). Does it make sense to auto-focus on the name field for user on User.update, since the user could modify any other field of the User and doing on auto-focus while doing User.update actually marks the entire name field instead of positioning the cursor on the name element. What should be the right behavior?
The purpose of auto-focus behavior on a web page is to save users from moving off the keyboard to make a mouse action for the most common task on that page.
So you need to ask the question: "What is the most common task performed on this page?"
Then ask, "What is the first UI element (field) a user needs to access or edit to accomplish the most common task(s) on this screen?"
Your answer should determine where your auto-focus goes. But be careful - users expect the auto-focus to go on the first field on the page. So only place it elsewhere if you are sure that this is desirable to the users. And also in that case, consider moving that field to the top of the page.
In your case, the "name" element gets entirely marked (selected) because that is how auto-focus works for fields that already contain data. This is the most desirable behavior because it allows the user to replace the contents of the field without doing further work with the cursor and delete keys, and if they only want to edit, they can simply use the Home/End and arrow keys to quickly move the cursor where they need it.
===== Edit / Addendum =====
I forgot to add this in the original answer, but it's such a huge pet peeve of mine that I have to mention it here.
Please, if you do an auto-focus, make sure it doesn't fire if the user is already typing! There is NOTHING more annoying than having your cursor moved automatically while you're in the middle of logging in.
This used to happen on Yahoo! Mail's login screen all the time. If the page was loading slowly, the login form would render a few seconds before the DOM was ready and the auto-focus only fired when it was ready. So I'd click manually to focus in the login field, and I'd already be halfway through my password when auto-focus would silently move my cursor back to the login field and I'd look up at the screen to find half my password in plain text up in the login field, smashed up against my username.
The fix is so simple; just check if the login field is still blank before focusing there. Otherwise don't because you then know the user already typed something and the convenience of auto-focus would turn into a frustration. Here's example code, assuming your field is given an id="username":
function focusIfBlank(){
username = document.getElementById('username');
if(username.value == "") {
username.focus();
}
}
Also consider calling focusIfBlank() inline instead of when the DOM is ready, because you'll increase the chances of it being useful to the user since it will focus almost instantly after it's rendered.
I am not sure whether its your answer,
<body>
Name: <input type="text" autofocus /> <br />
Email: <input type="text" />
</body>
Refer this,and this for more options..

Categories