I'm new to Blackberry 10 dev. So I'm wondering what's the best way to do this as I'm not getting any clear answers from the dev docs.
What I want is to start a separate view in my app from a navigation screen. The new page will then create a http request and update the UI based on the output.
The best way seems to be using the NavigationPane and add a qml view. However how do I invoke a C++ function when it's pushed onto the stack? Something similar to android onActivityCreated() in Fragments. There is the Http example docs, but the program started the http request from the constructor of the inherited QObject.
How to I have a function executed as the new qml is added to the navigation stack as
// navigationpane.qml
NavigationPane {
id: navigationPane
Page {
Container {
Label {
text: "First page"
}
}
actions: [
ActionItem {
title: "Next page"
ActionBar.placement: ActionBarPlacement.OnBar
onTriggered: {
var page = pageDefinition.createObject();
navigationPane.push(page);
}
attachedObjects: ComponentDefinition {
id: pageDefinition;
source: "secondpage.qml"
}
}
]
}
onPopTransitionEnded: { page.destroy(); }
}
I think the onCreationCompleted function may be what you're looking for.
In the Page object of your secondpage.qml file, add this:
Page {
id: secondpage
onCreationCompleted: {
// use Javascript to call the exposed C++ function
}
}
If you want something more in the spirit of "onActivityCreated()", you can use the signal transitionEnded:
NavigationPane {
onPushTransitionEnded{
top.callYourPageFunction();
}
}
Related
I'm new to Blackberry Cascades and I want to create a simple NavigationPane. I'm very used to Qt's StackView which allouse you to push and pop pages to and from the stack. However, Qt's [StackView][1] has this attached property called Stack.view which allows you to access the stack from any child page.
How can I do this in Blackberry's Cascades? Is it possible to access the NavigationPane stack of pages from the current page you're in? I see this extremely useful.
For example I have this simple project with two qml files each representing one page:
Main page:
// main.qml
import bb.cascades 1.4
NavigationPane {
id: nav
Page {
Container {
ListView {
dataModel: XmlDataModel {
source: "data.xml"
}
onTriggered: {
if (indexPath.length > 1) {
var chosenItem = dataModel.data(indexPath);
var contentpage = itemPageDefinition.createObject();
contentpage.itemPageTitle = chosenItem.name
nav.push(contentpage);
}
}
accessibility.name: "Listing"
}
}
}
attachedObjects: [
ComponentDefinition {
id: itemPageDefinition
source: "ItemPage.qml"
}
]
onPopTransitionEnded: {
page.destroy();
}
}
Secondary page:
// ItemPage.qml
import bb.cascades 1.4
Page {
property alias itemPageTitle: titlebar.title
titleBar: TitleBar {
id: titlebar
}
content: Container {
}
}
Is it possible to access nav or NavigationPane from ItemPage.qml? I would like e.g. to create a new page from ItemPage.qml and push it on the stack. Is it possible to do so?
EDIT:
For example there is this documentation page on the Blackberry developers website which has this example with a main page:
and a secondary page:
As you can see, in the secondary myPage.qml he uses the navigationPane. How is that possible? How does he have access to an ID present in another component?
In my application I have a main.qml which has a navigation pane that goes to homepage.qml and from there to profilepage.qml. When I come back from profilepage to homepage I need to trigger a function in home page. I noticed that whenever I pop back I get a call onPopTransitionEnded in the main page. Since homepage is pushed from main.qml there is no navigation pane on homepage and I cant access onPopTransitionEnded on homepage. Below are the sample structures of my 3 qml views.
main.qml
NavigationPane {
id: nav
peekEnabled: false
onPopTransitionEnded: {
console.log("POP PAGE from main");
if(page.objectName=="newProfilePage")
{
//I tried to access the function using the homepage id but didnt work
menuScreenPage.reloadView(); // This doesnt work, shows error unknown symbol menuScreenPage
}
page.destroy();
}
Page {
id: mainPage
Container {
//some code
}
onCreationCompleted: {
//Some code and then push to homepage
nav.push(homePageDefenition.createObject());
}
}
}
homepage.qml
Page {
id: menuScreenPage
objectName: "menuScreenPage"
function reloadView() //This is the function that is needed to be called on page pop from profile page
{
//some code
}
Container {
//some code
Button { //a button to push to profile page
id:pushButton
horizontalAlignment: HorizontalAlignment.Right
verticalAlignment: VerticalAlignment.Bottom
onClicked: {
console.log("I was clicked!")
nav.push(profilePageDefinition.createObject());
}
}
}
}
profilepage.qml
Page {
id: newProfilePage
objectName: "newProfilePage"
Container {
//some code
Button { //a button to pop to home page
id:popButton
horizontalAlignment: HorizontalAlignment.Right
verticalAlignment: VerticalAlignment.Bottom
onClicked: {
console.log("I was clicked!")
nav.pop();
}
}
}
}
So is there a way that I can access the function of homepage.qml from main.qml? Or is there any other function like onPopTransitionEnded which I can access on homepage.qml itself when I pop from profilepage? Please advice.
Seems that you created unnamed object with this line:
homePageDefenition.createObject()
If you want to access it later, you should save it in some property, for ex.
property var myHomePage: null
...
myHomePage = homePageDefenition.createObject()
nav.push(myHomePage )
...
myHomePage.reloadView();
Keep in mind that "menuScreenPage" is local name (id), it works only inside homepage.qml and nobody can access it beyond that file.
UPD
You can even use such code:
page.reloadView(); // Use local variable "page" instead of internal id "menuScreenPage"
I am trying to create a bootstrapped firefox extension to obtain current tabs url and title. The issue is that I want to check when the tab url has the word "about:" in its url. The solution that I propose is to check the require("sdk/tabs").activeTab.url" using the browsers native string.substr() javascript function. Is any posibility to use browsers native javasript functions on widget or ToolbarButton onClick method?
exports.main = function(options) {
var base64 = require("sdk/base64");
var panel = require("sdk/panel").Panel({
width: 700,
height: 470,
onHide: function ()
{
panel.contentURL = "about:blank";
}
});
var tbb = require("toolbarbutton").ToolbarButton({
id: "extension-tbb-id",
label: "IFShare+",
image: "https://www.fasdfasd.es/factory/templates/templateforidkreader/favicon.ico",
panel: panel,
onClick: function()
{
windowPanel = require("sdk/tabs").activeTab;
title = windowPanel.title;
url = windowPanel.url;
// Is any posibility to do something like that ????
contentScript: "if("+url+".substring(0,5)=='about:'){"
{
url='';
title='';
}
contentScript: "}"
this.panel.contentURL = "https://www.fasdfasdf.es/factory/index2.php?option=com_idkreader&view=shareplus&task=window&Itemid=0&url="+base64.encode(url, "utf-8")+'&title='+base64.encode(title, "utf-8")+'&ref=ext';
},
});
// move the toolbar button to the navigation bar
if ("install" == options.loadReason) {
tbb.moveTo({toolbarID: "nav-bar"});
}
}
I'm not entirely clear on the details of what you're trying to accomplish, but I think you're close.
To answer the question as asked, no you can't access variables from within a content script. The best you can do is use content script messaging a mentioned in the page-mod documentation.
However, to accomplish what you want, you don't need to do this. You can just do what you want in the onClick function itself, like so
function onClick()
{
windowPanel = require("sdk/tabs").activeTab;
title = windowPanel.title;
url = windowPanel.url;
if(url.substring(0,5)=='about:'){
{
url='';
title='';
} else {
//You can insert any content script stuff you want here
}
this.panel.contentURL = "https://www.fasdfasdf.es/factory/index2.php?option=com_idkreader&view=shareplus&task=window&Itemid=0&url="+base64.encode(url, "utf-8")+'&title='+base64.encode(title, "utf-8")+'&ref=ext';
}
If you refine your question a bit, I will be happy to refine my answer.
I have been using editor.plugins.contextmenu.onContextMenu.add to customize the contextmenu plugin in TinyMCE 3.x but cannot use it in version 4.0
Here is the error I receive:
TypeError: a.plugins.contextmenu.onContextMenu is undefined
and my code for plugin is:
tinymce.PluginManager.add("example", function(a,b) {
a.plugins.contextmenu.onContextMenu.add(function(th, menu, event) {
//my code for customizing contextmenu
})
a.addButton("exampleHelp", {
text : "help",
icon : !1,
onclick : function() {
//some code
}
})
});
Does it relate to init function which I had been using in version 3.X?
I was able to reverse engineer a solution by looking at the table plugin code.
tinymce.init({
plugins: "contextmenu",
contextmenu: "link image inserttable | cell row column deletetable | myMenuItem"
});
// Inside plugin
editor.addMenuItem('myMenuItem', {
text: 'My Menu Item',
context: 'div', // not sure what this does
onPostRender: postRender,
onclick: function() { console.log('hi!'); }
});
// Determine whether menu item is visible
function postRender() {
handleDisabledState(this, 'div.myCustomItem');
}
function handleDisabledState(ctrl, selector) {
function bindStateListener() {
ctrl.visible(editor.dom.getParent(editor.selection.getStart(), selector));
editor.selection.selectorChanged(selector, function(state) {
ctrl.visible(state);
});
}
if (editor.initialized)
bindStateListener();
else
editor.on('init', bindStateListener);
}
So the context menu should only render if it's inside a div.myCustomItem element. If you want the context menu item to always be visible, comment out handleDisabledState()
For now I found a temporary solution:
a.on("contextmenu",function(n){
// console.log($(a.getDoc()).find(' .mce-floatpanel.mce-menu'));
// find a way to add it into current context menu instead of deleting it
$(a.getDoc()).find(' .mce-floatpanel.mce-menu').remove();
var i;
var o=[]
o.push({text:'option1'})
o.push({text:'option2'})
o.push({text:'menu option', menu:o})
t=new tinymce.ui.Menu({items:o,context:"contextmenu"}),t.renderTo(document.body)
// fix positioning
var r={x:n.pageX,y:n.pageY};
a.inline||(r=tinymce.DOM.getPos(a.getContentAreaContainer()),
r.x+=n.clientX,r.y+=n.clientY),t.moveTo( r.x,r.y),
a.on("remove",function() {t.remove(),t=null})
})
I remove the default context menu and replace it with my customized menu. But I still need to know how I can add my items to default context menu
I found a solution on how to customise TinyMCE's (4.1.9) contect menu on the fly, see my response and proposed solution on this page: http://archive.tinymce.com/forum/viewtopic.php?pid=116109#p116109
Thanks,
Nic
I'm looking for a way to block/disable right click in javafx.scene.web.WebView. To be more specific I don't want the context menu to show up on right click. I'm new to the technology and can't find the way to do it.
Just for the record, it is implemented in JavaFX 2.2. See documentation for setContextMenuEnabled (JavaFX 2) and setContextMenuEnabled (JavaFX 8)
I've came up with working, but ugly, inelegant and, I'd say, partisan solution, which I don't really like, but actually I have no (or just can't find) other way out.
It includes modifying EventDispatcher of WebView.
So my implementation of EventDispatcher needs a reference to original WebView EventDispatcher and looks like that:
public class MyEventDispatcher implements EventDispatcher {
private EventDispatcher originalDispatcher;
public MyEventDispatcher(EventDispatcher originalDispatcher) {
this.originalDispatcher = originalDispatcher;
}
#Override
public Event dispatchEvent(Event event, EventDispatchChain tail) {
if (event instanceof MouseEvent) {
MouseEvent mouseEvent = (MouseEvent) event;
if (MouseButton.SECONDARY == mouseEvent.getButton()) {
mouseEvent.consume();
}
}
return originalDispatcher.dispatchEvent(event, tail);
}
}
Everytime event is dispatched it goes through our dispatcher and I check if it's right click. If it is I just consume it and proceed further.
To make it work you have to use WebView like that:
WebView webView = new WebView();
EventDispatcher originalDispatcher = webView.getEventDispatcher();
webView.setEventDispatcher(new MyEventDispatcher(originalDispatcher));
Every comment, clue and so on are appreciated.
With JavaFX 2.2+ it's now possible to set WebView's ContextMenuEnabled to false:
webView.setContextMenuEnabled(false);
WebView API Doc.
You can style context menus away using the following css.
.context-menu { -fx-background-color: transparent; }
.menu-item { -fx-background-color: transparent; }
.menu-item .label { -fx-text-fill: transparent; }
.menu-item:show-mnemonics .mnemonic-underline { -fx-stroke: -transparent; }
This will make all context menus and menu items transparent. I'm not sure of the css selector you could use to make this only apply to WebView context menus. If you don't have other menus in your application, that may not be a big deal.
You can do it with js (jquery used)
$(document).ready( function() { document.oncontextmenu = function() { return false } } );
Unfortunately it's not yet possible. There is a feature request for that, which you may want to track: http://javafx-jira.kenai.com/browse/RT-15684
This will will remove the context menu for the entire stage:
primaryStage.getScene().addEventFilter(MouseEvent.MOUSE_RELEASED,
new EventHandler<MouseEvent>() {
public void handle(MouseEvent event) {
if (event.getButton() == MouseButton.SECONDARY) {
event.consume();
}
}
});