Dynamo

46 replies to this thread. Most Recent

JDW

24 Feb 2017, 7:05 am

[Pro] Javascript for Search Field, Safari problems

Now with SoftPress2 back online, hopefully we can see a little more life in this forum!

I’ve been making some changes to my Freeway site with regard to my Search field. I’ve got something I like, which works great in FireFox and IE and Chrome on Mac and Windows8, but for some reason it doesn’t work in Safari on Mac or Chrome on WinXP.

I’ve created a JS Fiddle here (with instructions):

https://jsfiddle.net/JDW1/9qante80/

Here is the TEST PAGE shown on that Fiddle:

https://kiramek.com/search-test.html

The key problem surrounds my use of:

this.reset();

Without that, it works in all browsers, but of course that is not what I want. What I want is for the user to type their search query then hit Return, and then when they return to the page (via Back Button, etc.), the search field will be blank and deselected. Using that “reset” bit works to achieve my aims, but stupid Safari doesn’t like it. Would any of you know why, and how to fix?

Thank you,

James Wages

JDW

24 Feb 2017, 7:07 am

I should add that I don’t want to use jQuery or Prototype. Just pure JS.

—J. Wages

David Owen

24 Feb 2017, 1:11 pm

Hi James

Just on a side note your search results page goes out of kilter on a narrower browser window….

https://kiramek.com/english/search_results.html?q=kiramek&cx=018348177762133457495%3Azee6ukhbc-o

David Owen { Freeway Friendly Web hosting and Domains }

http://www.ineedwebhosting.co.uk | http://www.PrintlineAdvertising.co.uk

On 24 Feb 2017, at 07:05, JDW <[email protected]> wrote:

Now with SoftPress2 back online, hopefully we can see a little more life in this forum!

I’ve been making some changes to my Freeway site with regard to my Search field. I’ve got something I like, which works great in FireFox and IE and Chrome on Mac and Windows8, but for some reason it doesn’t work in Safari on Mac or Chrome on WinXP.

I’ve created a JS Fiddle here (with instructions):

https://jsfiddle.net/JDW1/9qante80/

Here is the TEST PAGE shown on that Fiddle:

https://kiramek.com/search-test.html

The key problem surrounds my use of:

this.reset();

Without that, it works in all browsers, but of course that is not what I want. What I want is for the user to type their search query then hit Return, and then when they return to the page (via Back Button, etc.), the search field will be blank and deselected. Using that “reset” bit works to achieve my aims, but stupid Safari doesn’t like it. Would any of you know why, and how to fix?

Thank you,

James Wages

www.ineedwebhosting.co.uk

Freeway Friendly Web Hosting, Domain Names, VPS and Dedicated Servers. (Create an account it’s Free!)


PrintlineAdvertising.co.uk

Print Design, Digital and Litho Printers, Promotional Merchandise and Corporate Gifts.

JDW

25 Feb 2017, 4:45 am

Thanks for the tip, David. I never noticed that on the English site because I spend most of my time on the Japanese site which doesn’t have that problem at all:

https://kiramek.com/japanese/search_results.html?q=alarm&cx=018348177762133457495%3Amdzyzovqz2q&lr=lang_ja&ie=UTF-8#gsc.tab=0&gsc.q=alarm&gsc.page=1

Now I need to dig around and see what the root cause is on the English site.

Anyway, if you have any ideas as to why Safari is disliking “this.reset();” I’d love to hear them!

James W.

JDW

27 Feb 2017, 12:49 am

Thanks again, David. There was a little HTML box on the page named PlaceHolder that should not have been on the page, and that was causing the narrow-browser-window problem. It’s now fixed.

James

JDW

27 Feb 2017, 12:50 am

Folks, I’m here on my knees pleading for the coders among us to kindly offer me a little guidance on the “this.reset();” problem I mentioned in my opening post.

Surely there must be a solution. I’ve spent several hours on my own trying to find a solution, but that time was in vain. That is why I posted here.

Any ideas at all would be greatly appreciated!

Thank you,

James Wages

waltd

27 Feb 2017, 1:01 am

You generally cannot do anything to a page after you submit a form contained within it.

What is your goal here? Because what you’ve written in the onsubmit appears to me to be contradictory. If you want to submit the form, it has to have content in it. If you reset it, it will lose its content and that may happen before the form sends to the server.

Is there a specific goal you have in mind here? Try instead of coding, writing in prose what you want the page to do when a user 1) First encounters the page, 2) Fills in the search form, 3) Submits the search form, etc.

If I didn’t know better, I could swear you were looking to have the form submit while remaining on the current page. If that’s the case, then just make an Ajax request to the server, and update another element on the page with the results.

Walter

On Feb 24, 2017, at 2:05 AM, JDW <[email protected]> wrote:

Now with SoftPress2 back online, hopefully we can see a little more life in this forum!

I’ve been making some changes to my Freeway site with regard to my Search field. I’ve got something I like, which works great in FireFox and IE and Chrome on Mac and Windows8, but for some reason it doesn’t work in Safari on Mac or Chrome on WinXP.

I’ve created a JS Fiddle here (with instructions):

https://jsfiddle.net/JDW1/9qante80/

Here is the TEST PAGE shown on that Fiddle:

https://kiramek.com/search-test.html

The key problem surrounds my use of:

this.reset();

Without that, it works in all browsers, but of course that is not what I want. What I want is for the user to type their search query then hit Return, and then when they return to the page (via Back Button, etc.), the search field will be blank and deselected. Using that “reset” bit works to achieve my aims, but stupid Safari doesn’t like it. Would any of you know why, and how to fix?

Thank you,

James Wages

Freeway user since 1997

http://www.walterdavisstudio.com

JDW

27 Feb 2017, 1:10 am

Walter, because I have Freeway’s “Form Setup” dialog filled out appropriately, I do not need any JavaScript to get the form to submit at all. The user need only type a keyword (for example, “alarm”) and then hit RETURN. That will submit the keyword “alarm” to Google and then the search results page will appear. That works fine. No edits required.

The problem is that when the user clicks the Back button or hits CMD-[ to go back to the search field page, the keyword they typed is stuck in that field. To me, that looks unsightly. I want that keyword removed and the search field to be restore to its pristine, untouched condition. That is the aim here.

I am able to accomplish my aim with the code I’ve linked for everyone to see, in my opening post. The problem is that Safari chokes on it for reasons unknown to me. Other browsers don’t choke on it, except for Chrome on Windows XP, but I don’t really care about XP — even so I mention it only because I tested it and found it chokes (even though FireFox does not). FireFox is happy with my code on any platform. And newer versions of IE on newer versions of Windows are happy too. Again, it is Safari that is the problem. But why? That is what I wish to know.

Any ideas?

Thanks,

James W.

JDW

27 Feb 2017, 1:29 am

Walter,

What I am trying to do is nothing unusual. I see it done everywhere. For example, check out the following StackOverflow page:

http://stackoverflow.com/questions/997774/how-do-you-clear-a-plain-html-form-after-onsubmit

Click in the search field atop that page and type a keyword. When the search results appear, click the browser back button and take note that the keyword you typed is not there.

Here’s yet another example. Visit Apple’s website, click the magnifier, type a search term, then on the results page click the browser back button. Note that your keyword is NOT stuck inside a search field after you return to the page on which you initiated the search.

That’s all I want to achieve.

Again, any thoughts? My code mostly works to do what I want, I just don’t understand why Safari chokes on it.

Thanks,

James

waltd

27 Feb 2017, 1:29 am

I’m not sure the code you’ve entered here is doing much of anything for you, and it may be actively hurting your page. I tried filling out the form and pressing return, and Google returned no results. Not even a “sorry, didn’t find anything to match”, just a header and no body content in the bottom area. The thing is, what you’re trying to do is alter the page after it has been closed for writing by the browser. If other browsers let you do that, that’s their bug. Safari is doing the correct thing by locking the DOM when the form is submitted.

The back button draws from the browser’s history cache, and thus has a picture of the page as it was when you left it. That’s what it shows the visitor when she presses the back button. I remind you, this is the exact expected behavior of any form on any site. If you are using back to navigate, you get the page from the history, not the server.

What you might want to do is put a search form on the results page, and allow it to be filled in by the querystring, too. That way there is no ambiguity about what is going on here. People who want to clear that form will either select-and-delete manually, you could add a reset button on the results page, or you could add a different UX pattern like click-to-select if you’re allergic to extra elements.

This approach would not prevent the user from using that back button, but if they didn’t find what they were looking for on the first try, they could take another stab at it from the results page, without having to navigate anywhere.

Walter

On Feb 26, 2017, at 8:10 PM, JDW <[email protected]> wrote:

Walter, because I have Freeway’s “Form Setup” dialog filled out appropriately, I do not need any JavaScript to get the form to submit at all. The user need only type a keyword (for example, “alarm”) and then hit RETURN. That will submit the keyword “alarm” to Google and then the search results page will appear. That works fine. No edits required.

The problem is that when the user clicks the Back button or hits CMD-[ to go back to the search field page, the keyword they typed is stuck in that field. To me, that looks unsightly. I want that keyword removed and the search field to be restore to its pristine, untouched condition. That is the aim here.

I am able to accomplish my aim with the code I’ve linked for everyone to see, in my opening post. The problem is that Safari chokes on it for reasons unknown to me. Other browsers don’t choke on it, except for Chrome on Windows XP, but I don’t really care about XP — even so I mention it only because I tested it and found it chokes (even though FireFox does not). FireFox is happy with my code on any platform. And newer versions of IE on newer versions of Windows are happy too. Again, it is Safari that is the problem. But why? That is what I wish to know.

Any ideas?

Thanks,

James W.

Freeway user since 1997

http://www.walterdavisstudio.com

JDW

27 Feb 2017, 1:34 am

Walter,

Like I said in my previous post. I am not seeking to do something new. StackOverflow does it. Apple.com does it. Countless other sites do it.

You put a search field on every page. The user types a keyword somewhere. They get a search results page. They then click the browser’s back button. After that, when they look at the search field, they don’t see their keyword stuck in that search field.

Go to Apple’s site and try it. Try it on StackOverflow.

waltd

27 Feb 2017, 1:48 am

Those sites could be setting a server header that causes the page to not be returned from cache on reload. You are creating a static page. The examples you are citing are heavy heavy server-side rendered Web applications. Not the same animal, and trying to ape what they look like without reproducing their tech stack is going to end in tears for you. What you are describing (and yes, I did look at the sites in question) is not normal, it is something quite refined that they have expended massive engineering resources to achieve. Make a static form in Freeway. Host it on a regular shared server somewhere. Visit it in a browser, and see what the back button does. That is what is normal.

In the case of Apple, there’s two things going on that mask the normal behavior from your sight. First, the search field is hidden on page load, because it only appears by a click handler (which is not stored in the history), second, the search field resets with an Ajax request to “suggestions”, which pre-fills the category names for the type-ahead search results and zeros out the field itself. That’s a POST request sent after the page loads (or reloads). I didn’t dig into SO in detail, but I imagine that they are doing something similar, because they also provide type-ahead search results.

The code you put in your onsubmit form attribute is like four shotguns being fired in four different directions, but on Safari, none of them are hitting the target, because the form is locked along with the rest of the DOM at the instant that you click the submit button.

If you are 100% convinced that you must fix this (and then I have failed you), then you can’t make this work without adding a submit button to the form. Observe the click event on that button, stop the event from propagating to the form, read the value from the search field into a variable, set the value to the empty string, then set the window.location.href to the form action + querystring (using the value you stashed a few steps back). That might work in Safari.

Walter

On Feb 26, 2017, at 8:34 PM, JDW <[email protected]> wrote:

Walter,

Like I said in my previous post. I am not seeking to do something new. StackOverflow does it. Apple.com does it. Countless other sites do it.

You put a search field on every page. The user types a keyword somewhere. They get a search results page. They then click the browser’s back button. After that, when they look at the search field, they don’t see their keyword stuck in that search field.

Go to Apple’s site and try it. Try it on StackOverflow.

—James

Freeway user since 1997

http://www.walterdavisstudio.com

JDW

27 Feb 2017, 5:17 am

Walter, you have not failed me. Nevertheless, I don’t want any Submit buttons. To me, that is a bit retro. I like the “type and hit return” approach.

So I did more research and found I could leverage the browser cache to resolve the Safari problem, as per this page:

https://webkit.org/blog/516/webkit-page-cache-ii-the-unload-event/

I edited my JavaScript and confirmed it is working in Edge on Win10, IE11 on Win8.1, Safari, Chrome (even Chrome 36 on WinXP), FF (even FF48 on XP), and iOS 10 & iOS8.1 via the iOS Simulator on my Mac.

Try it:

https://kiramek.com/search-test2.html

Type “alarm” and hit return. Notice how the search results appear just fine. Then click the browser BACK button. Form gets reset perfectly! (No keywords stuck in the search field.)

—James W.

waltd

27 Feb 2017, 1:06 pm

Excellent work! Bonus points for no frameworks in your JS!

Walter

On Feb 27, 2017, at 12:17 AM, JDW <[email protected]> wrote:

Walter, you have not failed me. Nevertheless, I don’t want any Submit buttons. To me, that is a bit retro. I like the “type and hit return” approach.

So I did more research and found I could leverage the browser cache to resolve the Safari problem, as per this page:

https://webkit.org/blog/516/webkit-page-cache-ii-the-unload-event/

I edited my JavaScript and confirmed it is working in Edge on Win10, IE11 on Win8.1, Safari, Chrome (even Chrome 36 on WinXP), FF (even FF48 on XP), and iOS 10 & iOS8.1 via the iOS Simulator on my Mac.

Try it:

https://kiramek.com/search-test2.html

Type “alarm” and hit return. Notice how the search results appear just fine. Then click the browser BACK button. Form gets reset perfectly! (No keywords stuck in the search field.)

—James W.

Freeway user since 1997

http://www.walterdavisstudio.com

JDW

28 Feb 2017, 12:34 am

Hi Walter,

I’ve actually been checking my web pages with Google’s PageSpeed Insights lately and it complains about “render-blocking JavaScript” …

https://developers.google.com/speed/docs/insights/BlockingJS

In my case that render-blocker is the Protaculous Action for Freeway, which uses the rather large Prototype framework (about 170k before gzipping), and it uses the slightly older 1.7.0.0 version instead of the latest 1.7.3 too.

I thought about a move to jQuery, but that too would be an external JS file that technically would be “render-blocking,” so I shifted over to putting pure JS on the page, despite the fact I am not well versed in that language.

Putting more on the page itself means I don’t get caching benefits, but it also means fewer server requests. I’m now trying to find the proper balance between server requests and the caching benefits of having external files.

Anyway, thank you for your kind assistance in this discussion!

Sincerely,

James W.

JDW

1 Mar 2017, 8:08 am

Walter,

I’ve discovered one caveat to my code. On pages in my Freeway site where I use the Rollover Action, I always choose “Preload: Yes” in the “Parameters” section (Actions palette). That results in the following HTML output:

<body onload="FWPreload()">

That conflicts with the JS I wrote (to defocus and clear my search field) due to the existence of 2 “onload” instructions:

//defocus search field and clear its contents under 2 conditions
window.onload = function(){
 var GF = document.getElementById("Field");
 //condition1: on page load
 GF.value = "";
 GF.blur();
 //condition2: when user clicks outside field
 GF.addEventListener("blur", function COF() {GF.value = '';});
}

Disabling “Preload” on all my Rollovers is a fix (that deletes the ‘onload’ in the ‘body’ tag), but there are two big problems with that:

  1. It’s a lot of work.
  2. Rollover images won’t show instantly, which I consider a problem.

And deleting ‘onload’ from my JS code isn’t an option either as that clears and defocuses the search field as I desire.

Would you know of any tricks to resolve this?

Thanks,

James W.

JDW

1 Mar 2017, 8:31 am

I know I can solve the problem by simple edits in TextWrangler:

  1. Delete ‘window.onload’ from my JS, and uniquely name my function.
  2. Add that new function name in the body ‘onload’.
//clear & unselect search field on page load
function SFcleaner(){
 var GF = document.getElementById("Field");
 //delete field contents and defocus on page load
 GF.value = "";
 GF.blur();
 //delete field contents and defocus when user clicks outside field
 GF.addEventListener("blur", function COF() {GF.value = '';});
}
<body onload="FWPreload();SFcleaner();">

But the problem is that Freeway auto-creates the “FWPreload()” in the body tag when needed. I cannot manually edit all my pages every time the site is rebuilt in Freeway.

I would appreciate hearing your thoughts.

Thanks!

James W.

waltd

1 Mar 2017, 1:24 pm

Yes. You don’t want to use or set body.onload, for just this reason. You want to use document.addEventListener('load',function(evt){ ... your function here ... }); instead. That’s because you can stack multiple listeners on a single event, and adding one does not delete another. They work the same way, and they don’t get in each other’s way.

Walter

On Mar 1, 2017, at 3:08 AM, JDW <[email protected]> wrote:

Would you know of any tricks to resolve this?

Freeway user since 1997

http://www.walterdavisstudio.com

JDW

2 Mar 2017, 12:43 am

Walter,

Altering the code as you suggest certainly resolves the dual-onload conflict, but it creates a new problem too. Here’s my modified code, as per your advice:

//clear & unselect search field on page load
document.addEventListener('load',function(evt){
 var GF = document.getElementById("Field");
 //delete field contents and defocus on page load
 GF.value = "";
 GF.blur();
 //delete field contents and defocus when user clicks outside field
 GF.addEventListener("blur", function COF() {GF.value = '';});
}

The problem that results is that the closing line in the code above no longer works to clear the contents of the field when the user clicks outside the field. In other words…

This part of the code still works fine…

 GF.value = "";
 GF.blur();

But this line no longer works at all…

 GF.addEventListener("blur", function COF() {GF.value = '';});

I tried moving that last line outside the function, as follows, but it still doesn’t clear the field contents when the user clicks outside the field:

//clear & unselect search field on page load
document.addEventListener("load",function(evt){
 var GF = document.getElementById("Field");
 //delete field contents and defocus on page load
 GF.value = "";
 GF.blur();
});

//delete field contents and defocus when user clicks outside field
document.getElementById("Field").addEventListener("blur", function(evt){
    document.getElementById("Field").value = '';
});

I tried this variation, but it does not work either…

//delete field contents and defocus when user clicks outside field
document.addEventListener("blur", function(evt){
    document.getElementById("Field").value = '';
});

Changing “document” to “window” does not resolve the problem either. Before, when I used “window.onload” it worked fine to clear the field contents when the user clicked outside the field.

Any idea what I am missing?

Thanks,

James W.

JDW

2 Mar 2017, 1:07 am

This doesn’t work either…

//delete field contents and defocus when user clicks outside field
function blurMe(evt){
    if (evt){
        document.getElementById("Field").value = '';
    }
}
window.addEventListener("blur", blurMe, false);

James W.

waltd

2 Mar 2017, 2:54 am

You’re missing something fundamental here. If you apply the listener to the search field element itself, then the event will be observed on the item that is creating it. The only reason you would need to wrap that listener in another listener is if you were putting your JavaScript in the head of the page. In that case, you have to wrap the field’s listener in a listener on the document itself, so you know when the document has finished loading.

This pen illustrates adding the listener on the search field:

http://codepen.io/walterdavis/pen/pegKbW

If you were going to put the JS code in the page head, rather than at the very bottom of the page in the Before /body position, then you would need to wrap the handler like this:

document.addEventListener('DOMContentLoaded', function(){
  document.getElementById('search').addEventListener('blur', function(){
    this.value = '';
  });
});

The outer one observes the page loading, and the inner one observes the form field blurring. It’s seriously easier to just move the code to the bottom of the page, though, and it means that you get a faster time to first paint on the screen.

You want to listen for these events as close to where they are emitted as possible. While the blur event will bubble out, and eventually reach the document, it’s just easier to listen directly from the input.

Walter

On Mar 1, 2017, at 8:07 PM, JDW <[email protected]> wrote:

This doesn’t work either…

//delete field contents and defocus when user clicks outside field
function blurMe(evt){
   if (evt){
       document.getElementById("Field").value = '';
   }
}
window.addEventListener("blur", blurMe, false);

James W.

Freeway user since 1997

http://www.walterdavisstudio.com

JDW

2 Mar 2017, 3:08 am

Hi Walter,

Thank you for the JS education! I confirmed your “wrapped” handler works great.

Per your suggestion about placement before </body>, are you saying I should put all my “addEventListener” code snippets in that location? Right now, I have everything placed before </head>, as follows:

//clear & unselect search field on page load
document.addEventListener("load",function(evt){
 var GF = document.getElementById("Field");
 //delete field contents and defocus on page load
 GF.value = "";
 GF.blur();
});

document.addEventListener('DOMContentLoaded', function(){
  document.getElementById('Field').addEventListener('blur', function(){
    this.value = '';
  });
});

//clear & reset search field on press of browser Back button
//(works in FF, Chrome & Safari, but not IE)
function pageShown(evt){
    var GF = document.getElementById("Field");
    if (evt.persisted){
        GF.value = "";
        GF.blur();
    }
}
window.addEventListener("pageshow", pageShown, false);

//prevents blue hover border from sticking in iOS Safari on browser BACK
function touchStart(evt){
    if (evt){
        document.getElementById("Field").style.border = "2px solid transparent";
    }
}
window.addEventListener("touchstart", touchStart, false);

//clear & reset search field on press of browser Back button in IE
function detectIE() {
    var ua = window.navigator.userAgent;
    var msie = ua.indexOf('MSIE '); //IE 10 & lower
    var trident = ua.indexOf('Trident/'); //IE 11
    var edge = ua.indexOf('Edge/');
    if (msie > 0 || trident > 0 || edge > 0) {
        document.getElementById("Field").value = "";
        document.getElementById("Field").blur();
    }
    return false; // browsers other than IE
}

waltd

2 Mar 2017, 3:36 am

You can put all of your JS in the before /body position, and it will work better (all page elements are guaranteed loaded, so you don’t have to wait for the page to load — no more wrappers. Speaking of which, your first two listeners below are doing almost the same thing. You should pick one, and don’t put both of them there. Try deleting the first one — I doubt you will need it now. In fact, try cutting things away and see how little you can get away with. The border appearing on back can be removed with CSS:

#Field { outline: none }

Walter

On Mar 1, 2017, at 10:08 PM, JDW <[email protected]> wrote:

Hi Walter,

Thank you for the JS education! I confirmed your “wrapped” handler works great.

Per your suggestion about placement before </body>, are you saying I should put all my “addEventListener” code snippets in that location? Right now, I have everything placed before </head>, as follows:

//clear & unselect search field on page load
document.addEventListener("load",function(evt){
var GF = document.getElementById("Field");
//delete field contents and defocus on page load
GF.value = "";
GF.blur();
});

document.addEventListener('DOMContentLoaded', function(){
 document.getElementById('Field').addEventListener('blur', function(){
   this.value = '';
 });
});

//clear & reset search field on press of browser Back button
//(works in FF, Chrome & Safari, but not IE)
function pageShown(evt){
   var GF = document.getElementById("Field");
   if (evt.persisted){
       GF.value = "";
       GF.blur();
   }
}
window.addEventListener("pageshow", pageShown, false);

//prevents blue hover border from sticking in iOS Safari on browser BACK
function touchStart(evt){
   if (evt){
       document.getElementById("Field").style.border = "2px solid transparent";
   }
}
window.addEventListener("touchstart", touchStart, false);

//clear & reset search field on press of browser Back button in IE
function detectIE() {
   var ua = window.navigator.userAgent;
   var msie = ua.indexOf('MSIE '); //IE 10 & lower
   var trident = ua.indexOf('Trident/'); //IE 11
   var edge = ua.indexOf('Edge/');
   if (msie > 0 || trident > 0 || edge > 0) {
       document.getElementById("Field").value = "";
       document.getElementById("Field").blur();
   }
   return false; // browsers other than IE
}

Freeway user since 1997

http://www.walterdavisstudio.com

JDW

2 Mar 2017, 4:38 am

Walter,

The border just acts as a hover state to highlight the search field. I set that border in the CSS. The only reason I use JS to kill it is because when I view the search results page and then click the browser back button, the border displays and continues to display even if I am not hovering over the search field. My JS prevents that problem from happening.

By the way, I just now began testing IE and Edge. Without the “window.onload” of my original JS code, clicking the browser BACK button from the Search Results page will leave the search term inside the search field. But when I use “window.onload”, that problem goes away (the search field properly gets blanked). I tried putting the JS just before </body> but the problem remains. Without “window.onload” search terms get stuck in the field when using modern IE or Edge. No other browser, not even Safari in iOS, needs “window.onload” — they clear the search term without it.

—James W.

JDW

2 Mar 2017, 5:07 am

This test page uses “window.onload” before </head> and works great in any browser, including stupid IE11 and Edge (but of course, it conflicts with Freeway rollovers that put “onload” in the “body” tag):

https://kiramek.com/search-test2.html

This version eliminates “window.onload” and puts all the JS before </body>, but IE11 and Edge retain the search-term inside the search field when you click the browser BACK button on the Search Results page:

https://kiramek.com/search-test3.html

To test the above pages, just click inside the search field and type “alarm” and then hit return.

—James W.

P.S. If you don’t have a Windoze computer, just download the free VM from MS here:

https://developer.microsoft.com/en-us/microsoft-edge/tools/vms/

I tested with “MS Edge on Win10 Stable” on “VirtualBox.” I also tested on a real Win10 computer and saw it respond the same. The VM comes with Edge and IE11, by the way.

JDW

2 Mar 2017, 5:33 am

Here’s a screencast showing the problem (no sound):

https://youtu.be/g6jCFl-yCqg

James W.

JDW

3 Mar 2017, 12:40 am

Walter,

Separate but related question…

I agree with your sound reasoning about putting JS before </body> instead of before </head>, but why does your Protaculous2 action put a link to the large “prototype.js” file before </head>? Why not before </body> instead? And why does Protaculous2 put “Additional JS Libraries” (which we type into the Actions palette) before </head>? Why not before </body>? Why does your Carousel2 action link to “scriptaculous.js” before </head>? Why does your ScriptyLightbox3 action link to “scripty_lightbox_3.js” before </head>? Is it a rule that all external scripts should be placed before </head>? Perhaps not in light of this…

https://www.nczonline.net/blog/2009/07/28/the-best-way-to-load-external-javascript/

Furthermore, I see a lot of Freeway-generated functions placed before </head> too, including:

  1. FWShowHideLayer
  2. FWLoad
  3. FWRestore
  4. FWLSwap
  5. FWCallHit
  6. FWSlave
  7. FWFindLayer

I have “render blocking” in mind when I pondering these things, especially the external *.js files which Google’s PageSpeed Tools dislikes.

—James W.

waltd

3 Mar 2017, 2:21 am

The Actions were all written a large number of years ago, when the thinking (and what was considered valid) was different. The current thinking (and Yahoo speed evaluations prove this out) is that you should put as much of the JS below the HTML content as possible, particularly after CSS and fonts, because they do block the rendering of the page until they load.

The Protaculouses all use a dom:loaded listener to make them only fire their scripts once the page has entirely loaded, which is why they don’t fail to work. But it’s even faster to not listen for the event, and simply use the empirical fact that the rest of the HTML has been requested to trigger your scripts.

When you’re looking at the core Actions, remember that many of them were written in the very late 90s and early ‘oughts. Times, and best practices, have changed.

Walter

On Mar 2, 2017, at 7:40 PM, JDW <[email protected]> wrote:

Walter,

Separate but related question…

I agree with your sound reasoning about putting JS before </body> instead of before </head>, but why does your Protaculous2 action put a link to the large “prototype.js” file before </head>? Why not before </body> instead? And why does Protaculous2 put “Additional JS Libraries” (which we type into the Actions palette) before </head>? Why not before </body>? Why does your Carousel2 action link to “scriptaculous.js” before </head>? Why does your ScriptyLightbox3 action link to “scripty_lightbox_3.js” before </head>? Is it a rule that all external scripts should be placed before </head>? Perhaps not in light of this…

https://www.nczonline.net/blog/2009/07/28/the-best-way-to-load-external-javascript/

Furthermore, I see a lot of Freeway-generated functions placed before </head> too, including:

  1. FWShowHideLayer
  2. FWLoad
  3. FWRestore
  4. FWLSwap
  5. FWCallHit
  6. FWSlave
  7. FWFindLayer

I have “render blocking” in mind when I pondering these things, especially the external *.js files which Google’s PageSpeed Tools dislikes.

—James W.

Freeway user since 1997

http://www.walterdavisstudio.com

JDW

3 Mar 2017, 4:21 am

Walter,

Thank you for the information about JS placement in light of how things have changed.

By the way, I was able to resolve the IE problem where the field wouldn’t get reset when the user clicks the BACK button from the Results page. While strange, my revised code works…

BEFORE (bad):

//clear & defocus search field after press of browser Back button on Results page
//(works in FF, Chrome & Safari, but not IE or Edge)
function pageShown(evt){
    if (evt.persisted){
        document.getElementById("Field").blur();
    } 
}
window.addEventListener("pageshow", pageShown, false);

AFTER (good):

//clear & defocus search field after press of browser Back button on Results page
//(works in FF, Chrome & Safari, but not IE or Edge)
function pageShown(evt){
    if (evt.persisted){
        document.getElementById("Field").blur();
    } else { document.getElementById("Field").value = ""; document.getElementById("Field").blur();}
}
window.addEventListener("pageshow", pageShown, false);

I tried it without the “if” statement at all, but that didn’t work. The addition of the “else” works. And I found that “blur();” needs to be in the “if” and both “blur();” and “value=”;” needs to be in the else. Confirmed in Edge(Win10), IE11(Win10), IE9(Visa), as well as Chrome and Firefox on Mac and Windows, as well as Safari, and iOS Safari, and FF on Android.

My code can now be placed before </body> without need for “window.onload” and it JustWorks.

Thanks again, for all your advice.

Sincerely,

James W.

JDW

3 Mar 2017, 8:47 am

One last question for you, Walter…

In the past in another thread, you kindly gave me the following code for use inside “DOM Loaded Observer” in your Protaculous2 Action. It displays an overlay (splash screen of sorts) when the page is first loaded and then a cookie is set so the overlay won’t bother the same user again for a week.

//this cookie ensures the patent-splash displays only once a week
var message_box = $('legaleze').setStyle('z-index: 1000');
$$('body').first().insert(message_box.remove());
//cookie expires once a week, in seconds:
var jar = new CookieJar({expires: '604800'});
if(!jar.get('hide_message')){
  message_box.show().observe(
    'click',
    function(evt){
      jar.put('hide_message',true);
      this.hide();
    }
  );
};

I copied the content of the external cookiejar.js file, minified it, and dumped that just above the above code in “DOM Loaded Observer.” What I want to do now is eliminate the reliance on prototype.js (delete Protaculous2 entirely on that page). To do that, I need to rewrite the above script in regular JS. Since I am not well versed in JS, this is proving to be a challenge.

I thought I could just extract the relevant functions contained inside prototype.js, but my oh my are there many, and so many are all tied together. It would be a huge amount of code to do it that way.

Is there some online tool that can magically take prototype code and change it to regular JS? (Probably not, since I couldn’t find it.)

Thanks,

James W.

waltd

3 Mar 2017, 1:38 pm

The entire point of Prototype is that it is optimized for developer speed primarily, and page speed secondarily. All those functions, all inter-related, is why you can write something in a terse one-liner and it will just work in every browser. The developers who invented it looked at JavaScript, and wanted it to be more like Ruby. And from Ruby comes the Principle of Least Surprise, meaning you can say $('item').remove(); or $$(‘items’ ).apply(‘highlight’);` and pretty well expect it to do what it says. Under the hood, all of that simplicity is paid for with an object-oriented kit of parts that take up thousands of lines of code, and plaster over the differences between browsers’ various interpretations of the standards.

The author of CookieJar was able to pack a lot of functionality and reliability into a very few lines of code because he had that base to stand on and that principle of programming to follow.

So rather than re-writing all of Prototype in order to get CookieJar, your best bet is to look for a “vanilla” version of what CookieJar does. I think if your goal is to write and read cookies from JavaScript, you’ll find something on MDN or Stack Overflow that can do that without too much drama. The document.cookie interface is built into JavaScript, and the only reason you would need a library function to access it is to translate the low-level interface into something you can call more simply. You’re not the only one using the cookie if you use Google Analytics or similar, so you have to dig “your” data out of an undifferentiated mass. That’s the bulk of the work that CookieJar does for you.

Walter

On Mar 3, 2017, at 3:47 AM, JDW <[email protected]> wrote:

One last question for you, Walter…

In the past in another thread, you kindly gave me the following code for use inside “DOM Loaded Observer” in your Protaculous2 Action. It displays an overlay (splash screen of sorts) when the page is first loaded and then a cookie is set so the overlay won’t bother the same user again for a week.

//this cookie ensures the patent-splash displays only once a week
var message_box = $('legaleze').setStyle('z-index: 1000');
$$('body').first().insert(message_box.remove());
//cookie expires once a week, in seconds:
var jar = new CookieJar({expires: '604800'});
if(!jar.get('hide_message')){
 message_box.show().observe(
   'click',
   function(evt){
     jar.put('hide_message',true);
     this.hide();
   }
 );
};

I copied the content of the external cookiejar.js file, minified it, and dumped that just above the above code in “DOM Loaded Observer.” What I want to do now is eliminate the reliance on prototype.js (delete Protaculous2 entirely on that page). To do that, I need to rewrite the above script in regular JS. Since I am not well versed in JS, this is proving to be a challenge.

I thought I could just extract the relevant functions contained inside prototype.js, but my oh my are there many, and so many are all tied together. It would be a huge amount of code to do it that way.

Is there some online tool that can magically take prototype code and change it to regular JS? (Probably not, since I couldn’t find it.)

Thanks,

James W.

Freeway user since 1997

http://www.walterdavisstudio.com

JDW

4 Mar 2017, 2:10 am

Thank you for the advice, Walter. I understand the power of the prototype framework , but it seems most JS programmers are using the jQuery library instead. There are other, albeit less popular JS libraries as well. For simple needs, I am thinking I should avoid all of these libraries altogether and just write pure JavaScript.

James W.

waltd

4 Mar 2017, 2:41 am

I understand and agree with your direction here. My point about Prototype wasn’t to say that you should use it, but that you don’t need to replace it entirely in order to get what you want done. The CookieJar tool is really cool and nicely written, and could not be written as simply as it is without Prototype, but there’s nothing about the problem of reading and writing cookies that can’t be done with vanilla JS.

Walter

On Mar 3, 2017, at 9:10 PM, JDW <[email protected]> wrote:

Thank you for the advice, Walter. I understand the power of the prototype framework , but it seems most JS programmers are using the jQuery library instead. There are other, albeit less popular JS libraries as well. For simple needs, I am thinking I should avoid all of these libraries altogether and just write pure JavaScript.

James W.

Freeway user since 1997

http://www.walterdavisstudio.com

Dianne Terwilliger

4 Mar 2017, 2:49 am

Please take me off this list, I don’t know how to get myself off of it. Thanks

On Fri, Mar 3, 2017 at 6:41 PM Walter Lee Davis <[email protected]> wrote:

I understand and agree with your direction here. My point about Prototype wasn’t to say that you should use it, but that you don’t need to replace it entirely in order to get what you want done. The CookieJar tool is really cool and nicely written, and could not be written as simply as it is without Prototype, but there’s nothing about the problem of reading and writing cookies that can’t be done with vanilla JS.

Walter

On Mar 3, 2017, at 9:10 PM, JDW <[email protected]> wrote:

Thank you for the advice, Walter. I understand the power of the prototype framework , but it seems most JS programmers are using the jQuery library instead. There are other, albeit less popular JS libraries as well. For simple needs, I am thinking I should avoid all of these libraries altogether and just write pure JavaScript.

James W.

Dianne Terwilliger [email protected]

waltd

4 Mar 2017, 3:48 pm

At the bottom of every message you get is a link where you can manage that. Nobody else can help you with it. If you’ve forgotten your password, there is a recovery system where you can either get it or reset it (can’t recall, it was many years ago when I wrote it).

Walter

On Mar 3, 2017, at 9:49 PM, Dianne Terwilliger <[email protected]> wrote:

Please take me off this list, I don’t know how to get myself off of it. Thanks

On Fri, Mar 3, 2017 at 6:41 PM Walter Lee Davis <[email protected]> wrote:

I understand and agree with your direction here. My point about Prototype wasn’t to say that you should use it, but that you don’t need to replace it entirely in order to get what you want done. The CookieJar tool is really cool and nicely written, and could not be written as simply as it is without Prototype, but there’s nothing about the problem of reading and writing cookies that can’t be done with vanilla JS.

Walter

On Mar 3, 2017, at 9:10 PM, JDW <[email protected]> wrote:

Thank you for the advice, Walter. I understand the power of the prototype framework , but it seems most JS programmers are using the jQuery library instead. There are other, albeit less popular JS libraries as well. For simple needs, I am thinking I should avoid all of these libraries altogether and just write pure JavaScript.

James W.

— Dianne Terwilliger [email protected]

Freeway user since 1997

http://www.walterdavisstudio.com

JDW

8 Mar 2017, 8:11 am

Walter,

I finalized my CSS and JS for my cookie application. No Protaculous2/Prototype or jQuery external libraries required.

The cookie is used only to remember the last time a DIV overlay was displayed, and when the cookie expires (I set it to 30 days), then the overlay will display again and a new cookie will be set when the user clicks anywhere on-screen to close the overlay. By using the cookie, the overlay is not bothersome (not displayed on every page load) to repeat visitors.

For the sake of others who wish to do something similar, here’s the code…

Put this CSS in “before </head> in Freeway’s HTML Markup dialog:

<style type="text/css">
/* DIV overlay is named "legaleze" */
    #legaleze{
   display:none;
   top: 0;
   left: 0;
   right: 0;
   bottom:0;
   background-color: white;
   opacity: 0.9;
   filter: alpha(opacity=90);
}
/* Close box is named "box" */
    #box:hover {
  background-color: red;
  cursor: pointer;
}
</style>

Put this JS in “before </body>” in Freeway’s HTML markup dialog:

<script type="text/javascript">
function setCookie(cname,cvalue,exdays) {
    var d = new Date();
    d.setTime(d.getTime() + (exdays*24*60*60*1000));
    document.cookie = cname + "=" + cvalue + ";" + "expires=" + d.toGMTString() + ";path=/";
}
function getCookie(cname) {
    var name = cname + "=";
    var ca = decodeURIComponent(document.cookie).split(';');
    for(var i = 0; i < ca.length; i++) {
        var c = ca[i];
        while (c.charAt(0) == ' ') {
            c = c.substring(1);
        }
        if (c.indexOf(name) == 0) {
            return c.substring(name.length, c.length);
        }
    }
    return "";
}
document.addEventListener('DOMContentLoaded', function(){
    var cook=getCookie("kiramek_patent_notice");
    if (cook === "Show every 30 days") { //do nothing
    } else { //close the overlay on click and set cookie
    document.getElementById("legaleze").style.display = 'block';
    document.getElementById('legaleze').onclick = function(){ 
        document.getElementById("legaleze").style.display = 'none'; 
        setCookie("kiramek_patent_notice", "Show every 30 days", 30);
        }
    }
});
</script

NOTE: Add the closing greater-than symbol to the end of /script above. I tried to add it, but it totally messes up the line breaks here on FreewayTalk when I do that, even though it’s situated within “~~~~ ” tags.

—James Wages

waltd

8 Mar 2017, 12:13 pm

This is great work, James. As far as the code tags go — they are really just a hack, I never spent any time on them besides getting them to parse the very few posts left over from the interregnum period when this mailing list was hosted on PHPBB. This list uses Markdown, not BBCode. To make a block script tag, either indent every line with one tab or four spaces, or make a “fenced” code block with four tildes in a row, on a line by itself, before and after the block of code. And if you really want your code to look great (color highlighting and everything) make a Gist or Pastie, and put the link to the resulting page all by itself on one line here.

Walter

On Mar 8, 2017, at 3:11 AM, JDW <[email protected]> wrote:

I tried to add it, but it totally messes up the line breaks here on FreewayTalk when I do that, even though it’s situated within “~~~~ ” tags.

Freeway user since 1997

http://www.walterdavisstudio.com

JDW

9 Mar 2017, 12:50 am

Thank you for the Gist/Pastie suggestion, Walter. That code is indeed lovely to behold!

James W.

JDW

9 Mar 2017, 4:18 am

Walter, I created a Gist but when I paste the URL into this field here on FreewayTalk, the URL does not appear in the Preview! The only way I can get it to display is by putting it inside “code” tags like this:

<https://gist.github.com/JDW1/2c2b619fb6bca99fdbfd43d4a4c49b2c#file-gistfile1-txt>

I copied your Gist’s URL above and pasted it into my post here, but that URL too won’t display in Preview. How in the world did you insert it?

Furthermore, when I view my Gist on Gist Hub, it is not colored. What’s the trick to that?

Thanks,

James

waltd

9 Mar 2017, 10:00 am

The Gist (or Pastie) only appears in FreewayTalk after you publish the new post. That’s a long-standing bug that I never fixed while I had the chance, and now can’t fix because I no longer have access to the server.

In my usual use-case, I just paste the URL in Mail.app when I compose messages there, so I don’t see that distinction. The color syntax highlighting is dependent on you setting the correct file type, either by giving the Gist a fake filename when you create it, as I did, or by using the file type picker to choose the programming language. Both of those options are in the Gist interface, not the FreewayTalk one.

In the case of your example, which I just pasted into Gist, the fact that it had <script> tags meant that it was HTML, so I ended my example’s “filename” with .html. That was all the clue that the formatter needed. I could also have stripped off the <script> tags, and set it to .js, and that would have worked similarly.

Walter

On Mar 8, 2017, at 11:18 PM, JDW <[email protected]> wrote:

Walter, I created a Gist but when I paste the URL into this field here on FreewayTalk, the URL does not appear in the Preview! The only way I can get it to display is by putting it inside “code” tags like this:

<https://gist.github.com/JDW1/2c2b619fb6bca99fdbfd43d4a4c49b2c#file-gistfile1-txt>

I copied your Gist’s URL above and pasted it into my post here, but that URL too won’t display in Preview. How in the world did you insert it?

Furthermore, when I view my Gist on Gist Hub, it is not colored. What’s the trick to that?

Thanks,

James

Freeway user since 1997

http://www.walterdavisstudio.com

waltd

9 Mar 2017, 10:07 am

I almost forgot my favorite reason for using these services — unlike an e-mail, you can edit them after the fact. I cannot count the number of times I have posted something example-shaped, read through what I wrote (after I sent it) and saw a typo that either altered the meaning or broke the example entirely. I can go back and edit a Gist, and the next person to see it embedded in FreewayTalk will see the corrected version.

True, sometimes there is value in my errors, and pointing them out, and correcting them “in public” with a follow up message. But if a person comes along later, parachuted into the conversation by Google (or the fabulous Sphinx search engine in FreewayTalk.net), then they also have to piece together the real solution over multiple messages in a thread. Sometimes having everything together and fully baked is just nicer.

Walter

On Mar 9, 2017, at 5:00 AM, Walter Lee Davis <[email protected]> wrote:

The Gist (or Pastie) only appears in FreewayTalk after you publish the new post. That’s a long-standing bug that I never fixed while I had the chance, and now can’t fix because I no longer have access to the server.

In my usual use-case, I just paste the URL in Mail.app when I compose messages there, so I don’t see that distinction. The color syntax highlighting is dependent on you setting the correct file type, either by giving the Gist a fake filename when you create it, as I did, or by using the file type picker to choose the programming language. Both of those options are in the Gist interface, not the FreewayTalk one.

In the case of your example, which I just pasted into Gist, the fact that it had <script> tags meant that it was HTML, so I ended my example’s “filename” with .html. That was all the clue that the formatter needed. I could also have stripped off the <script> tags, and set it to .js, and that would have worked similarly.

Walter

On Mar 8, 2017, at 11:18 PM, JDW <[email protected]> wrote:

Walter, I created a Gist but when I paste the URL into this field here on FreewayTalk, the URL does not appear in the Preview! The only way I can get it to display is by putting it inside “code” tags like this:

<https://gist.github.com/JDW1/2c2b619fb6bca99fdbfd43d4a4c49b2c#file-gistfile1-txt>

I copied your Gist’s URL above and pasted it into my post here, but that URL too won’t display in Preview. How in the world did you insert it?

Furthermore, when I view my Gist on Gist Hub, it is not colored. What’s the trick to that?

Thanks,

James

Freeway user since 1997

http://www.walterdavisstudio.com

JDW

10 Mar 2017, 12:31 am

I never use an email client to post to this list. I simply receive email notifications that replies have appear, then I come here with Safari and do my thing. Because we cannot EDIT or DELETE posts (for reasons I already know), I am very cautious about posting, which is why I noticed the URL missing in the Preview. The Preview is my Savior! It keeps me from posting a train of separate posts which can be hard to read and boggle up discussions. But since you cannot access the server to fix the problem, I guess it cannot be helped. So I will conduct a truly “blind” test here to see if a CSS Gist will come through as I expect…

The following is a copy/paste of the “Embed” URL (with SCRIPT tags) at GitHubGist:

Fingers crossed it displays.

James Wages

JDW

10 Mar 2017, 12:32 am

Holy cow, it does display fine! Well, that’s a relief. I shall remember this trick when posting in other threads. Thanks, Walter.

James W.

waltd

10 Mar 2017, 12:43 am

It’s even easier than that — just grab the HTML page URL. No need to fiddle with the embed widget business. Copy and paste just the full HTML URL to the Gist as you see it in your browser after initially creating it. The FreewayTalk server is smart enough to recognize a Gist (or Pastie.org) URL on its own on a line in your post and turn that into the entire script tag to do the embed thing.

Walter

On Mar 9, 2017, at 7:32 PM, JDW <[email protected]> wrote:

Holy cow, it does display fine! Well, that’s a relief. I shall remember this trick when posting in other threads. Thanks, Walter.

James W.

Freeway user since 1997

http://www.walterdavisstudio.com

JDW

10 Mar 2017, 1:04 am

Understood. Thanks!

JDW

14 Mar 2017, 2:18 am

For the sake of others who may come lurking into this thread, I wish to mention that I updated my code today to eliminate the second inline SVG, making the code a tad more compact.

Originally I used a gray magnifier icon as the normal state and a white one as the rollover (focus) state. But I realized I could eliminate one SVG by simply leveraging opacity in the CSS. However, it took a little time to work out the kinks. For some reason, Safari and Chrome (Webkit) were fading the placeholder text, while FireFox and IE/Edge were not. (Actually, FF usually fades the placeholder text, but using the opacity attribute set to 1.0 fixes that, but doing the same would not fix Webkit.) The fix was for me to simply reorder the first three lines of the CSS. Instead of having the “input::-webkit-input-placeholder” line first, I put it third, beneath the 2 Mozilla lines, and magically (again, I don’t know why) Safari and Chrome stopped fading my placeholder text and now it looks the same across all browsers.

Here’s my updated Fiddle: https://jsfiddle.net/JDW1/p37x6mgc/

Since the SVG I use is an inline background-image, to ensure cross-browser compatibility, I used the following SVG encoder:

http://yoksel.github.io/url-encoder/

You can download the original unencoded SVG from my website here (it’s WHITE so you can’t see it in-browser): https://kiramek.com/SearchMagWHT.svg

Also note that if you Minify the CSS, you cannot Minify the SVG code or it won’t display. So just Minify all your CSS here:

http://www.minifier.org

Then replace the SVG part of the minified code with the unmagnified (but encoded) SVG. And yes, if you’re wondering, you can still shave off a fair amount from your code if you Minify and use GZIP on your web server. It isn’t a lot, but sometimes every little bit counts.

I tested this JS/CSS combination in all modern browsers on Windows and Mac, as well as in iOS. It works well, I think.

Best wishes,

James Wages

Back to Top

JDW

14 Mar 2017, 2:38 am

If you are wondering why I used “initial” in the second line of the following code instead of “all”…

    -webkit-transition: all 0.4s ease-in-out;
    transition: initial 0.4s ease-in-out

…it’s because Explorer and even Edge are stupid. (Don’t we all know that by now?) Meaning, those lovely browsers from MS will cause the SVG to vanish until the 400ms is finish and then the roll state SVG will appear (yes, even when rolled by opacity change). Just plain stupid. To fix, I used the “initial” attribute on the “transition” line. That means most every other modern browser (Chrome, FF, Safari, etc., even on iOS) will show the ease-in-out just fine, but silly explorer won’t show the transition at all, just making the roll state appear instantly. I also found older versions of FF running on WinXP won’t show the transition due to my hack either, but that’s okay with me. And yes, I tested Opera on MacOS Sierra, and it works fine.

—James Wages