Sencha Touch 2 Component in list emptyText - sencha-touch-2

I have a list component that I want to display a button to send a suggestion for the data to be included if it turns up no results.
List component itself is implemented like this:
{
xtype: 'list',
itemTpl: '{name}',
// This is not ideal!
emptyText: [
'<div class="x-button-normal x-button">',
'<span class="x-button-label">',
'Suggest <i><span id="suggest-name"></i>',
'</span>',
'</div>'
].join(''),
store: 'TheStore'
}
And this is the handler for the search field that simply sets a substring filter on the store:
'keyup': function(self, e, eOpts) {
queryString = self.getValue();
 
var store = Ext.getStore('TheStore');
store.clearFilter();
 
if(queryString){
var thisRegEx = new RegExp(queryString, "i");
store.filterBy(function(record) {
if (thisRegEx.test(record.get('name'))) {
return true;
};
return false;
});
// Changes the button so it shows name
document.getElementById('suggest-name').innerText = queryString;
}
},
Right now, I have the emptyText set to some simple HTML that emulates the look of a Sencha Touch button, but this means I have none of the button behaviour since it's not tied into the component system (such as being depressed when tapped). How can I set the emptyText attribute (or emulate it) since a proper button is displayed instead?

Try to view the two screencasts below
Sencha Touch - Intro to Nested List Component
Sencha Touch 2 -
Intro to List Component

I know it's about 2 years too late... but I ran into the same problem as #Hampus Nilsson and when I found the solution, I figured if I was running into this 2 years later, others might run into it as well.
With that said... I'm currently running Sencha Touch version 2.3.1. The solution, as it pertains to that version, was really easy to implement, just super tricky to find. The problem is that Sencha has a CSS property on the emptyText component (x-list-emptytext class) that is ignoring all pointer interactions called pointer-events: none; (who knew?!)
This property is found in:
[sdk_root]/resources/themes/stylesheets/sencha-touch/base/src/dataview/_List.scss
.x-list-emptytext {
text-align: center;
pointer-events: none; // THIS ONE!!
font-color: #333333;
#include st-box();
#include st-box-orient(vertical);
#include st-box-pack(center);
}
To fix this, simply override that property in your own sass/css. I chose to override it with pointer-events: inherit; but your mileage may vary.
THEN, all you need to do is setup a listener on your list, I recommend in the initialize function of your list class, like the so:
this.emptyTextCmp.element.on({
delegate: '.x-button-normal',
scope: this,
tap: this.yourCustomFunction
});
Where this is your list component. It's important to note that you need a "." in front of the class name of your delegate. In the above example, I set the delegate to: '.x-button-normal', because that was one of the two classes listed in the question's code. I could've also used '.x-button'. If it were me, I'd give your html an additional class, to be used as the delegate, that helps identify it a little better, instead of just using the default Sencha class as your delegate. That's an opinion, not a requirement.
That's it, I hope this helps someone else!

Related

Is it possible to un-nest (or re-nest) a selector block in LESS?

Say I have some LESS styling like:
.some-context {
.some-parent {
.some-nav {
a {
color: blue;
&.active { color: black; text-decoration: underline; }
}
}
}
}
Basically, we were styling links within one particular deep context in a certain way.
But now we have a second context that needs the same link styling.
I know I can use & to repeat the parent selector, but is there a way to "unset" the parent selector? Instead of re-using/re-arraging the parent selector, I want to discard it.
(I have used &:extend() to "steal" styling of other parts of the page from another context, but ends up quite fragile — quietly breaking whenever the other code/nesting ever changes. So I'm looking for alternatives.)
Is there a way to do something like:
// (deep within a nested context)
a, ⅋ .other-context a {
// …
}
…where whatever actual syntax "⅋" is standing in for would mean "reset the context and discard all parent selectors"?
Unfortunately, it is not currently possible (as of December 2018), but there is an open github feature request that can be found here. However, if you consider the option of switching to SASS, then you could use its #at-root directive.

Displaying Custom Images in 'tools' config options of ext.grid.panel

I am only a month old with extjs and still experimenting. My question is: I have a grid panel and within it the 'tools' config options. I am using this to enable/disable a Ext.grid.feature.Grouping variable. The 2 handler functions have the logic to disable/enable the 2 views by clicking on the 2 'cross' buttons that appear on the right side of the header. The logic is fine. However, I would like to display my set of custom images in place of the 'cross' buttons. Can this be done? If yes, how? Do I need to make some changes in the css code for that?
I have looked into the documentation and also done a good search but nothing seems to answer my question.
Specify a custom type config on your tools:
Ext.create('Ext.grid.Panel', {
...
tools: [
{
type: 'enable-grouping',
handler: function() {
...
}
},
{
type: 'disable-grouping',
handler: function() {
...
}
}
]
});
Then define the following classes in a stylesheet to style your new tools:
.x-tool-enable-grouping {
background-image: url('path/to/tool/image/enable-grouping.png');
}
.x-tool-disable-grouping {
background-image: url('path/to/tool/image/disable-grouping.png');
}
The size of a tool image should be 15 x 15 px

How do you recover the dijit registry after destroying it recursively?

I am working on an application and was doing something like this:
dojo.ready(
function(){ require['dojo/parser','dijit/registry','dojo/on'],function(.....){
//find a dijit and wrap it in event handling code.});
I was getting an error indicating that dojo was trying to register a widget with an id that was already in use. To solve the problem I entered this line of code:
//before finding the dijit destroy the existing registry.
However, logically this prevents the next line from working because now no widget exists to which I can connect an event. How can I recover the dijit ids?
The best solution is to find out why your code is trying to register a widget with an id that is already in use and change it to not to do so.
The #mschr's solution should work, but I would advise again using it, as it can break your code in many other places and you are likely to spend hours investigating strange behavior of your application.
Anyway, if you are willing to do it that way and automatically destroy widgets with the same ID, do not override registry.add() method. You could do it, but it does not mean, you should do it (especially in programming). Employ dojo/aspect instead to call a function that will destroy the widget with the same ID before registry.add() is called:
require([
"dojo/aspect",
"dijit/registry"
], function(
aspect,
registry
) {
aspect.before(registry, "add", function(widget) {
if(registry.byId(widget.id)) {
registry.byId(widget.id).destroy();
// this warning can save you hours of debugging:
console.warn("Widget with id==" + widget.id + " was destroyed to register a widget with the same id.");
}
return [widget];
});
});
I was myself curious how to accomplish #mschr solution without that override, so I created an jsFiddle to experiment: http://jsfiddle.net/phusick/feXVT/
What happens once you register a dijit is the following; it is referenced by the dijit.registry._hash:
function (widget) {
if (hash[widget.id]) {
throw new Error("Tried to register widget with id==" + widget.id + " but that id is already registered");
}
hash[widget.id] = widget;
this.length++;
}
Now, every now and then you would have a contentpane in which you would put a widget programatically (programatically, hence dojo.parser handles cpane.unload and derefences / destroys parser-instantiated widgets).
When this happens, you need to hook onto some form of 'unload', like, when your call cpane.set('content' foo) or cpane.set('href', bar). Hook is needed to destroy and unregister the instances you keep of widgets - otherwise you would have a memoryleak in your program.
Normally, once an object has no references anywhere - it will get cleaned out of memory however with complex objects such as a widget might be, 'class-variables' often have reference to something _outside _widget scope which flags the widget unsafe to delete to the garbage collector... Once you get this point, you will know to perform proper lifecycles, yet not before the concept is fully understood..
What you could do is to override the dijit.registry with your own handler and have any widgets that are doublets destroyed automatically like so:
// pull in registry in-sync and with global scoped
// accees (aka dijit.registry instead of dj_reg)
require({
async:false,
publishRequireResult:true
}, [
"dijit.registry"
], function(dj_reg) {
dijit.registry.add = function(widget) {
// lets change this bit
if (this._hash[widget.id]) {
this._hash[widget.id].destroy(); // optinally destroyRecursively
this.remove(widget.id)
}
this._hash[widget.id] = widget;
this.length++;
}
});

QML application launcher similar to iOS

I'm trying to write an application launcher using QtQuick\QML, and I'd like the user experience to be similar to iOS, in terms of having a grid of icons that can be rearranged with icons that "move out of the way" via animated transitions and a "snap to grid" effect if the icon is dropped in an intermediate position. I've tried using GridView and the drag properties, but I can't seem to get the layout do what I want. What would be the best way to implement this type of app using QML? I'm fairly new to QtQuick, and I feel like maybe I'm missing something fundamental that would make this fairly easy\obvious to write.
For putting icons in a grid, you can use the grid view:
http://developer.qt.nokia.com/doc/qt-4.8/qml-gridview.html
Go through the Qt Quick documentation, you will find out how to do this.
This is not directly relevant to implementing the grid of icons, but I recently came across the QML component Loader. This lets you load QML components on demand, and could be useful for the code that launches an app after the icon is selected.
http://doc-snapshot.qt-project.org/5.0/qml-qtquick2-loader.html
I have made Nokia N9 launched look and feel (Maemo 6, or also known as MeeGo).
It is similar, I just scroll from up to down with icons, while you change "pages" from left to right (and vice versa).
I don't know is it best way, but this is how I did icon manager (its shrinked, this is only to give you idea - in reality it is considerably larger):
Item
{
id: root
function getChildAt(x, y) {}
function getIndexOfChild(child) {}
function moveChild(child, x, y)
{
//moving around icons
}
function setIndexToChild(child)
{
//index of child in Grid element (where to drop)
}
Flickable
{
id: scroller
clip: true
//you most likely want HorizontalFlick ("paging" effect you can add on onBeginingXChanged)
flickableDirection: Flickable.VerticalFlick
contentHeight: iconTable.height
contentWidth: iconTable.width
Grid
{
id: iconTable
width: root.width
anchors.top: parent.top
flow: Grid.LeftToRight
spacing: 10
add: Transition
{
NumberAnimation
{
properties: "x,y"
//make desired transition
}
}
move: Transition
{
NumberAnimation
{
properties: "x,y"
//make desired transition
}
}
}
}
}
You could also write down your own implementation of manager in C++ and later on use it in QML.
This is how it looks like:
I created something distantly connected to this recently, the idea is: create a ListView with snapping. Its delegate should contain a GridView. Separate all of the apps into n-element chunks. Then (it's only the idea)
ListModel
{
ListElement { apps: [app1, app2, ..., appn] }
ListElement { apps: [app1, app2, ..., appn] }
....
ListElement { apps: [app1, app2, ..., appk] }
}
Then populate the ListView with this model and the GridView with the apps property.
I don't know whether you can provide drag and drop here, though

Set a default UI across all components in Sencha Touch

Within Sencha Touch, is it possible to define a default UI , like "light" or "dark", that applies to all components (unless overwritten explicitly)?
The aim is to avoid having to declare ui: "dark", or any custom UI that is made, for every element.
Cheers!
You can try this:
Ext.apply(Ext.Component.prototype, {
getUi: function() {
var defaultUi = 'light';
// value of [this.config.ui] is ignored here
// we can use something like forcedUi
return (this.forcedUi) ? this.forcedUi : defaultUi;
}
})
The disadvantage of this code is that we need to specify another variable for applying ui different from 'light' (because variable 'ui' via getUi() will always return 'light'):
...
items: [{
xtype: 'button',
forcedUi: 'dark'
}]
...
I am stuck on Touch 1.1 so sunsay's solution didn't work for me, but this did:
Ext.CustomToolbar = Ext.extend(Ext.Toolbar,
{
ui:'app'
});
Ext.reg('toolbar', Ext.CustomToolbar);
So, it's still component-by-component-type, but not component-by-component-instance. And since you can overwrite the "reg", no need for custom x-types all over the place, either.
I assume that you know about sencha touch styles and themes. Otherwise you can download a pdf file from this link which clearly describes about how to do it...
http://f.cl.ly/items/d9df79f57b67e6e876c6/SenchaTouchThemes.pdf
In it they are mentioning about scss file where you can specify the base-color, ie
$base-color: #4bb8f0 ;
$base-gradient: 'glossy';
Then run it ... you can see the toolbars and buttons created with the color and gradient you have mentioned.