Adding URL adresses to views in SAPUI5 - shell

I have SAPUI5 application where I am using Shell. I have different views in my Shell and I am able to navigate from one view to another. The problem is that I don't know how can I create or change URL adress to each view. I need to set URL adresses to be able to use "back" button in a browser. I want to add unique URL adress to each view inside my Shell to use "back" and "forward" buttons.
Thanks!

Take a look at this simple sap.ui.core.routing.Router example it shows how to easily set up and use routes and a hash changer with an app Shell container.
sap.ui.core.routing is a javascript routes utilty, it handles URL changes and dispatches control based on pattern logic to views and event handlers, part of routing is HashChanger and History functionality.
if you are using the desktop shell this routing example with sap.ui.ux3.Shell
A lot of examples use jQuery.sap.history.js IMO it doesn't properly support bookmarks and has limited features which means you have to use it with other techniques

Unfortunately, History API presents in modern browsers only. For IE6+ I recommend you to use "hashchange" event of window:
function router(){
var sViewName = window.location.hash.slice(1),
oView = sap.ui.getCore().byId(sViewName) || new sap.ui.view.XMLView({id : sViewName, viewName : sViewName});
sap.ui.getCore().byId("uxShell").setContent(oView);
return false;
}
if("onhashchange" in window){
if(window.attachEvent){ //IE8
attachEvent('onhashchange', router);
} else if(window.addEventListener){ //IE9+, Chrome, Opera, Firefox
addEventListener('hashchange', router);
}
} else { //IE6-7
var oldHref = window.location.hash;
setInterval(function(){
var newHref = window.location.hash;
if(oldHref !== newHref){
oldHref = newHref;
router();
}
}, 100);
}
But to make it work you need to set href property to navigation items like this: #catalog.viewName

Related

Firefox Extension - New Tab - How To Override Preferences?

I am new to Firefox extension, that is why I use the Add On SDK.
I want to create an extension that shows a specific site every time the user opens up a new tab. This is my code so far:
var self = require("sdk/self");
var tabs = require("sdk/tabs");
// Listen for tab openings.
tabs.on('open', function onOpen(tab) {
getActiveTab();
});
function getActiveTab(){
tabs.on('activate', function (tab) {
tab.url = "http://www.example.com";
});
}
This works. But before it loads the specified domain it loads the Firefox default newtab page. Now is there an API reference to access the newtab setting and change to example.com?
Thanks,
Gerd
It was possible to change about:newtab URL using SDK:
require('sdk/preferences/service').set('browser.newtab.url', 'http://www.stackoverflow.com');
but it becomes obsolete with FF41, as there isn't a browser.newtab.url preference any more.
If you still plan on using it, you might also consider adding this to your code:
var { when: unload } = require('sdk/system/unload');
var reason;
unload( function ( reason ) {
require('sdk/preferences/service').set('browser.newtab.url', 'about:newtab');
});
so that the preference change gets undone after add-on unload. You can also pass one of unload reasons to the function: 'uninstall', 'disable', 'shutdown', 'upgrade', or 'downgrade', or not provide reason argument at all / leave it undefined.
Since the browser.newtab.url preference has been removed, this is the new way to do this: https://github.com/sblask/firefox-open-tabs-next-to-current/blob/master/lib/helpers.js#L50 The code of the module can be found here: https://dxr.mozilla.org/mozilla-central/source/browser/modules/NewTabURL.jsm
If you also want to replace the homepage, you have to change the browser.startup.homepage preference.

Manually load kendo mobile view

I'm working on a Kendo Mobile project with a number of:
Kendo Views (external to root html)
Modal Views (in the root html).
The external files load on demand and everything works fine. But i'd like to have the same load on demand behavior for some of the modal views, because the root/based html file is becoming too large and not manageable.
Is there a way to either:
Store a modal view in an external file? If so is it possible to load via javascript syntax (app.navigate()) rather than the declarative syntax (href='externalmodal').
Manually pre-load an external view without navigating to it first.
This code lets you manually create a view:
var viewUrl = 'blahblahblah';
var element = $.parseHTML('<div data-role=view>test</div>')[0];
element.style.display = 'none';
$(document.body).append(element);
var options = $.extend({}, kendo.parseOptions(element, kendo.mobile.ui.View.fn.options));
var view = new kendo.mobile.ui.View(element, options);
view.element[0].setAttribute('data-url', viewUrl);
kendo.mobile.application.navigate(viewUrl, '');
Depending on what features you use, you may need to instead use code similar that that used for ModalView below so that Kendo creates the subclass (changes: substitute View for ModalView, substitute view for modalview, add data-url, remove call to show(), maybe check that view not already created by checking for element with matching data-url). We haven't tested setting roles.view this way, but we did something similar while testing this stuff out and it worked.
Don't try settings the options - Kendo got confused (at least trying to set useNativeScrolling didn't work, also don't try setting the options object on the subclass unless you really know what you are doing).
Caveat: This was using browserHistory:false (which disables routing) when the kendo.mobile.Application was created. The technique should still work when using browser history if you use a valid url fragment (same as would be created by Kendo for the pushstate/hashchange url).
This is a also way to cleanly subclass kendo.mobile.ui.View that works well - although you must still use data-role=view even though your subclass is a "different" component. Note that you can't just use you cant use your own subclassed component with its own name like role=myview to subclass a view because there are hard-coded checks specifically for data-role=view in the kendo codebase. Same if you wish to subclass: layout modalview drawer splitview page (amongst other hard-coded kendo ui component names - search kendo code for kendo.roleSelector - ugly). e.g.
MyView = kendo.mobile.ui.View.extend({
init: function(element, options) {
kendo.mobile.ui.View.prototype.init.apply(this, arguments);
...
var myView = new MyView('<div data-role=view>test</div>');
Why it works: The relevant function in the Kendo source code is _findViewElement which does element = this.container.children("[" + attr("url") + "='" + urlPath + "']"); to see if the view already exists for a url, before creating a new one. A unique init function is always required as it ends up being the constructor function.
If you want to subclass a modalview, you need to do something different due to the way kendo works:
var MyModalView = kendo.mobile.ui.ModalView.extend({
html: '<div data-role=modalview style="width:90%;display:none;">Foobar</div>',
init: function() {
kendo.mobile.ui.ModalView.prototype.init.apply(this, arguments);
}
});
function makeModalView() {
$(document.body).append($.parseHTML(MyModalView.prototype.html));
var roles = $.extend({}, kendo.mobile.ui.roles);
roles.modalview = MyModalView;
var modalView = kendo.initWidget($(element), {}, roles);
modalView.open();
return modalView;
}

How can I dynamically change kendo.mobile.Application's loading property?

I am developing a mobile web app using Kendo UI Mobile. Whenever we make any AJAX calls, or our DataSources make them we call app.startLoading() to show the loading icon to the user. This works very well.
However, depending on the context in which the call is made we would like to change the text that is displayed along with the loading icon. I know you can define this when I create the kendo.mobile.Application instance. How can I change it afterwards?
The documentation does not suggest a way to do this, and a browse of the source code did not help me either. Is this really not possible?
EDIT: This is using Kendo UI Mobile v.2012.3.1114
I usually make a "utility" function to do this:
var _kendoApp = new kendo.mobile.Application(document.body, {});
var showLoading = function (message) {
_kendoApp.loading = "<h1>" + (message ? message : "Loading...") + "</h1>";
_kendoApp.showLoading();
};
I am also setting a default message of "Loading..." if one isn't passed in.
Edit:
I could have sworn that worked for me in a past app I did, but judging by thr source, I think you are right, my answer above shouldn't work. My best suggestion is to add a class to the message element so you can target it, and use jQuery to change the text.
var _kendoApp;
var showLoading = function (message) {
$(".loading-message").text(message ? message : "Loading...");
_kendoApp.showLoading();
};
_kendoApp = new kendo.mobile.Application(document.body, {
loading: '<h1 class="loading-message">Loading...</h1>'
});

firefox addon page-mod - when url doesn't match

I want to be able to activate a widget if a url matches some pattern, but the problem is I also want to disable the widget when page-mod rule doesn't match the url.
So if I have few tabs open and if I switch between them I should be able to somehow disable the widget if an active tab's url doesn't match the rule, or in other case activate it. The state of widget(on/off) should be changed on loading pages and switching through tabs.
I've been struggling with this for a while and still haven't found a solution.
This is where I'm at right now:
// Activates on matching one of the site domains, but I also want to deactivate
// it when it does not match
var pageMod = require("page-mod");
pageMod.PageMod({
include: ["*.site1.com","*.site2.com"],
onAttach: function() {
alert("Widget activated!");
});
});
Thank you for any help!
If I understand correctly what you are trying to do then page-mod is the wrong solution - you simply want to listen to the active tab. Use tabs module for that, listen to ready (new URL loaded) and activate (active tab changed) events:
var tabs = require("tabs");
tabs.on("ready", function(tab)
{
if (tab == tabs.activeTab)
updateActiveTab(tab);
});
tabs.on("activate", function(tab)
{
updateActiveTab(tab);
});
Your updateActiveTab() function would need to check tab.url and activate or deactivate the widget then. If you want to use patterns for that like the ones you specify for page-mod then you need to use the internal match-pattern module, like this:
var {MatchPattern} = require("match-pattern");
var patterns = [
new MatchPattern("*.site1.com"),
new MatchPattern("*.site2.com")
];
function updateActiveTab(tab)
{
var matches = false;
for (var i = 0; i < patterns.length; i++)
if (patterns[i].test(tab.url))
matches = true;
if (matches)
activateWidget();
else
deactivateWidget();
}
But of course you can just use a regular expression or something like this to test tab.url, you don't have to use the match-pattern module.
Disclaimer: The code examples are only there to make the approach easier to understand, they haven't been tested.

Limit a firefox extension to a specific domain

I would like to write a firefox extension. This extension is not a generic extension but work specifically for a domain where I need to highlight specific html components.
How should I do that? I just want the js loaded when the user is browsing a specific domain.
My current overaly.js is basically empty (generated by the Extension Wizard):
var myextension = {
onLoad: function() {
// initialization code
this.initialized = true;
this.strings = document.getElementById("myextension-strings");
},
onMenuItemCommand: function(e) {
var promptService = Components.classes["#mozilla.org/embedcomp/prompt-service;1"]
.getService(Components.interfaces.nsIPromptService);
promptService.alert(window, this.strings.getString("helloMessageTitle"),
this.strings.getString("helloMessage"));
},
onToolbarButtonCommand: function(e) {
// just reuse the function above. you can change this, obviously!
myextension.onMenuItemCommand(e);
}
};
window.addEventListener("load", myextension.onLoad, false);
And my ff-overlay.xul is:
myextension.onFirefoxLoad = function(event) {
document.getElementById("contentAreaContextMenu")
.addEventListener("popupshowing", function (e){ myextension.showFirefoxContextMenu(e); }, false);
};
myextension.showFirefoxContextMenu = function(event) {
// show or hide the menuitem based on what the context menu is on
document.getElementById("context-myextension").hidden = gContextMenu.onImage;
};
window.addEventListener("load", myextension.onFirefoxLoad, false);
I was thinking to go neanderthal and do a check inside myextension.onFirefoxLoad to see if the currentpage is the one I want but that requires the user to click the proper item on the context menu.
I'm not totally following what you have because both of those look like JS files, not XUL files. But what you probably want to do is listen for the load event coming from the web pages that are loaded. Then, in your event loader, just look at each page that loads and see whether it's coming from the specific domain you want.
A great (though not always quite as easy as it sounds) way to find out how to do something in a Firefox addon is to find another addon that does something similar. DOM Inspector and Inspect Context are your friends! The first such addon that comes to mind in this case is WikiTrust so you could try looking at that one to see if it gives you any inspiration.

Resources