How to access the previous route from Durandal router - durandal-2.0

Is there a way to access the previous route/instruction from the Durandal.js router? I know I can do router.navigateBack() to actually navigate back, but I want to know the route that I will navigating back to before I trigger the navigation.

Not directly I'm afraid.
router.navigateBack() is defined in router.js as
router.navigateBack = function() {
history.navigateBack();
};
And history.navigateBack() is defined in history.js as
history.navigateBack = function() {
history.history.back();
};
and history.history is an alias defined above for window.history which is part of the browser and would cause security issues if exposed.
If you want to have that functionality you'll have to implement it yourself. Possibly by intercepting router.navigate() and router.navigateBack().

Related

How to navigate using nativescript-urlhandler

I have a javascript Nativescript app (i.e., no Angular, Vue, or typescript), What I want to be able to do is receive a text with a deep-link into my app, receive the link, and then navigate to a specific page.
I've followed the nativescript-urlhandler docs and, on iOS, can receive the url, but I don't know what to do with it once I have it. That is, in my app.js file, I have:
handleOpenURL(function(appURL) {
console.log('Got the following appURL', appURL);
});
What I want to do from here would ordinarily be a
frame.topmost().navigate(navigationOptions);
call, but how can I get the app's viewModel for the resulting page, since that's loaded by main-page.js (using the standard template). That is, such navigation requests are otherwise always made from within the app where the viewModel is already set, but it's not yet set in app.js.
I've been looking for code samples but haven't found anything with straight NativeScript, so I'm posing the question to the StackOverflow-verse. Any help or insight welcome!
I was able to get this working. Yes, the
frame.topmost().navigate(navigationOptions);
works. What I did was create my own instance of the viewModel and set that as the binding context, such as ,
handleOpenURL(function (appUrl) {
var viewModel = createViewModel(); // create own instance of viewModel
viewModel.helpReq = parseUrl(appUrl.toString()); // add data from URL to viewModel
var navigationOptions = {
moduleName: './views/help-req-page',
context: { bindingContext: viewModel }
}
frame.topmost().navigate(navigationOptions);
}
Where parseUrl(), predictably, parses the url and creates an object from the various components.
If I have an empty action bar on the target page, then I automatically get a link back to my app that closes the target page cleanly.
I have this working on iOS; I have not tried Android yet.

Single page application with Rails 4 and AngularJS

Ok, this idea might seem quite a bit crazy and it kindo' is (at least for me at my level).
I have a fairly standarad rails app (some content pages, a blog, a news block, some authentication). And I want to make it into a single page app.
What I want to accomplish is:
All the pages are fetched through AJAX like when using turbolinks, except that the AJAX returns only the view part (the yield part in the layout) withought the layout itself, which stays the same (less data in the responces, quicker render and load time).
The pages are mostly just static html with AngularJS markup so not much to process.
All the actual data is loaded separately through JSON and populated in the view.
Also the url and the page title get changed accordingly.
I've been thinking about this concept for quite a while and I just can't seem to come up with a solution. At this point I've got to some ideas on how this actualy might be done along with some problems I can't pass. Any ideas or solutions are greatly appreciated. Or might be I've just gone crazy and 3 small requests to load a page are worse then I big that needs all the rendering done on server side.
So, here's my idea and known problems.
When user first visits the app, the view template with angular markup is rendered regularly and the second request comes from the Angular Resource.
Then on ngClick on any link that adress is sent to ngInclude of the content wrapper.
How do I bind that onClick on any link and how can I exclude certain links from that bind (e.g. links to external authentication services)?
How do I tell the server not to render the layout if the request is comming from Angular? I though about adding a parameter to the request, but there might be a better idea.
When ngInclude gets the requested template, it fires the ngInit functions of the controllers (usually a single one) in that template and gets the data from the server as JSON (along with the proper page title).
Angular populates the template with the received data, sets the browser url to the url of the link and sets the page title to what it just got.
How do I change the page title and the page url? The title can be changed using jQuery, but is there a way through Angular itself?
Again, I keep thinking about some kind of animation to make this change more fancy.
Profit!
So. What do you guys think?
OK, in case enyone ever finds this idea worth thinking about.
The key can be solved as follows.
Server-side decision of whether to render the view or not.
Use a param in the ngInclude and set the layout: false in the controller if that param is present.
Have not found an easier way.
Client-side binding all links except those that have a particular class no-ajax
Here's a directive that does it.
App.directive('allClicks', function($parse) {
return {
restrict: 'A',
transclude: true,
replace: true,
link: function(scope, element, attrs) {
var $a = element.find('a').not($('a.no-ajax')),
fn = $parse(attrs['allLinks']);
$a.on('click', function(event) {
event.preventDefault();
scope.$apply(function() {
var $this = angular.element(event.target);
fn(scope, {
$event: event,
$href: $this.attr('href'),
$link: $this
});
});
});
}
};
})
And then use it on some wrapper div or body tag like <body ng-controller="WrapperCtrl" all-links="ajaxLink($href)"> and then in your content div do <div id="content" ng-include="current_page_template">
In your angular controller set the current_page template to the document.URL and implement that ajaxLink function.
$scope.ajaxLink = function(path) {
$scope.current_page_template = path+"?nolayout=true";
}
And then when you get your JSON with your data from the server don't forget to use history.pushState to set the url line and document.title = to setr the title.

What is the right away to update a panel using AJAX?

In MVC4 applications, I would like to update a panel using AJAX but using jQuery methods instead using AjaxExtensions from MVC.
But my problem is the updatePanelId.
I've seen several people use this to update it when has success:
success: function (response) {
var $target = $("#target");
var $newHtml = response;
$target.replaceWith($newHtml);
}
But when I do this, it forces me to use in every partial view that includes the id="target" at the root level of my razor view, and I guess that's not a good practice; I said this because I've realized when I use AjaxExtensions it doesn't happens, replace the update and it does not remove the panelId. But using jQuery it does.
Any idea to port the AjaxExtensions feature to jQuery?
You can use just:
$("#target").html(response); // it will just update content of the $("#target") container
Use jQuery's .load function. This will load the contents of the URL you specify into the target element. You can optionally specify a selector after the URL in load to only grab part of the target page.
$(function() {
$("#target").load("/MyURL");
});
JavaScript same origin policy applies to this.

Use Ajax in Prototype.js to load PART of an external page into a div

I'm looking for a way to load a part of an external page (possibly selected by an id in the external page) into a div. Something similar to Ajax.Updater, but with the option of specifying an id to look for in the external page.
Does anything like this exist in prototype. I've been googling for examples without luck. If I can't find it soon I'll have to do some "gymnastics" with Ajax.Request and some function tied to onSuccess.
You could do something like this, though it is by no means an elegant solution.
new Ajax.Updater("container", 'www.babes.com', {
onSuccess: function() {
$("container").update( $('idOfSomeLoadedElement') );
}
});
I don't think there is an actual elegant way of doing this purely in js. Ideally, you'd make your AJAX request only for what you need. You might be able to do some server-side stuff to lop out what you don't need (basically, offload the onsuccess functionality above to the server).
Instead of AJAX you might get by with an iframe.
// dollar function calls Element.extend
var iframe = $(document.createElement('iframe'));
// control how and what it loads
iframe.addEventListener('onLoad', function() {
$('container').update(iframe.contentDocument.select('#someID').first());
});
iframe.setAttribute('src', 'http://URL');
// add it as invisible, content isn't loaded until then
iframe.setAttribute('hidden', true);
document.body.appendChild(iframe);
From a minimal test it's clear that you'll have to be as concious about cross-origin policies as any AJAX method, that is, it's a PITA.

How to "bookmark" page or content fetched using AJAX?

How to "bookmark" page or content fetched using AJAX?
It looks like it can be easy if we just add the details to the "anchor", and then, use the routing or even in PHP code or Ruby on Rails's route.rb, to catch that part, and then show the content or page accordingly? (show the whole page or partial content)
Then it can be very simple? It looks like that's how facebook does it. What are other good ways to do it?
Update: There is now the HTML5 History API (pushState, popState) which deprecates the HTML4 hashchange functionality. History.js provides cross-browser compatibility and an optional hashchange fallback for HTML4 browsers.
To store the history of a page, the most popular and full featured/supported way is using hashchanges. This means that say you go from yoursite/page.html#page1 to yoursite/page.html#page2 you can track that change, and because we are using hashes it can be picked up by bookmarks and back and forward buttons.
You can find a great way to bind to hash changes using the jQuery History project
http://www.balupton.com/projects/jquery-history
There is also a full featured AJAX extension for it, allowing you to easily integrate Ajax requests to your states/hashes to transform your website into a full featured Web 2.0 Application:
http://www.balupton.com/projects/jquery-ajaxy
They both provide great documentation on their demo pages to explain what is happening and what is going on.
Here is an example of using jQuery History (as taken from the demo site):
// Bind a handler for ALL hash/state changes
$.History.bind(function(state){
// Update the current element to indicate which state we are now on
$current.text('Our current state is: ['+state+']');
// Update the page"s title with our current state on the end
document.title = document_title + ' | ' + state;
});
// Bind a handler for state: apricots
$.History.bind('/apricots',function(state){
// Update Menu
updateMenu(state);
// Show apricots tab, hide the other tabs
$tabs.hide();
$apricots.stop(true,true).fadeIn(200);
});
And an example of jQuery Ajaxy (as taken from the demo site):
'page': {
selector: '.ajaxy-page',
matches: /^\/pages\/?/,
request: function(){
// Log what is happening
window.console.debug('$.Ajaxy.configure.Controllers.page.request', [this,arguments]);
// Adjust Menu
$menu.children('.active').removeClass('active');
// Hide Content
$content.stop(true,true).fadeOut(400);
// Return true
return true;
},
response: function(){
// Prepare
var Ajaxy = $.Ajaxy; var data = this.State.Response.data; var state = this.state;
// Log what is happening
window.console.debug('$.Ajaxy.configure.Controllers.page.response', [this,arguments], data, state);
// Adjust Menu
$menu.children(':has(a[href*="'+state+'"])').addClass('active').siblings('.active').removeClass('active');
// Show Content
var Action = this;
$content.html(data.content).fadeIn(400,function(){
Action.documentReady($content);
});
// Return true
return true;
And if you ever want to get the querystring params (so yoursite/page.html#page1?a.b=1&a.c=2) you can just use:
$.History.bind(function(state){
var params = state.queryStringToJSON(); // would give you back {a:{b:1,c:2}}
}
So check out those demo links to see them in action, and for all installation and usage details.
If you use jquery, you can do that in a simple manner. just use ajaxify plugin. it can manage bookmarking of ajax pages and many other things.
Check this, something may help you:
How to change URL from javascript: http://doet.habrahabr.ru/blog/15736/
How to pack the app state into url: http://habrahabr.ru/blogs/javascript/92505/
An approach description: http://habrahabr.ru/blogs/webstandards/92300/
Note: all articles are in Russian, so either Google Translate them, or just review the code and guess the details.
Take a look to the Single Page Interface Manifesto
I tried many packages. The jQuery History plugin seems to be most complete:
http://github.com/tkyk/jquery-history-plugin

Resources