Viewport Apply Conditional Toolbar with Sencha Touch - model-view-controller

Im going to MVC route with Sencha. I have a Viewport panel initialized much like the twitter example:
/**
* #author Jeff Blake
*/
Ext.regApplication('App', {
defaultTarget: 'viewport',
defaultUrl : 'Viewport/index',
name : 'App',
icon : "mobile/public/resources/images/icon.png",
phoneStartupScreen : "mobile/public/resources/images/phone_startup.png",
//useHistory : false,
//useLoadMask : true,
launch: function() {
Ext.Viewport.init();
Ext.Viewport.onOrientationChange();
this.viewport = new App.Viewport({
application: this
});
Ext.dispatch({
controller: 'User',
action : 'index'
});
}
});
/**
* #class App.Viewport
* #extends Ext.Panel
* This is a default generated class which would usually be used to initialize your application's
* main viewport. By default this is simply a welcome screen that tells you that the app was
* generated correctly.
*/
App.Viewport = Ext.extend(Ext.Panel, {
id : 'viewport',
layout : 'card',
fullscreen: true,
cardSwitchAnimation: 'slide',
initComponent: function() {
Ext.apply(this, {
dockedItems: [
{
// Top Bar
dock : 'top',
xtype : 'toolbar',
title : 'Whats Good',
items: [
{
text: 'About'
},
]
}
]
});
App.Viewport.superclass.initComponent.apply(this, arguments);
}
});
Ext.reg('App.Viewport', App.Viewport);
New Code:
if (!App.viewport.getDockedComponent(homeBar)) {
var homeBar = new App.HomeBar();
App.viewport.addDocked(homeBar);
}
I want to be able to conditionally apply DockedItems (toolbars) based on which Type of panel is currently rendered in the Viewport. EG: one for Login, Home screen, detail screen, etc.
I've tried using Ext.apply(App.Viewport, { dockedItems: [App.LoginBar]});
But that doesn't work. Currently it works to add the toolbar to the currently rendered Panel and setting it to fullscreen, but unfortunately transitions and things behave weirdly as the structure is
Panel
Toolbar
Panel
Toolbar
/end Panel
/end Panel
Does anyone have a suggestion?

To programmatically add a docked item, I would recommend using
viewport.addDocked(loginBar);
Methods like this are far better than trying to update the original configuration of the component.
Then there is also a .removeDocked() method to take it off again.
Also make sure you are dealing with instances of the components, not trying to update their class.

To get the reference to your application's viewport, you can come in through the 'App' namespace, which is automatically created by the name property of the regApplication config.
So you could make your toolbar button do this for example:
{
text: 'About',
handler: function() {
App.viewport.getDockedItems()[0].setTitle('Pressed!');
}
},
Which would make the title change when you press the button.
But now I better understand what it is you are trying to do, I recommend you don't dock a single, dynamically-changed toolbar to the outer viewport, but add individual toolbars to each of the (card) panels in it. That way they get to slide nicely too ;-)

Related

How to force CKEditor to process widgets when setting the HTML of an element

I have create a simple CKEditor widget that highlights the elements that have the class "pink".
I have also added a "Pinkify" button to the toolbar, which replaces the HTML of the selected element with some other elements that have the class "pink".
What I observe when I click the button is that widgets are not created for the freshly inserted elements. However, when I toggle between Source mode and WYSISYG mode, the widgets get created.
See the jsfiddle and its code:
CKEDITOR.replace('ck', {
allowedContent: true,
extraPlugins: 'pink'
});
CKEDITOR.plugins.add('pink', {
requires: 'widget',
init: function(editor) {
editor.widgets.add('pinkwidget', {
upcast: function(element) {
return element.hasClass('pink');
}
});
editor.addCommand('pinkify', {
editorFocus: 1,
exec: function(editor) {
var selection = editor.getSelection(),
selectedElement = selection.getStartElement();
if (selectedElement) {
selectedElement.setHtml("Let's have some <span class=\"pink\">pink</span> widget here!");
editor.widgets.checkWidgets(); // needed?
}
}
});
editor.ui.addButton('pinkify', {
label: 'Pinkify',
command: 'pinkify'
});
},
onLoad: function() {
CKEDITOR.addCss('.cke_widget_pinkwidget { background: pink; }');
}
});
I am aware of this question on Stackoverflow, but I can't get it to work with setHtml called on an element. Can you suggest how to modify the code so that widgets get created as soon as the HTML is updated?
According to the CKEditor team, it is normal that CKEDITOR.dom.element.setHtml does not instanciate widgets (see Widgets not initialised after calling setHtml on an element).
So the workaround they gave me was to rewrite the code that insert HTML in place of the selected element to:
if (selectedElement) {
selectedElement.setHtml("");
editor.insertHtml("Let's have some <span class=\"pink\">pink</span> widget here!");
}
For those like me who didn't know, editor.insertHTML inserts HTML code into the currently selected position in the editor in WYSIWYG mode.
Updated jsFiddle here.

How to add Toolbar Button for Firefox Australis

I used below code to add toolbar buttons automatically in navigation toolbar below Firefox Australis.
var buttonId = "toolbarbutton-toolbarbutton";
var navBar = document.getElementById("nav-bar");
var currentSet = navBar.currentSet;
var curSet = currentSet.split(",");
if (curSet.indexOf(buttonId) == -1)
{
navBar.insertItem(buttonId);
navBar.setAttribute("currentset", navBar.currentSet);
document.persist("nav-bar", "currentset");
try
{
top.BrowserToolboxCustomizeDone(true);
}
catch (e)
{
}
}
Because user interface and modules changed for Australis, the code needs to be updated. How can I add Toolbar Button for Australis proper way?
You have to use the CustomizableUI module:
try
{
Components.utils.import("resource:///modules/CustomizableUI.jsm");
CustomizableUI.createWidget({
id: "toolbarbutton-toolbarbutton",
defaultArea: "nav-bar",
removable: true,
label: "My button",
tooltiptext: "My tooltip text",
onClick: function()
{
alert("Clicked");
}
});
}
catch (e)
{
Components.utils.reportError(e);
// No such module? Try the old approach.
...
}
Note that the widget no longer needs to be added for each browser window, it is enough to do it once. Unfortunately, the module documentation is practically non-existent right now, the code above has been deduced from module's source code. The documentation should improve soon however.
If it helps, Adblock Plus source code contains an emulation of the CustomizableUI API for older Firefox versions. This one is far from complete however, it is only meant to cover the needs of Adblock Plus.

Windows with Layouts livesearchgridpanel Ext.js4

I have some grids already designed, but I have to include them in a Windows Layout. The problem is: The grids are enabled for livesearchpanel. How can I mantain this type of grid inside a window layout? Here there is no way to define the grid by a constructor, they're just items of a bigger constructor:
Ext.create('widget.window', {
Where should I place the constructor:
Ext.create('Ext.ux.LiveSearchGridPanel', {
?
I'm confused, any hint?
Put it as an item in the window:
Ext.create('Ext.Window', {
// ... window configuration
,layout: 'fit' // if you don't want other items
,items: [
Ext.create('Ext.ux.LiveSearchGridPanel', {...});
]
});
Don't do that if you extend the window class, however, or you'll get bitten if you try to create multiple instances of this window (because they'd be sharing one single instance of your grid component). Create an instance of you component during window initialization instead:
Ext.define('My.GridWindow', {
extend: 'Ext.Window'
// ... window configuration
,layout: 'fit' // if you don't want other items
,initComponent: function() {
this.items = [
Ext.create('Ext.ux.LiveSearchGridPanel', {...})
];
this.callParent(arguments);
}
});

Cancel panel opening from toolbar widget onClick handler

I have a Firefox extension which adds a toolbar Widget with a panel which should display when the widget is clicked. Under certain circumstances, the panel should not show when the toolbar widget is clicked.
I am instantiating the toolbar and panel like so:
var popup = panel.Panel({
width: 310,
height: 400,
contentURL: self.data.url('panel.html'),
contentScriptFile: self.data.url('panel.js'),
// NOTE: You can't use the contentStyleFile option here.
});
var toolbarOptions = {
id: 'someid',
label: 'Some Label',
contentURL: self.data.url('icon-16.png'),
panel: popup
};
// There doesn't seem to be a way to remove the toolbar in PB mode.
var toolbar = widgets.Widget(toolbarOptions);
How can I cancel the panel opening from the widget click handler? It seems to always open no matter what logic I put in there.
toolbar.on('click', function() {
if (dontShowPanel()){
// I want to somehow cancel the panel opening at this point.
} else {
panel.show();
}
});
I have tried to return false; from the click hander which doesn't seem to work. I have also tried to call panel.hide(). That doesn't seem to work either.
I'm using version 1.10 of the add-on SDK.
Your click event handler is called before the panel shows up which means that you can still change the panel at this point. However, something that is non-obvious: changing the panel of the Widget object won't have any immediate effect, you need to change it for the WidgetView object (the widget instance in the particular browser window). That object is being passed as a parameter to the click event handler. So your toolbar options could look like this:
var toolbarOptions = {
id: 'someid',
label: 'Some Label',
contentURL: self.data.url('icon-16.png'),
onClick: function(view) {
if (dontShowPanel()){
view.panel = null;
} else {
view.panel = popup;
}
}
};
When you create the widget, you need to add the panel instance as a property:
var panel = require("panel").Panel({
width: 250,
height: 250,
contentURL: data.url('panel.html')
});
require("widget").Widget({
id: 'id',
label: 'my-label',
contentURL: data.url('http://www.mozilla.org/favicon.ico'),
panel: panel
});
Update: sorry I didn't understand the entire question. As far as I know there is no way to conditionally prevent show the panel based on the click event, in a way that will preserve the anchoring.

Reusing extended components in other views with ExtJS4 MVC

I'm using the mvc architecture method for a ui I'm building. I have a menu that I would like to reuse and would like to know if the following is possible:
File structure:
app/
--->app.js
--->view/
--------->viewport.js
--------->Toolbar.js
--------->SaveMenu.js
viewport.js:
Ext.define('MyApp.view.Viewport', {
extend: 'Ext.container.Viewport',
layout: 'fit',
requires: [
'MyApp.view.Toolbar',
'MyApp.view.SaveMenu',
],
initComponent: function () {
this.items = {
dockedItems: [
{
dock : 'top',
xtype : 'myapptoolbar',
height : 40,
}
]
...
// more config, but this works now.
Toolbar.js
Ext.define ('Myapp.view.Toolbar', {
extend : 'Ext.toolbar.Toolbar',
alias : 'widget.myapptoolbar',
items : [
{
text : 'Save',
// The following doesn't work, is there another way to achieve this?
menu : 'myappsavemenu',
}
]
});
SaveMenu.js
Ext.define ('Myapp.view.SaveMenu', {
extend : 'Ext.menu.Menu',
alias : 'widget.myappsavemenu',
items : [
{
text : 'Save as...',
}
]
});
Is it possible to reuse previously defined view components in other views, and if so how should I go about doing this?
Edit - Forgot the error thrown when using this configuration:
Uncaught TypeError: Cannot set property 'ownerCt' of undefined
Yes, it's perfectly reasonable, but the menu property should be a menu instance, a menu id or an object config.
I would go with:
menu: {xtype: 'myappsavemenu'},
ExtJS docs are available online. The button's menu config is addressed here: http://docs.sencha.com/ext-js/4-0/#!/api/Ext.button.Button-cfg-menu
In general, I'm just getting familiar with Ext.
Also note, the first method, which I've now removed, will give you the same menu instance across all myapptoolbars. This may or may not be a terrible thing depending on what you're doing. I try to stay away from it as it can be hard to debug when problems are introduced.

Resources