Unobtrisuvely ask user for details - javascript

I am trying to figure out the best way to acompish "unobtrusive" forms for a user (within a web app).
The purpose: keep user on the site by not asking to fill unnecessary form in. Ask for the details as only when such are needed.
The requrements are:
User should provide additional details only when it is required (email to receive notifications, login required for account page, save credit card details when checking out).
User should not leave the current page providing the additional details.
The implementation would be fairly easy if all requests would be AJAX ones. It would be easy to analyse the response (401 or so) and show the appropriate lightbox-form.
I do not see how it can be done "the right way" with plain anchors and form submits as in both cases the user actually leaves the page (by following the link or submitting a form) and there is no way to analyse the response on the client side.
Converting all links and forms to AJAX ones would be just silly.
The closest analog to what I want to achieve is the default Basic Authentication dialog in most of the browser. But obviously that just doesn't fit my requirements.
Any creative suggestions how to do that for non-AJAX requests?
Regards,
Dmytrii.

In a page sense, where "page" refers to what the user sees and not what the URL is, I only can think of following ways to update independent parts in a page with JavaScript (and thus Ajax) switched off:
Frames
Iframes
Using held-open connections there are two more ways to update a page, however these do not work reliably in all cases:
Animated GIF
CSS DIV tags with absolute positioning.
Note that this needs that your Server can keep open a session for each person looking at the page, which can be thousands. If this does not work the only possible workaround is with FRAMEs and automatic refresh, which is somewhat clumsy.
As I think that you do not want to use Frames and you do not want to render animated GIFs, I explain the CSS DIV way:
When you load the page you do not finish loading it. Instead the connection is kept open by the web server and the script handling the connection waits for additional information to arrive. When there is additional data, this is sent to the browser by encapsulating it into additional DIV tags which can overwrite other parts of the page.
Using "style" in the DIV tag and CSS position:absolute these can overwrite other information on the page like a new layer. However you need either position:absolute or must add this data to the end of the page.
How does this work with forms?
Forms usually have a known size so you can put them into IFRAMEs. These IFRAMEs get submitted to the webserver. The script there notifies the other script that new data must be output, so the waiting script renders the response and displays it in the page while the script which took the submit redisplays the form with fresh values only.
How does this work with 404 and anchors?
I don't really know because this must be tested, but here is a hint how I would try to implement this:
We have 2 issues here.
First the URL must not point to other pages but back to a server script again, so the href is under control. This script then notifies the waiting script to update the page accordingly, for example by retrieving the page and sending it to your browser. The script can check for 404 as well.
Second you must hinder the browser to switch the page when clicking on the anchor. This probably involves some clever tricks using CSS, target and server side status codes (like "gone" or redirect to the current page, whatever) to keep the browser from switching the page. I am not completely sure if that works, but if you remember download pages, these show URLs which do not switch the page but have an effect (downloading the file). That's where to start to try to hack browsers not leaving the current page without using JavaScript.
One idea not followed here is not keeping the connection of the page open but the CSS file and send new css information to the browser which then "fills in empty stubs" using the CSS way. But I doubt that this works very well, most browsers probably will parse the CSS only after loading finished, but perhaps I am wrong.
Also note that keeping a connection open never finishes the page loading, so you will see the busy-logo spinning all the time, which is unavoidable with this technique.
Having said this all I doubt you get around JavaScript.
What I wrote here is very difficult to do and therefor usually is not used because it scales badly. And it is a lot more difficult than using JavaScript alone (that's why I explained it).
With proper AJAX it is much more easy to reach your goal. Also note that you do not need to change your page source much, all you need is to add a script which augments the page content such, that for example forms suddenly use AJAX instead of a direct POST with re-rendering the page. Things which cannot be detected easily then need some hints in the tags such that the tag scanner knows how to handle the tag. The good thing then is, that with JavaScript switched off your page still works - however it then "leaves the page".
Normal HTML just was not designed to create application-like web pages like we want to see today. This all was added using JavaScript.
About popup forms
The Basic-Auth-Handler reloads the page after the user enters something into this dialog, only if cancel is hit the current page is displayed.
But there are two ways to present additional query-popups in a page using JavaScript:
The first one is the javascript "prompt", like in following example:
http://de.selfhtml.org/javascript/objekte/anzeige/window_prompt_vor.htm
(Click on the "Hier").
The second one is "JavaScript forms" which are like popups within an HTML-page.
However I consider popups to be far too intrusive and bad design.
Ajax and JavaScript is the easiest way
Unfortunately using JavaScript is never easy, but if you think JavaScript is improper or too difficult, there is no other technique which is easier, that's why JavaScript is used everywhere.
For example your page onload-Script can cycle through all Anchor-Tags and modify them such, that clicking on them invokes a function. This function then must do something clever.
Same is true for Forms. Fields which can be modified (like the user's eMail address) then have two views, on is visible, the other one hidden. The hidden one is a form. Clicking on the eMail address then switches the view (disables the first div and enables the second), such that suddenly instead of the eMail address a text form field is there containing the eMail address. If you click on the "OK" button the button changes the look into a spinner until the data is submitted, then the view switches back to the normal one.
That's the usual way to do it using JavaScript and Ajax. And this involves a lot of programming until it works well.
Sorry for not shortening this post and missing code snippets, I am currently lacking time ;)

Hidden iframe.
Set target attribute of the form to the name of the iframe. use the onload event of the iframe to determine what is the response.
Or, if you really dont like any javascript, don't hide the iframe and instead present it in a creative manner.
CSS to hide an element
#myiframe { position:absolute; left: -999em; display: none; visibility: hidden; }
But normally, display: none is enough. This is just an overkill.

Related

How to target strings/email addresses within a page using jQuery

I'm trying to make a script that will search through an entire webpage for email addresses that end in #xyz.com. For example:
$(document).ready(function() {
$("body:contains('#xyz.com')")
.css("text-decoration","underline");
/*$("*:contains('#xyz.com')")
.css("text-decoration","underline"); doesn't work either */
I figured contents(); wouldn't be a better choice over contains(); ...
});
For some reason, it can't seem to detect any email addresses I've hard coded into my page within the paragraphs on the page.
I can't tie the selector down to a specific div since this script will be running on different webpages thus not being able to controll what element the email address is presented in. But... even if I managed to figure that problem out, I still have another problem to deal with...
The email addresses on the webpages will be all random but will all end in #xyz.com. So I'd have to also select anything to left of the # symbol up until it detects a space between characters.
I can only find solutions to how to detect an email from a list or validation on forms etc.
How can I achieve this?
The problem is that your script is running in the background page, not in the page. The background page can't access directly to DOM of pages loaded by chrome.
To do what you want, look for Content Scripts. This allow you to inject scripts into a given page (like the page loaded in the active tab of chrome). This script can perform action on DOM and comunicate with the background page via the Messaging API of chrome.
Here more informations

How can I make modifications to an HTML form that is automatically generated?

I'm creating a webform using a marketing automation platform. I want to add a field that functions with jquery to do an autocomplete. Unfortunately, the forms are generated through a WYSIWYG editor in the software, and then generated and put into the page when it renders. The only code for the form that appears in the HTML for the page is a simple variable placeholder - %%FORM::DEFINITION%% - which is then replaced with the form code when you visit the URL. The software support team tells me that making the change I want to make is impossible, which I see as a challenge.
The only thing I need to be able to do is add an id="autocomplete-dynamic" attribute to the input on the form. I had two ideas how I could achieve this.
The first, and most preferable option, would be some script that runs at the bottom of the page that simply inserts the attribute into the input tag after the page renders out. This would only be a client-side change, but since all this does is make the text field capable of looking up values out of another table, it should be fine. If someone had a script blocker in place, they would not be prevented from typing into the text field normally, it's just that the auto-lookup wouldn't work. We're trying to make it easier to select an item from a list of thousands of possibilities, but if someone had to type in their own entry without the autocomplete, it would not be a disaster. This seems like a clean solution, but I am not sure if it can be done.
The other possibility is to get the form code out of the software and embed it in a separate HTML document, and make the change there. You can extract the raw HTML for the form for use on another page, but pasting this code right back into the landing page causes errors. So, the thought then was that if I have taken the code generated by the software and put it in an HTML page on a separate web server, I could modify it as needed, and then turn around and use an iframe to stick it right back in the landing page. The software shouldn't complain because the form is being used on an external site like it's supposed to be... I have just hidden that external site back inside the platform-hosted page.
Option 1 would still be much easier to implement, I think, provided it is actually possible.
Thanks in advance.
Your first solution seems completely appropriate.
$(function() {
$('#myForm input').attr('id', 'autocomplete-dynamic');
});
This can be added anywhere inside a script tag because it's wrapped in a shorthand document.ready function, which waits to run until the DOM is ready.

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.

JS page formatting is not retained when navigating away from a page and back

I have a bit of an issue with page formatting when I navigate away, and then hit browser back to a page.
Here is an example:
I have security questions on a form in a drop down list like so:
http://i.stack.imgur.com/ib32z.jpg
When the user selects [Type in your own question] from the drop down list, I have some jquery that animates a CSS change that pushes the form down, and makes visible a hidden field for 'custom security question'. When selected, the form looks like this:
http://i.stack.imgur.com/uVPKo.jpg
Now my dilemma is when I navigate away from this page, and then navigate back using the browsers back button, my formatting gets screwed up and looks like this:
http://i.stack.imgur.com/5Xhpi.jpg
The javascript that I have written does not trigger again on the back button so the browser doesn't know to move the form back down to accomodate the change in spacing. Is there anyway I can force the document.ready to reload or clear some kind of cache?
Thanks!
EDIT: Sorry guys, I need to reupload the images to a host and repost. Sorry for the delay.
There are basically four mechanisms for persisting state on the web:
Browser-based - the browser, if you're lucky, will save answers to form fields and re-display them when it sees an INPUT with the same name; also, some browsers will preserve some state between forward<=>back navigation
Cookie-based - pretty self-explanatory; you save a cookie with the state info, and check it later to recover the state
URL-based - navigate to a different hash of your URL, with the info you want in it (eg. "?roll_down=true")
HTML5/Local Storage - Look it up if you're interested :-)
We can basically throw 1 and 4 out, because they both rely too much on browser behavior/support, and we can't reliably rely on all browsers to handle them the way we want. That leaves #2 or #3.
Cookies allow you to save more info (as much as a cookie holds, ie. about 4k). URLs allow less info, but they have the added benefit of bookmark-ability; if the user saves the URL as a bookmark (or as a link they send a friend, or whatever), the state still gets preserved.
So, take your pick of the above, decide on how to persist your "my form is rolled down" state ... and then comes the part that (I think) you're really interested in: how do you check this state and fix things when the user clicks "back"?
That part I humbly defer to another SO post, which has already answered it:
Is there a way to catch the back button event in javascript?

Overlay an HTML page with an HTML form

this is a question about the best way (or least effort of the best ways) to overlay an html page with a form. Best in this context meaning best user experience whilst meeting the functional requirements.
Let's say I have a page with a short form on it; the user has to enter some financial details. To assist the user to enter an accurate value for one of the fields there's another, much longer form. The longer form needs to be displayed only if the user requests the help.
For users without javascript, clicking a link will submit the short form (persisting already filled fields in a session) and the server will respond with the long form. They'll submit the long form and the server will combine the submitted data with the persisted data and serve the short form again - with the fields populated.
For users with javascript I want to overlay the short form page (in a lightbox stylee) with the long form, allow them to populate the long form and then go back to the short form with less round-trips to the server.
Do I:
Overlay the short form page with an iframe whose target is the long form?
Request the long form over ajax and stuff it into a div?
Generate the long form entirely on the client-side?
Some other wizadry I haven't thought of?
A short explanation of the best mechanism will do me very nicely indeed. Thank you very much!
I'd be thinking about option #2.
When the user asks for help, load the help-form dynamically into a div that you can pretty up with a lightbox of sliding drawer effect or whatever.
If possible, I'd do all the processing of the long form on the client side, and use the results to dynamically update the short form.
I use Colorbox for this kind of stuff it's really good.
You can specify the content inline or via another URL (which is what I do). It's probably better to use this second method as it keeps your webpage a lot cleaner and only requests the form content if required. It also means you can post back to that form itself (via AJAX if required) keeping the whole experience cleaner
Check it out here - click "Tag this smiley". The form is taken from a remote URL and posted back to it inside the form using jQuery. It's obviously a simple version of what you want but works, and looks, really nice.
For your scenario where you want a decent fallback for users without javascript I would have the form on the webpage but hidden via javascript, then use Colorbox to load use that content for the popup when required.

Categories