Issues with "Recurly.js" form generation and GWT / AJAX - javascript

I am building a user interface for Recurly account management in a GWT application.
This means there is no actual browser navigation happening between "pages" in the app, and client DOM state is maintained in memory until the user actually refreshes their browser.
In other words, when the user leaves the billing information "page" - the input elements still exist in memory and are simply detached from the visible area of the user interface.
Unfortunately, the fields that are being provided by "Recurly.js" are somewhat problematic here as they seem to be designed for use in a conventional framework where the user submits the form and then is redirected to a new page.
While they work perfectly for an initial submission of updated billing information (i.e. the first time the "form" is instantiated), if someone re-visits the screen multiple times without refreshing their browser, the fields do not accept input.
I have tried the following:
clearing the inner HTML of the wrapping recurly div elements (into
which the provided fields are drawn by Recurly.JS) and calling
configure() again
Not calling configure() after the first time it is called (in this case, subsequent visits to the page result in unresponsive inputs)
Is there a way I can tell Recurly.js to reset itself so that the provided fields can be redrawn? Or (and preferably) is there a way to configure recurly to use my own "input" fields for number, date, month, and cvv instead of those that are rendered into divs by Recurly.js?
Thank you
Edit:
I have discovered that Recurly.js is setting the visibility of their provided billing inputs to "visibility:hidden" after the form is accessed after being instantiated. If I can't force recurly to redraw the inputs, then I need to prevent this from happening some how...

I discovered a "readyState" variable in Recurly.js.
If I set that back to "0" before calling "reconfigure", the fields correctly reconfigure themselves.
This seems to fix my issue.

Related

In Dynamics 365, is there a way to filter associated view results based on a record's field value and user permissions?

As the title states, I need to filter results of an associated view based on a record's field value and user permissions.
I've used some Javascript to achieve this whenever the iFrame loads, but if the user switches to a different view, my Javascript is not called and the filtered records come back. I've tried to implement an event listener for various changes within the iFrame, but haven't been able to get what I need. I've gotten onclick to call my function whenever the user opens the view dropdown, but I need it to call whenever they actually switch views.
Am I over complicating this and there's a native way to do this? Or does anyone know how to detect changes within an iFrame?
Unfortunately there’s no native config to do it by OOB. I recommend these.
Don’t rely on associated view, as the name suggests it’s for seeing all the associated records. Remove navigation item in Form editor to remove them if you don’t want your users to see it
Use Subgrid for all your different needs, but not with view switcher, as again you will get roadblock of view switch triggers, etc. also this is going to be unsupported approach to rig the FetchXml with your custom filters
Custom HTML with grid is better or even PCF control of your own to take query & filters
Plugin on RetrieveMultiple can be used in worst cases

Restoring form state with back button and "sortable" forms issue (Chrome and safari but not Firefox)

I'm writing this to document a current (apparent) bug.
Situation:
Given a webapp where users can view and sort tabular data (it is loaded from DOM, and sortable via javascript). They can use checkboxes and a buttons to take action on what is viewed.
If you use the back button to go back to the tabular data page, then the browser fills in the states of the checkboxes. This is expected behaviour.
Complication:
If you sort the table first (an in-DOM sort using javascript) and then fill in the checkboxes and go to another page, and then use the back button to go back then browsers behave differently.
Currently Chrome (58) and Safari (10.1) reloads the form and tabular data in the original (not the js-sorted) order, but restore the inputs in the order they were clicked (ie ignoring any ids for the inputs -- just their order in the DOM at the time) -- this results in very surprising behaviour (the form at first glance seems to be what you expect, but different form elements have been restored with different data)
However Firefox (v50.0) reload the form and tabular data in the js-sorted order, and the restored inputs are correct.
I've documented this more fully at https://timdiggins.github.io/back-button-restore-sorted-inputs/
Ideally the browsers would store their input data against the input's id rather than its order in the DOM, or would cached the DOM order too.
I'll answer this myself with a workaround, but I'm hoping someone will come up with a better suggestion.
Or alternatively point out anywhere in HTML5 specs that say that form's DOM shouldn't be sortable? (ie. is it possible that Chrome and Webkit are behaving to spec here).
I've found three ways of working around this. Two which are very reliable, but each lose functionality, and one which I am in two minds about
1) Disable dynamic sorting in the initial form (obviously).
2) Disable saving form state for all of the form elements with autocomplete="off" (on every input, see https://stackoverflow.com/a/2458153/109175). Optionally could skip this for browsers (like Firefox) that have unproblematic behaviour (in my use case Firefox never used).
3) An option that occurred to me is to make sure that the order is reset to the original DOM order when form state is saved. This might mean adding a before submit handler on the form (easy enough) but in order to ensure the form is restored correctly when navigating away with a simple link <a>, this might mean adding a callback before executing links -- this wouldn't cover javascript based navigation.
4) Another option which occurs to me, is to focus on the reordering process -- either to convert it from js to a page reload or to use pushState or replaceState from the History API
Both 3 and 4 seem clever, but (for my use cases) I'm inclined to go with one of 1 or 2 and deal with the reduced functionality.

Getting field values from another form to perform validation on the web in lotus notes

I have a radio button field on a lotus notes form (say main form). If it is selected as "Yes", a link gets unhidden. On click of this link, another form opens up. If in the radio button, "Yes" is selected in the main form, the contents in the second form must be filled. So I need to write a validation if the radio button field is "yes" and the field inside the second form is not filled, then it should show a popup asking to fill the field in the second form. How do I get the value of the field in the second form on the main form for me to perform the validation?
You literally cannot do what you've described you want to do. The second (pop-up) form and its content no longer exist in the client (browser) context when you want to do validation on the first form's data. There are three possible ways to tackle the problem but only two of them are actually practical.
Let's dispense with the impractical method first. That would have the pop-up form write something back to its parent/opener, either as a JavaScript variable or as DOM content (a field outside of the Domino form or hidden element or some such) or, perhaps as a cookie value. Setting up the opener relationship reliably can be a problem cross-browser, but it is doable. The problem is that no matter how you do this, you have no guarantee that the value will be there when you need it (or expect it) except when the parent form is initially filled out. If the document is ever edited, you have no way of knowing whether or not the user has filled in the data on the pop-up. Anything you may have written to JS variables or the DOM during the initial session with the form only exist during the initial session. Cookies aren't permanent; they can be cleared by the user even if you try to give them eternal life via the expires value. No matter how you do it, you'd be telling anybody who has previously filled out the data you want that they need to fill it out again.
The second method would be to make a call back to the server to see if the pop-up form has been submitted and turned into a Notes document. That doesn't scale at all; even if everything is happening on a single server, there's no way to guarantee that the document you are looking for will have been written and indexed by the time you need it, and there is a time factor involved. If the user has already seen the validation nagging once, does what you tell them to do, and then gets the nag again, you're not making any friends.
The third method is to do everything you need to do on one form. (You can use CSS to do the pop-up if you're married to the pop-up idea.) And, you know, it really doesn't matter at all whether or not you would prefer to do it another way, it's the only way that will be reliable and make happy users. Yes, it will mean a little bit of extra work on your part. You're a developer - that's what you do for a living. You can even keep the structure of the existing application intact; WQO and WQS agents mean that you can glue documents together before sending them to your user, and pull them apart again before you save them. This is the only method that is guaranteed to be fast enough and reliable enough to be usable on the web.

appendChild() checkboxes: remember selections with browser back button

Thank you in advance to anyone who attempts to help me with this.
I have a form that I am adding checkboxes to via appendChild() - as selections for the user to chose from - based on a bunch of criteria.
When the user checks any of these boxes and then clicks the 'continue' button to post the selection to another page - and then clicks the back button - the checkboxes that were checked by the user - have now been forgotten by the browser (no longer checked).
If I use php to write the checkboxes or simply have static checkboxes - when the user checks any of these boxes and then clicks the 'continue' button to post the selection to another page - and then clicks the back button - the selected checkboxes are remembered (still checked)
My question is:
Why does the browser forget the selections the user made when I create the checkboxes with appendChild()
yet the same browser will remember the selections the user made when using static checkboxes
What is it about appendChild() that is not allowing the same browser to remember the checked selection?
[div id="mydiv"] here is where the checkboxes are going[div]
[script type="text/javascript"]
var newInput = document.createElement("INPUT");
newInput.id = "mycheckboxid";
newInput.name = "mycheckboxname";
newInput.type = "checkbox";
document.getElementById('mydiv').appendChild(newInput);
[/script]
The browser may "forget" dynamic changes to the DOM because different browsers use different strategies for caching web pages. When you hit the back button, the idea is that the browser can display its cached copy rather than re-request the page from the original web server.
It can accomplish this in (at least) two ways:
The browser caches the DOM itself of a page upon leaving it. Upon revisit (forward or back) dynamic changes will persist.
The browser caches only the original HTML of the page at load time (prior to any dynamic changes). This has the effect of losing those dynamic changes--further modification to the DOM with appendChild() or innerHTML is not recorded.
Note that some browsers additionally keep modified form data, and others do not. If your goal is 99+% compatibility across all browsers, then you have some work to do.
To work around this you need to persist the state somehow. You have a few options:
Save data about the modifications to the page to localstorage. Use a key that is generated randomly on first page load and then kept in the page, so that the state changes will only apply to that instance of the page. On page load, if this key already exists, read the change data out and re-apply the changes. Older browsers do not support local storage.
Do the prior thing with cookies. I don't recommend this, as it has the drawback of proliferating cookies. Cookies are sent and received in every request (including ajax ones), so you would be bloating the data being transmitted on every request. Old browsers would work fine with this.
Abandon your dynamic change model and make the changes occur through a post to the server. Then the page will contain the modified html when pulled from the browser's cache. You probably don't want this, but I thought I'd point it out for completeness' sake.
Save data about the modifications to the page via ajax behind the scenes to the server. This is not the same as actually round-tripping each change like the previous item. You still make changes dynamically, but you post an "advisement" file to the server. Then, on each page load, request any adjustment data from the server. This is similar to the first suggestion, but you are using the remote server as your storage. This makes extra net traffic occur on each page load, but the traffic can be minimal as it would be just about this page. It also makes extra net traffic occur that would not normally be sent (the advisement data). A clever system architecture, however, could use this information to persist a user's unsubmitted form data across computers and over time in a way that could be very handy (lets say your user does 199 out of a 200-question survey and then his power goes out--with this scheme he has a chance of painlessly continuing later exactly where he left off!).
Make your Continue button open a new browser window, preserving the original page intact.
Make your Continue button post the data without leaving the page, preserving it intact. You could do a simple lightbox-style overlay.
If the lightbox-style overlay will not work but you really have to display a new page and don't want it to be in a new window, then redesign your site to work similarly to gmail: where pages change only through javascript, and only through using #hash tags at the end of URLs to control behavior. This can be difficult but there are libraries out there that can accomplish it. (For some browsers one has to resort to polling to see if the hashtag has changed.) The basic idea is that when you click a link that points to the same page but has a tag on it such as About the browser will initiate a page load event, and will push a new context into the history forward/back stack, but will not actually load a new page. You then parse the updated URL for the hash code (which maps to some kind of command) and carry it out. Through careful choice of the proper hash codes for each link, you can hide and display the appropriate page dynamically through Javascript and it will appear as if the person is navigating around a real web site. The reason you do all this is that, because the page never loads, you not only can maintain state in Javascript, you can maintain your DOM state as well--you simply hide the page that was modified by the user, and when the back event occurs that means to visit that page again, you display it, and it is exactly how the user left it. Advantage: If your site requires Javascript to operate, then you are not taking a risk by using even more Javascript to accomplish it. Disadvantage: Completely changing the architecture of your site is a LOT of work and can be difficult to get working on older browsers. To get started with this see Unique URLs. You might try out the jQuery hashchange plugin. If your web site has wide distribution you will want to be sure to address search engine optimization and web usability issues. You may want to see this SO page on detecting back button hash changes.
Use the same strategy as in the prior point but instead of doing it with hashtags, use the new HTML5 history.pushState() and history.replaceState() methods--see Mozilla browser history.
If your goal is not 99% compatibility across 99% of the browsers in use, then please let us know what you are aiming at, as there may be a shortcut possible.
Update: added an option #8
Scripting pages doesn't stop at state management. It includes state management.
This means scripted state changes such as scripted page transitions(pages that internally navigate), content panes, popover menus , style changes and of course, form input and selections are all the responsibility of the scripter.
So, in answer to why .. it is because you did not manage the page state you scripted.
If you want your page to work as you seem to expect you can manage the page state changes you script yourself, use a js lib that manages page, or perhaps in your case form, state, or use the http(s) client/server state management and load up the session state, or in your case just the form state, at the server.

Is it dangerous to store user-enterable text into a hidden form via javascript?

In my asp.net MVC application I am using in place editors to allow users to edit fields without having a standard form view. Unfortunately, since I am using Linq to Sql combined with my data mapping layer I cannot just update one field at a time and instead need to send all fields over at once.
So the solution I came up with was to store all my model fields into hidden fields, and provide span tags that contain the visible data (these span tags become editable due to my jquery plugin). When a user triggers a save of their edits of a field, jquery then takes their value and places it in the hidden form, and sends the whole form to the server to commit via ajax.
When the data goes into the hidden field originally (page load) and into the span tags the data is properly encoded, but upon the user changing the data in the contenteditable span field, I just run
$("#hiddenfield").val($("#spanfield").html();
Am I opening any holes this method? Obviously the server also properly encodes stuff prior to database entry.
Assuming your server is properly detecting and dealing with XSS attempts, there's no way a malicious user could submit an attack for another user. Unless someone wants to hack themselves(?), it seems secure to me.
I find this approach pretty unsavory. I guess the overall soundness of this scheme depends on what fields you're actually populating this way --
For example, if you store fields that are supposed to be set only once (at the time of record creation) and never changed, this will allow a (malicious) user to change the field values mid-stream by editing a hidden field before posting (very easy to do, for example, with Firebug).
There's no difference here than if you were providing visible input fields and having that form submitted. Simply shuffling the data into hidden fields vs. visible ones would not make a difference.

Categories