Rectangle 27 7

If you are looking for the simplest "back" button, then you could set up a directive like so:

.directive('back', function factory($window) {
      return {
        restrict   : 'E',
        replace    : true,
        transclude : true,
        templateUrl: 'wherever your template is located',
        link: function (scope, element, attrs) {
          scope.navBack = function() {
            $window.history.back();
          };
        }
      };
    });

Keep in mind this is a fairly unintelligent "back" button because it is using the browser's history. If you include it on your landing page, it will send a user back to any url they came from prior to landing on yours.

javascript - How do I get the Back Button to work with an AngularJS ui...

javascript coffeescript angular-ui-router
Rectangle 27 7

If you are looking for the simplest "back" button, then you could set up a directive like so:

.directive('back', function factory($window) {
      return {
        restrict   : 'E',
        replace    : true,
        transclude : true,
        templateUrl: 'wherever your template is located',
        link: function (scope, element, attrs) {
          scope.navBack = function() {
            $window.history.back();
          };
        }
      };
    });

Keep in mind this is a fairly unintelligent "back" button because it is using the browser's history. If you include it on your landing page, it will send a user back to any url they came from prior to landing on yours.

javascript - How do I get the Back Button to work with an AngularJS ui...

javascript coffeescript angular-ui-router
Rectangle 27 83

So, I've seen these questions frequently on SO, and have recently run into the issue of controlling back button functionality myself. After a few days of searching for the best solution for my application (Single-Page with Hash Navigation), I've come up with a simple, cross-browser, library-less system for detecting the back button.

window.onhashchange = function() {
 //blah blah blah
}

However, this function will also be called when a user uses on in-page element that changes the location hash. Not the best user experience when your user clicks and the page goes backwards or forwards.

To give you a general outline of my system, I'm filling up an array with previous hashes as my user moves through the interface. It looks something like this:

function updateHistory(curr) {
    window.location.lasthash.push(window.location.hash);
    window.location.hash = curr;
}

Pretty straight forward. I do this to ensure cross-browser support, as well as support for older browsers. Simply pass the new hash to the function, and it'll store it for you and then change the hash (which is then put into the browser's history).

I also utilise an in-page back button that moves the user between pages using the lasthash array. It looks like this:

function goBack() {
    window.location.hash = window.location.lasthash[window.location.lasthash.length-1];
    //blah blah blah
    window.location.lasthash.pop();
}

So this will move the user back to the last hash, and remove that last hash from the array (I have no forward button right now).

So. How do I detect whether or not a user has used my in-page back button, or the browser button?

At first I looked at window.onbeforeunload, but to no avail - that is only called if the user is going to change pages. This does not happen in a single-page-application using hash navigation.

So, after some more digging, I saw recommendations for trying to set a flag variable. The issue with this in my case, is that I would try to set it, but as everything is asynchronous, it wouldn't always be set in time for the if statement in the hash change. .onMouseDown wasn't always called in click, and adding it to an onclick wouldn't ever trigger it fast enough.

This is when I started to look at the difference between document, and window. My final solution was to set the flag using document.onmouseover, and disable it using document.onmouseleave.

What happens is that while the user's mouse is inside the document area (read: the rendered page, but excluding the browser frame), my boolean is set to true. As soon as the mouse leaves the document area, the boolean flips to false.

window.onhashchange
window.onhashchange = function() {
    if (window.innerDocClick) {
        window.innerDocClick = false;
    } else {
        if (window.location.hash != '#undefined') {
            goBack();
        } else {
            history.pushState("", document.title, window.location.pathname);
            location.reload();
        }
    }
}

You'll note the check for #undefined. This is because if there is no history available in my array, it returns undefined. I use this to ask the user if they want to leave using a window.onbeforeunload event.

So, in short, and for people that aren't necessarily using an in-page back button or an array to store the history:

document.onmouseover = function() {
    //User's mouse is inside the page.
    window.innerDocClick = true;
}

document.onmouseleave = function() {
    //User's mouse has left the page.
    window.innerDocClick = false;
}

window.onhashchange = function() {
    if (window.innerDocClick) {
        //Your own in-page mechanism triggered the hash change
    } else {
        //Browser back button was clicked
    }
}

And there you have it. a simple, three-part way to detect back button usage vs in-page elements with regards to hash navigation.

To ensure that the user doesn't use backspace to trigger the back event, you can also include the following (Thanks to @thetoolman on this Question):

$(function(){
    /*
     * this swallows backspace keys on any non-input element.
     * stops backspace -> back
     */
    var rx = /INPUT|SELECT|TEXTAREA/i;

    $(document).bind("keydown keypress", function(e){
        if( e.which == 8 ){ // 8 == backspace
            if(!rx.test(e.target.tagName) || e.target.disabled || e.target.readOnly ){
                e.preventDefault();
            }
        }
    });
});

+1 nice idea, but i think this will fail if user uses whatever keyboard shortcut is for "back" (backspace key on firefox) whilst his mouse is inside browser window

Will do - I'm in the office right now anyways :) (EDIT: Done now)

What about swipe events from trackpad in MAC. Could that be captured as well?

javascript - How to Detect Browser Back Button event - Cross Browser -...

javascript cross-browser single-page-application back
Rectangle 27 68

Yes, it is possible to have the browser back/forward (history) and refresh whilst running a pure ui-router state-machine but it takes a bit of doing.

Here is my implementation of each of these requirements. I have bundled everything up into three services:

class SessionService

    setStorage:(key, value) ->
        json =  if value is undefined then null else JSON.stringify value
        sessionStorage.setItem key, json

    getStorage:(key)->
        JSON.parse sessionStorage.getItem key

    clear: ->
        @setStorage(key, null) for key of sessionStorage

    stateHistory:(value=null) ->
        @accessor 'stateHistory', value

    # other properties goes here

    accessor:(name, value)->
        return @getStorage name unless value?
        @setStorage name, value

angular
.module 'app.Services'
.service 'sessionService', SessionService
sessionStorage
class StateHistoryService
    @$inject:['sessionService']
    constructor:(@sessionService) ->

    set:(key, state)->
        history = @sessionService.stateHistory() ? {}
        history[key] = state
        @sessionService.stateHistory history

    get:(key)->
        @sessionService.stateHistory()?[key]

angular
.module 'app.Services'
.service 'stateHistoryService', StateHistoryService

The StateHistoryService looks after the storage and retrieval of historical states keyed by generated, unique urls. It is really just a convenience wrapper for a dictionary style object.

class StateLocationService
    preventCall:[]
    @$inject:['$location','$state', 'stateHistoryService']
    constructor:(@location, @state, @stateHistoryService) ->

    locationChange: ->
        return if @preventCall.pop('locationChange')?
        entry = @stateHistoryService.get @location.url()
        return unless entry?
        @preventCall.push 'stateChange'
        @state.go entry.name, entry.params, {location:false}

    stateChange: ->
        return if @preventCall.pop('stateChange')?
        entry = {name: @state.current.name, params: @state.params}
        #generate your site specific, unique url here
        url = "/#{@state.params.subscriptionUrl}/#{Math.guid().substr(0,8)}"
        @stateHistoryService.set url, entry
        @preventCall.push 'locationChange'
        @location.url url

angular
.module 'app.Services'
.service 'stateLocationService', StateLocationService
StateLocationService

The big problem with this technique is that calling @location.url url in the stateChange method will trigger the $locationChangeSuccess event and so call the locationChange method. Equally calling the @state.go from locationChange will trigger the $stateChangeSuccess event and so the stateChange method. This gets very confusing and messes up the browser history no end.

The solution is very simple. You can see the preventCall array being used as a stack (pop and push). Each time one of the methods is called it prevents the other method being called one-time-only. This technique does not interfere with the correct triggering of the $ events and keeps everything straight.

Now all we need to do is call the HistoryService methods at the appropriate time in the state transition life-cycle. This is done in the AngularJS Apps .run method, like this:

angular
.module 'app', ['ui.router']
.run ($rootScope, stateLocationService) ->

    $rootScope.$on '$stateChangeSuccess', (event, toState, toParams) ->
        stateLocationService.stateChange()

    $rootScope.$on '$locationChangeSuccess', ->
        stateLocationService.locationChange()

Generate a Guid

Math.guid = ->
    s4 = -> Math.floor((1 + Math.random()) * 0x10000).toString(16).substring(1)
    "#{s4()}#{s4()}-#{s4()}-#{s4()}-#{s4()}-#{s4()}#{s4()}#{s4()}"

With all this in place, the forward / back buttons and the refresh button all work as expected.

in the example of the SessionService above, I think the accessor: method should be using @setStorage and @getStorage rather than `@get/setSession'.

Which language is used for this example. Doesn't seem to be angular that i am familiar with.

The language was javascript, the syntax was coffeescript.

@jlguenego You have a functional browser history/ bowser back and forth buttons and URL's that you can bookmark.

@jlguenego - the answers that suggest using variations of $window.history.back() have missed a crucial part of the question. The point was to restore the application's state to the correct state-location as the history jumps (back/forward/refresh). This would normally be achieved by supplying the state data via the URI. The question asked how to jump between state-locations without (explicit) URI state data. Given this constraint, it is not sufficient to just replicate the back button because this relies on the URI state data to re-establish the state-location.

javascript - How do I get the Back Button to work with an AngularJS ui...

javascript coffeescript angular-ui-router
Rectangle 27 67

Yes, it is possible to have the browser back/forward (history) and refresh whilst running a pure ui-router state-machine but it takes a bit of doing.

Here is my implementation of each of these requirements. I have bundled everything up into three services:

class SessionService

    setStorage:(key, value) ->
        json =  if value is undefined then null else JSON.stringify value
        sessionStorage.setItem key, json

    getStorage:(key)->
        JSON.parse sessionStorage.getItem key

    clear: ->
        @setStorage(key, null) for key of sessionStorage

    stateHistory:(value=null) ->
        @accessor 'stateHistory', value

    # other properties goes here

    accessor:(name, value)->
        return @getStorage name unless value?
        @setStorage name, value

angular
.module 'app.Services'
.service 'sessionService', SessionService
sessionStorage
class StateHistoryService
    @$inject:['sessionService']
    constructor:(@sessionService) ->

    set:(key, state)->
        history = @sessionService.stateHistory() ? {}
        history[key] = state
        @sessionService.stateHistory history

    get:(key)->
        @sessionService.stateHistory()?[key]

angular
.module 'app.Services'
.service 'stateHistoryService', StateHistoryService

The StateHistoryService looks after the storage and retrieval of historical states keyed by generated, unique urls. It is really just a convenience wrapper for a dictionary style object.

class StateLocationService
    preventCall:[]
    @$inject:['$location','$state', 'stateHistoryService']
    constructor:(@location, @state, @stateHistoryService) ->

    locationChange: ->
        return if @preventCall.pop('locationChange')?
        entry = @stateHistoryService.get @location.url()
        return unless entry?
        @preventCall.push 'stateChange'
        @state.go entry.name, entry.params, {location:false}

    stateChange: ->
        return if @preventCall.pop('stateChange')?
        entry = {name: @state.current.name, params: @state.params}
        #generate your site specific, unique url here
        url = "/#{@state.params.subscriptionUrl}/#{Math.guid().substr(0,8)}"
        @stateHistoryService.set url, entry
        @preventCall.push 'locationChange'
        @location.url url

angular
.module 'app.Services'
.service 'stateLocationService', StateLocationService
StateLocationService

The big problem with this technique is that calling @location.url url in the stateChange method will trigger the $locationChangeSuccess event and so call the locationChange method. Equally calling the @state.go from locationChange will trigger the $stateChangeSuccess event and so the stateChange method. This gets very confusing and messes up the browser history no end.

The solution is very simple. You can see the preventCall array being used as a stack (pop and push). Each time one of the methods is called it prevents the other method being called one-time-only. This technique does not interfere with the correct triggering of the $ events and keeps everything straight.

Now all we need to do is call the HistoryService methods at the appropriate time in the state transition life-cycle. This is done in the AngularJS Apps .run method, like this:

angular
.module 'app', ['ui.router']
.run ($rootScope, stateLocationService) ->

    $rootScope.$on '$stateChangeSuccess', (event, toState, toParams) ->
        stateLocationService.stateChange()

    $rootScope.$on '$locationChangeSuccess', ->
        stateLocationService.locationChange()

Generate a Guid

Math.guid = ->
    s4 = -> Math.floor((1 + Math.random()) * 0x10000).toString(16).substring(1)
    "#{s4()}#{s4()}-#{s4()}-#{s4()}-#{s4()}-#{s4()}#{s4()}#{s4()}"

With all this in place, the forward / back buttons and the refresh button all work as expected.

in the example of the SessionService above, I think the accessor: method should be using @setStorage and @getStorage rather than `@get/setSession'.

Which language is used for this example. Doesn't seem to be angular that i am familiar with.

The language was javascript, the syntax was coffeescript.

@jlguenego You have a functional browser history/ bowser back and forth buttons and URL's that you can bookmark.

@jlguenego - the answers that suggest using variations of $window.history.back() have missed a crucial part of the question. The point was to restore the application's state to the correct state-location as the history jumps (back/forward/refresh). This would normally be achieved by supplying the state data via the URI. The question asked how to jump between state-locations without (explicit) URI state data. Given this constraint, it is not sufficient to just replicate the back button because this relies on the URI state data to re-establish the state-location.

javascript - How do I get the Back Button to work with an AngularJS ui...

javascript coffeescript angular-ui-router
Rectangle 27 43

app.run(['$window', '$rootScope', 
function ($window ,  $rootScope) {
  $rootScope.goBack = function(){
    $window.history.back();
  }
}]);

<a href="#" ng-click="goBack()">Back</a>

love this! ... lol ... for clarity $window.history.back is doing the magic not $rootScope ... so go back could be bound to your navbar directive scope if you want.

@BenjaminConant For people who don't know how to implement this, you simply put the $window.history.back(); in a function to be called upon ng-click.

correct rootScope is only to make the function accessible in any template

javascript - How do I get the Back Button to work with an AngularJS ui...

javascript coffeescript angular-ui-router
Rectangle 27 43

app.run(['$window', '$rootScope', 
function ($window ,  $rootScope) {
  $rootScope.goBack = function(){
    $window.history.back();
  }
}]);

<a href="#" ng-click="goBack()">Back</a>

love this! ... lol ... for clarity $window.history.back is doing the magic not $rootScope ... so go back could be bound to your navbar directive scope if you want.

@BenjaminConant For people who don't know how to implement this, you simply put the $window.history.back(); in a function to be called upon ng-click.

correct rootScope is only to make the function accessible in any template

javascript - How do I get the Back Button to work with an AngularJS ui...

javascript coffeescript angular-ui-router
Rectangle 27 26

This can't be done using javascript. Some people think that Facebook is reading what's currently on the page. It's not. It makes a separate request to your server using the same url (from window.location.href) using it's Scraper, and the Facebook Scraper does not run javascript. That's why you get {{page_title}} when clicking on something like a Facebook share button. Your content will have to be generated by the server so when Facebook goes to hit the url it gets the content it needs up front without the need for javascript. You can tackle the server side rendering in a fews ways.

  • You can allow your server side technology to render the content.

Check prerender.io, it is also based on phantomjs but seems to support multiple js frameworks and server platforms like node, java or php.

I've outlined a simple implementation of Earl's first suggestion (server-side rendering) in an article here: michaelbromley.co.uk/blog/171/

facebook - og meta tags, social buttons and angularjs - Stack Overflow

facebook angularjs facebook-opengraph
Rectangle 27 20

After testing different proposals, I found that the easiest way is often the best.

If you use angular ui-router and that you need a button to go back best is this:

<button onclick="history.back()">Back</button>
<a onclick="history.back()>Back</a>

// Warning don't set the href or the path will be broken.

Explanation: Suppose a standard management application. Search object -> View object -> Edit object

Well that's what we wanted except if now you click the browser back button you'll be there again :

And that is not logical

However using the simple solution

<a onclick="history.back()"> Back </a>

from :

after click on browser back button :

javascript - How do I get the Back Button to work with an AngularJS ui...

javascript coffeescript angular-ui-router
Rectangle 27 20

After testing different proposals, I found that the easiest way is often the best.

If you use angular ui-router and that you need a button to go back best is this:

<button onclick="history.back()">Back</button>
<a onclick="history.back()>Back</a>

// Warning don't set the href or the path will be broken.

Explanation: Suppose a standard management application. Search object -> View object -> Edit object

Well that's what we wanted except if now you click the browser back button you'll be there again :

And that is not logical

However using the simple solution

<a onclick="history.back()"> Back </a>

from :

after click on browser back button :

javascript - How do I get the Back Button to work with an AngularJS ui...

javascript coffeescript angular-ui-router
Rectangle 27 1

<button type="button"></button>

2) Your problem can be solved few ways:

a) Save all values on clicking Next to session and when returning to page, just save all values. Your inputs than will look something like<input type='text' value='<?php echo isset($_SESSION['a1']) ? $_SESSION['a1'] : ''; ?>' name='a1'/>; In PHP side: $_SESSION['a1'] = isset($_POST['a1']) ? $_POST['a1'] : '';. In last confirmation step you save values from last form + values from session to database and clear your session.

b) You can use single form with tabs in it and only show specific tab with jQuery/js:

<div class='tab' data-ref='#tab1'>First step tab</div>
<div class='tabContent' id='tab1'>Content of first step tab</div>

$('.tab').click(function(){
    $('.tabContent').hide();
    $($(this).data('ref')).show();
});

Thanks for taking time and explaining me, and I went for the option B but only with php :D

javascript - Back Button with keeping form value - Stack Overflow

javascript php forms back
Rectangle 27 20

One cannot disable the browser back button functionality only thing that can be done is prevent them.

Below JavaScript code needs to be placed in the head section of the page where you dont want the user to revisit using the back button:

<script>
  function preventBack(){window.history.forward();}
  setTimeout("preventBack()", 0);
  window.onunload=function(){null};
</script>
Page1.php
Page2.php

Hence to prevent user from visiting Page1.php using Back Button you will need to place the above script in the head section of Page1.php.

Reference code not working in Chrome.

Works for me in Chrome and IE. Thanks!

How to disable back button in browser using javascript - Stack Overflo...

javascript
Rectangle 27 2

browser's back/forward button solution I encountered the same problem and I solved it using the popstate event from the $window object and ui-router's $state object. A popstate event is dispatched to the window every time the active history entry changes. The $stateChangeSuccess and $locationChangeSuccess events are not triggered on browser's button click even though the address bar indicates the new location. So, assuming you've navigated from states main to folder to main again, when you hit back on the browser, you should be back to the folder route. The path is updated but the view is not and still displays whatever you have on main. try this:

angular
.module 'app', ['ui.router']
.run($state, $window) {

     $window.onpopstate = function(event) {

        var stateName = $state.current.name,
            pathname = $window.location.pathname.split('/')[1],
            routeParams = {};  // i.e.- $state.params

        console.log($state.current.name, pathname); // 'main', 'folder'

        if ($state.current.name.indexOf(pathname) === -1) {
            // Optionally set option.notify to false if you don't want 
            // to retrigger another $stateChangeStart event
            $state.go(
              $state.current.name, 
              routeParams,
              {reload:true, notify: false}
            );
        }
    };
}

note: check browser compatibility for window.onpopstate() to be sure

javascript - How do I get the Back Button to work with an AngularJS ui...

javascript coffeescript angular-ui-router
Rectangle 27 2

browser's back/forward button solution I encountered the same problem and I solved it using the popstate event from the $window object and ui-router's $state object. A popstate event is dispatched to the window every time the active history entry changes. The $stateChangeSuccess and $locationChangeSuccess events are not triggered on browser's button click even though the address bar indicates the new location. So, assuming you've navigated from states main to folder to main again, when you hit back on the browser, you should be back to the folder route. The path is updated but the view is not and still displays whatever you have on main. try this:

angular
.module 'app', ['ui.router']
.run($state, $window) {

     $window.onpopstate = function(event) {

        var stateName = $state.current.name,
            pathname = $window.location.pathname.split('/')[1],
            routeParams = {};  // i.e.- $state.params

        console.log($state.current.name, pathname); // 'main', 'folder'

        if ($state.current.name.indexOf(pathname) === -1) {
            // Optionally set option.notify to false if you don't want 
            // to retrigger another $stateChangeStart event
            $state.go(
              $state.current.name, 
              routeParams,
              {reload:true, notify: false}
            );
        }
    };
}

note: check browser compatibility for window.onpopstate() to be sure

javascript - How do I get the Back Button to work with an AngularJS ui...

javascript coffeescript angular-ui-router
Rectangle 27 106

There are numerous reasons why disabling the back button will not really work. Your best bet is to warn the user:

window.onbeforeunload = function() { return "Your work will be lost."; };

This page does list a number of ways you could try to disable the back button, but none are guaranteed:

hey thanks your link works best for me full credit to you as both the functions work like it stops going back and my timer is also working well.many thanks to you for helping me as i am new php developer.thanks once again and also thanks to stackoveflow....

@user1656134 If this answer has helped you, select this as the correct answer. And, welcome to SO.

You should check in your PHP code if the answer has been submitted already and if so reject it.

It's worth mentioning that things have now changed in modern browsers: see stackoverflow.com/questions/19926641/

how to stop browser back button using javascript - Stack Overflow

javascript browser
Rectangle 27 105

There are numerous reasons why disabling the back button will not really work. Your best bet is to warn the user:

window.onbeforeunload = function() { return "Your work will be lost."; };

This page does list a number of ways you could try to disable the back button, but none are guaranteed:

hey thanks your link works best for me full credit to you as both the functions work like it stops going back and my timer is also working well.many thanks to you for helping me as i am new php developer.thanks once again and also thanks to stackoveflow....

@user1656134 If this answer has helped you, select this as the correct answer. And, welcome to SO.

You should check in your PHP code if the answer has been submitted already and if so reject it.

It's worth mentioning that things have now changed in modern browsers: see stackoverflow.com/questions/19926641/

how to stop browser back button using javascript - Stack Overflow

javascript browser
Rectangle 27 35

The 'popstate' event only works when you push something before. So you have to do something like this:

jQuery(document).ready(function($) {

  if (window.history && window.history.pushState) {

    window.history.pushState('forward', null, './#forward');

    $(window).on('popstate', function() {
      alert('Back button was pressed.');
    });

  }
});

this does not distinguish between back or forward button, just popstate, wich can be both

Your code runs perfectly in desktop browser.But in mobile browser its not working properly

But alert fire on backword and forward both, how can i detect only back click

JavaScript or jQuery browser back button click detector - Stack Overfl...

javascript jquery back-button
Rectangle 27 53

<script>
window.location.hash="no-back-button";
window.location.hash="Again-No-back-button";//again because google chrome don't insert first hash into history
window.onhashchange=function(){window.location.hash="no-back-button";}
</script>

Genius! I used this to prevent accidental trigger of Back button when user hits Backspace (on disabled/readonly fields, for example) in a web app where back/forward didn't really make sense anyway. Confirmed disables back and forward functionality (tho not the buttons themselves), including context menu option; verified in IE8 thru IE11, Chrome & FF.

This works, but resets all data entered in textboxes. Is it possible to prevent clearing?

It worked for me on firefox, but not on chrome (version 36.0.1985.143)

how to stop browser back button using javascript - Stack Overflow

javascript browser
Rectangle 27 53

<script>
window.location.hash="no-back-button";
window.location.hash="Again-No-back-button";//again because google chrome don't insert first hash into history
window.onhashchange=function(){window.location.hash="no-back-button";}
</script>

Genius! I used this to prevent accidental trigger of Back button when user hits Backspace (on disabled/readonly fields, for example) in a web app where back/forward didn't really make sense anyway. Confirmed disables back and forward functionality (tho not the buttons themselves), including context menu option; verified in IE8 thru IE11, Chrome & FF.

This works, but resets all data entered in textboxes. Is it possible to prevent clearing?

It worked for me on firefox, but not on chrome (version 36.0.1985.143)

how to stop browser back button using javascript - Stack Overflow

javascript browser
Rectangle 27 5

So I had this same problem and using $parent with ng-model didn't appear to be working. My problem was that I had groups of checkboxes but used the same name attribute for each of them. It ended up hiding the default checked radio button in the last group.

Make sure you are using distinct name attributes for each distinct group.

javascript - ng-model not working for radio button in AngularJS - Stac...

javascript angularjs angularjs-scope