jQuery Address: Certify that user is pressing forw

2019-06-19 13:22发布

问题:

EDIT 3: This jsFiddle works with the plugin, I almost have it.

EDIT 2: I made a fiddle.I can't get the plugin to work there, but maybe it is easier to analyze.


In the webpage I am building, Articles(posts) and new Pages are loaded via Ajax. At the same time when new Ajax-content is loaded, the address bar changes (using jQuery Address plugin).

So a normal navigation would go like this:

       /       /page2       /page3       /article7       /page3       /page4

Please note that in this navigation, no browser button was pressed, when exiting the article7 the website goes back to its prior url which is page3 in this case.

The plugin doesn't detect when the user pressed the back or forward button. I managed to figure out a way to know when the user presses back or forward button:

Each time new content is added and the address is changed I store the new address in an array. If the user presses the back'or'forward button I analise it this way:

if (new_url == penultimate_value_in_array) => Back button pressed (errase last value from array)
else => Forward button pressed (add new value to array)

This works correctly for this kind of navigation:

       /       /page2       /page3       /page4

In my case, it works perfect for the Back button. However if the user presses Forward from /article7 to /page3 the function will read it as Back. Here is an example to understand what I mean:


user is in /page4 and presses Back -> new_page=/page3 that is equal to penultimate_page_in_array(/page3) => BACK

       /       /page2       /page3       /article7       /page3       /page4

user is in /page3 and presses Back -> new_page=/article7 that is equal to penultimate_page_in_array(/article7) => BACK

       /       /page2       /page3       /article7       /page3

user is in /article7 and presses Back -> new_page=/page3 that is equal to penultimate_page_in_array(/page3) => BACK

       /       /page2       /page3       /article7

user is in /page3 and presses Back -> new_page=/page2 that is equal to penultimate_page_in_array(/page2) => BACK

       /       /page2       /page3

user is in /page2 and presses Forward -> new_page=/page3 that is NOT equal to penultimate_page_in_array(/) => FORWARD

       /       /page2

user is in /page3 and presses Forward -> new_page=/article7 that is NOT equal to penultimate_page_in_array(/page2) => FORWARD

       /       /page2       /page3

user is in /article7 and presses Forward -> new_page=/page3 that IS equal to penultimate_page_in_array(/page3) => BACK (and here the value should be FORWARD)

       /       /page2       /page3       /article7

How can I introduce another statement that would determine that False Back should be Forward?



EDIT:

This is the code I am using, I'm not sure if it will help to resolve the issue but here it is:

var site_url = 'www.mysite.com',
    last_visited_url = '',
    just_visited_url = $.address.baseURL().replace(site_url,''),
    visited_pages_array = [just_visited_url],
    page_number = '';

when visiting new page: ajax call,then:

last_visited_url = just_visited_url;
page_number = $('a.next_page_link').attr('href').replace(site_url,''); // /page3 for example
$.address.state(site_url).value(page_number);
just_visited_url = page_number;
visited_pages_array.push(just_visited_url);

when loading Article: ajax call,then:

article_url = $('a.article_title').attr('href').replace(site_url,''); // /article7 for example
last_visited_url = just_visited_url;
$.address.state(site_url).value(article_url);
just_visited_url = article_url;
visited_pages_array.push(just_visited_url);

when existing an Article:

last_visited_url = just_visited_url;
$.address.state(site_url).value(page_number); // This page number is the last page_number value
just_visited_url = page_number;
visited_pages_array.push(just_visited_url);

And this code is executed when the user presses some of the browser butons:

$.address.externalChange(function() {

    var newPage = $.address.baseURL().replace(site_url,'');

    if (visited_pages_array[visited_pages_array.length-2] == newPage) {

        visited_pages_array.splice(visited_pages_array.length-1 , 1);
        console.log('BACK pressed');

    } else if (visited_pages_array.length > 1) {

        visited_pages_array.push(newPage);
        console.log('FORWARD pressed');

    } else {

        console.log('REFRESH pressed');

    }

});

回答1:

The fastest and easiest solution I can think of is the following:

Your problem is that when your "next" and "previous" pages are the same, pressing Forward is detected by your code as Back because the following condition is true:

visited_pages_array[visited_pages_array.length-2] == newPage

I would recommend 2 things in your case:

  1. DO NOT delete the address you just left from visited_pages_array as in:

    visited_pages_array.splice(visited_pages_array.length-1 , 1);

    that way visited_pages_array will keep a list of all visited pages.

  2. Create a new "global" variable called current_page_index that will hold the index of your current page in visited_pages_array which can now hold visited_pages_array.length-1 if you are currently at the last page visited or lower values if you used Back button.

Now all you have to do is change your condition from:

if (visited_pages_array[visited_pages_array.length-2] == newPage)

to:

if (visited_pages_array[current_page_index-1] == newPage)

Notes:

  1. When you detect a Back click - do this: current_page_index--; and when you detect a Forward do: current_page_index++;
  2. When the user clicks your navigation to move the another page, MAKE SURE to do: visited_pages_array.splice(current_page_index+1 ,visited_pages_array.length-current_page_index-1); (removing all the saved Forwards) before pushing the new address to the end of visited_pages_array. And ofcourse setting current_page_index++;

I hope this is clear enough, I couldn't get your jsFiddle to work so explained as clearly as I can. GL :)

EDIT: another idea taken from the jQuery Address docs: (not sure about this one though)

$.address.externalChange(fn): Binds a function to be executed when the address is changed from the browser usually when entering the page or using the back and forward buttons. The function receives a single event object parameter that contains the following properties: value, path, pathNames, parameterNames, parameters and queryString.

which means your function can receive an event object - try alert()ing all it's properties maybe the answer will be lying there

$.address.externalChange(function(ev){
    // loop and alert ev's properties
    for (var p in ev) {
        alert(p + ': ' + ev[p]);
    }
})


回答2:

I am not completely sure about your logic here, but what you are describing sounds like a perfect candidate for html5 pushState (browser history state manipulation) functionality. Here are a few good summaries:

  • Reference 1
  • Reference 2

Also, here are some good demos from fellow stackoverflow users:

HTML5 History API Demo