extjs 4.0 delegate to the parent node on mouse over - extjs

I wanted to to delegate the mouseover/mouseout event to my parent node.
Here in the below code when i roll over to the #mycontent > span.bannerContent, i should delegate my mouseover event to the parents child img#bannerImage.
How i can achieve using extjs
HTML code:
<div>
<img id="bannerImage" />
<div id="mycontent">
<span> my dummy content </span>
</div>
EXtJS code
items : [{
xtype: 'image',
id:'bannerview1',
src: 'images/homePage/banner-1.jpg',
height: 500,
width: 1240,
listeners: {
el: {
click: function(el,src) {
var link =src.src;
if(link.indexOf("banner-1.jpg")!= -1){
window.open("main");
}
}
}
}
},
{
xtype: 'box',
id:'label',
html: '<span class="bannerContent"></span> ',
listeners: {
**el: {
mouseover:function(){
},
mouseout:function(){
}**
}
}
}
]

Normally you can pass an event to any observable using relayEvent, but the problem is, that Ext.dom.Element is not observable (does not know fireEvent method). So either you can listen to mouse events on parent div, hook carousel also on box events or if you insist on relaying events, extend Ext.Img such that it fires mouseout and mouseover events itself (and not its 'el') and then hook your carousel on such events.
Ext.define('My.Img',{
extend: 'Ext.Img',
alias: 'widget.myimage',
initComponent: function(){
var me = this;
me.addEvents('mouseover','mouseout');
me.on('render',function(){
me.getEl().relayEvent('mouseover',me);
me.getEl().relayEvent('mouseout',me);
});
me.callParent();
}
});
var myImage = Ext.create('My.Img',{
id:'bannerview1',
height: 500,
width: 1240,
src: '/img/header_01.gif',
listeners: {
mouseover:function(e){
console.log('mouseover image');
},
mouseout:function(e){
console.log('mouseout image');
}
}
});
Ext.create(' ... ',{
...
items : [ myImage,
{
xtype: 'box',
id:'label',
html: '<span class="bannerContent">blablabla</span> ',
listeners: {
render: function(){
this.getEl().relayEvent('mouseover',myImage);
this.getEl().relayEvent('mouseout',myImage);
}
}
}
]
});
Personally I think that such solution is not very straightforward.

Related

Unable to listen change event in controller

Am new in Ext JS community. Here I want to apply a change event to child component which is 'textfield'.
I have specified the 'onChangeSealNumber' function in the controller. But it's not getting fired.
Can someone help me into it?
I have tried many approaches, however, If I pass anonymous function on change, it will work. But it won't work when we explicitly specify as 'onChangeSealNumber'.
View File
/**
* Search Form Panel View.
* #class 'BulkTransaction.view.searchfrom.SearchForm'
*/
Ext.define('BulkTransaction.view.searchform.SearchForm', {
extend: 'Ext.container.Container',
requires: [
'Common.view.widget.RepeatingWidgetGroup',
'BulkTransaction.view.storagelocation.StorageLocation',
'BulkTransaction.view.searchform.SearchFormController',
],
alias: 'widget.searchform',
controller: 'searchformcontroller',
items: [
{
xtype: 'basepanel',
width: '100%',
reference: 'searchform',
header: false,
items: [
{
width: '100%',
xtype: 'connect-repeating-widget-group',
bind: {
store: '{topSealNumbers}'
},
bindReference: 'topSealNumbers',
widgetConfig: {
xtype: 'textfield',
fieldLabel: BulkTransaction.util.Constants.searchForm.topSealNumbers,
allowBlank: false,
bind: '{topSealNumbers.searchCriteria}',
cls: 'seal-number-field',
listeners: {
change: 'onChangeSealNumber'
}
}
}
]
}
]
});
Controler File
/**
* Controller containing the methods implementing functionality
* related to search form
*/
Ext.define('BulkTransaction.view.searchform.SearchFormController', {
extend: 'Ext.app.ViewController',
alias: 'controller.searchformcontroller',
init: function () {
const me = this;
const viewModel = me.getViewModel();
viewModel.bind({
bindTo: '{topSealNumbers}',
deep: true
}, me.onSearchCriteriaChange, me);
},
/**
* Handle change to the sealnumber details
* #private
*/
onSearchCriteriaChange: function (store) {
const me = this;
let searchCriteriaRecords;
searchCriteriaRecords = store.queryBy(rec =>{
if (!Ext.isEmpty(rec.get('searchCriteria').trim())) {
return rec;
}
});
this.fireEvent('toggleSearchButton', searchCriteriaRecords.length > 0);
},
onSealNumberChange (elm) {
const me = this,
view = me.getView();
}
});
In you controller you need to create a function named onChangeSealNumber something like this
Ext.define('BulkTransaction.view.searchform.SearchFormController', {
extend: 'Ext.app.ViewController',
alias: 'controller.searchformcontroller',
onChangeSealNumber: function(field, newValue, oldValue, eOpts) {
//do something here
},
})
You can try (MyApp - name of your application):
listeners: {change: MyApp.app.getController('SearchFormController').onChangeSealNumber()}
But as for me its not good way to work with controller. More better add into controller (inside init):
init: function (application) {
this.control({
"searchform textfield": {
change: this.onChangeSealNumber
},
});
}
As for identifier I'm not sure because as usually use itemId and name
(like `"#myItemId textfield[name=MyFieldName]"` )

extjs contextmenu click, pass parent grid as parameter to controller method

Inside my extjs grid, when I right click I call a context menu. When I click on one of the items I want to launch a method in the controller. This all works successfully, problem is I want to pass the parent grid that this is being called from into the controller method. Can someone please show me how to do this?
This is my context menu
Ext.define('Example.ContextMenuTradematch', {
xtype: 'contextMenuTradematch',
extend: 'Ext.menu.Menu',
items: [
{
text: 'Match Trade',
iconCls: 'greenIcon',
listeners: {
click: {
fn: 'onMatchTrade',
params: {
param1: this
}
}
}
},
{
text: 'Delete Trade',
iconCls: 'deleteIcon',
listeners: {
click: 'onDeleteTrade'
}
}
]
});
then this is my controller method
onMatchTrade: function (event, target, options) {
debugger;
var me = this;
How can I access the grid that the event originated from?
--and this is how I add the context menu to the grid
title: 'Tradematch Results: UNMATCHED',
xtype: 'grid',
itemId: 'gridUnmatchedId',
ui: 'featuredpanel-framed',
cls: 'custom-grid',
margin: '0px 10px 0px 10px',
flex: 2,
width: '100%',
bind: {
store: '{myTM_ResultsStore}'
},
listeners: {
itemcontextmenu: 'showContextMenuTradematch'
},
and this is how the controller adds it...
getContextMenu: function (cMenu) {
if (!this.contextMenu) {
debugger;
this.contextMenu = this.getView().add({ xtype: cMenu });
}
return this.contextMenu;
},
showContextMenuTradematch: function (view, rec, node, index, e) {
e.stopEvent();
e.stopEvent();
debugger;
this.getContextMenu('contextMenuTradematch1').show().setPagePosition(e.getXY());
return false;
},
The easiest way to do this is when you create your Example.ContextMenuTradematch instance - that I'm assuming you do from a itemcontextmenu listener - then you could pass a reference to the grid.
itemcontextmenu: function (grid, record, item) {
// code to create your menu
// probably something like:
if (!grid.contextMenu) {
grid.contextMenu = Ext.create('Example.ContextMenuTradematch', {
ownerGrid: grid
});
}
grid.contextMenu.showBy(item);
}
If onMatchTrade was fired by clicking on an Ext.menu.Item instance then it's signature will be:
onMatchTrade: function (item, e) {
var menu = item.up('menu'),
grid = menu.ownerGrid;
console.log(grid);
}
There was a lot of guessing here. If this is not how you are creating your menu or calling the methods, adding a fiddle with the issue would help.
Here is a fiddle to use as template: https://fiddle.sencha.com/#view/editor&fiddle/24fc

ExtJS 4.2 resizable, draggable component

In my code I use MVC architecture. My view Component looks like this:
Ext.define('calendar.view.event', {
extend: 'Ext.Component',
alias: 'widget.event',
renderTo: Ext.getBody(),
initComponent:function(){
this.addEvents('eventClick');
this.callParent(arguments);
},
afterRender: function() {
this.mon(this.el, 'click', this.eventClick, this); //mon( item, ename, [fn], [scope], [options] ) - zkratka pro addManagedListener.
this.callParent(arguments);
},
eventClick: function (ev, t) {
var height = this.getHeight();
this.fireEvent('eventClick', this, height, ev);
}
});
Im firing Event on click for controller which is like this:
Ext.define('calendar.controller.eventsChange', {
extend: 'Ext.app.Controller',
views: ['event'],
init: function () {
this.control({
'event': {
eventClick: function (callerObject) {
this.editEvent(callerObject)
}
}
});
},
editEvent: function (callerObject) { //oznaci jako editovatelny
callerObject.get
if(callerObject.hasCls('SpecEv') || callerObject.hasCls('activeEvent'))
{
if (callerObject.hasCls('activeEvent'))
{
callerObject.removeCls('activeEvent');
callerObject.addCls('SpecEv');
this.application.fireEvent('reRender');
}
else
{
console.log(callerObject);
callerObject.addCls('activeEvent');
callerObject.removeCls('SpecEv');
Ext.apply(callerObject, {
resizable: {
pinned:true,
dynamic:true
},
draggable: true,
});
callerObject.setLocalX(0);
var parentWidth = Ext.getCmp('SpecEv').getWidth();
callerObject.setWidth(parentWidth);
}
}
}
});
The problem comes when with
Ext.apply(callerObject, {resizable: {
pinned:true,
dynamic:true
},
draggable: true,
});
When console.log shows me the object after my apply, it says draggable:true and resizable:true. Does anyone know where the problem is?
Thanks for reponses.
It can't works, because your code only set configuration properties, which are handled only when component is initializing. So when you set these properties on already constructed object nothing happen. Component resizability and draggability will not be initialized automatically after setting these properties.
You can try use Ext.Component initResizable and initDraggable methods. But these methods are internal and undocumented.
callerObject.initResizable({
pinned:true,
dynamic:true
});
callerObject.initDraggable();
Also you can try setup Ext.util.ComponentDragger and Ext.resizer.Resizer for your existing component manually.

Sencha touch calendar swarmonline - refresh calendar event

I'm trying to work with a Sencha Touch calendar extension (http://www.sencha.com/forum/showthread.php?156351-Ext.ux.TouchCalendar) Here is an example of what im using: http://www.swarmonline.com/Ext.ux.TouchCalendar/examples/simple-events-list.html
Am facing a problem here. when the app loads first time the events dots are missing..but when I resize my browser window, suddenly some event call happens and dots become visible and also at the same time its duplicating..
Am using their Simple events plugin. This is my view structure
Ext.define('WinReo.view.EventListPanel', {
extend: 'Ext.Panel',
//xtype:'EventListPanel',
requires: [
'Ext.dataview.List',
'Ext.layout.Fit'
],
alias: 'widget.EventListPanel',
config: {
// title : 'Events List',
layout : 'fit',
store:'WinReo.store.Events'
},
initialize: function(){
var store = Ext.getStore('Events');
store.load({
callback: function(records, operation, success) {
// the operation object contains all of the details of the load operation
console.log(records);
},
scope: this
});
this.callParent(arguments);
this.setItems([
{
xclass : 'Ext.ux.TouchCalendarView',
itemId : 'calendarView',
//minDate : Ext.Date.add((new Date()), Ext.Date.DAY, -40),
//maxDate : Ext.Date.add((new Date()), Ext.Date.DAY, 55),
viewMode : 'month',
weekStart : 0,
value : new Date(),
eventStore : Ext.getStore('Events'),
plugins : [Ext.create('Ext.ux.TouchCalendarSimpleEvents')]
/* plugins : [Ext.create('Ext.ux.TouchCalendarEvents', {
eventBarTpl: '{Days2Go}'
})]*/
},
{
xtype : 'list',
itemId : 'calendarlist',
docked : 'bottom',
onItemDisclosure:'true',
cls:'myList',
height : 100,
itemTpl : ['<tpl if ="Days2Go==0">',
'<div class="calendarlistred"> <div style="float:left; width: 45%">{PropertyAddr}</div><div style="float:left; width:45%">{TaskDesc}</div><div style="float:right; width:10%">{Days2Go}</div></div>',
'</tpl>',
'<tpl if ="Days2Go!=0">',
'<div> <div style="float:left; width: 45%">{PropertyAddr}</div><div style="float:left; width:45%">{TaskDesc}</div><div style="float:left; width:10%">{Days2Go}</div></div>',
'</tpl>'
],
store : Ext.create('Ext.data.Store', {
model: 'WinReo.model.Event',
data: []
}),
listeners: {
itemtap: function(dw, index,record, item, e){
window.open('http://blr.amt.in:8081/CRM_API/TaskCalendar.ashx?all_tasks=-1');
}
}
},
{
xtype : 'label',
html: '<div> <div style="float:left; width: 45%">Property</div><div style="float:left; width:45%">Task Description</div><div style="float:right; width:10%">Days to go</div></div>',
layout:'hbox',
docked : 'bottom',
cls:'calendarlistheader'
}
]);
}
});
Also I want I come to know that there is function there in TouchCalendarSimpleEvents.js
refreshEvents: function(){
if (!this.disabled && this.calendar.getViewMode() !== ‘DAY’) {
var datesStore = this.calendar.getStore();
…..
how can i call this function in my periodchange controller event ?
onPeriodChange: function(view, minDate, maxDate, direction){
Ext.Ajax.setDefaultHeaders({
'session_id' : localStorage.getItem("session_id")
});
console.log('periodchange');
console.log(view);
console.log(minDate);
var monthstartdate = Ext.Date.format(minDate, 'm/d/Y');
var url = 'http://blr.amt.in:8081/CRM_API/TaskCalendar.ashx?';
var urlafter = url + 'monthstartdate='+ monthstartdate;
// proxy change
var group_store = Ext.getStore("Events");
group_store.getProxy().setUrl(urlafter);
group_store.load();
var storecount = group_store.getCount();
this.refreshEvents(); // ***here i want to call refresh function***
}
Your help is much appreciated.

How to close modal window extjs when clicking on mask?

If I create a modal window:
Ext.define('myWindow', {
extend: 'Ext.Container',
alias: 'widget.myWindow',
floating: true,
modal: true,
listeners:
'onMaskClick???': { close the window }
.....
}
How do I know when a user has clicked on the mask outside the window? In Sench Touch, there is a config hideOnMaskTap that lets me specify. What is the event/config for extJS?
Tramway's case (sort of) works on modal or non modal windows. But not in case child components like the boundlist of a combobox float outside the windows boundaries.
However if you use modal windows anyway you can listen for a click event on the mask like this.
Ext.define('myWindow', {
extend: 'Ext.window.Window',
alias: 'widget.myWindow',
floating: true,
modal: true,
initComponent: function () {
var me = this;
me.callParent(arguments);
me.mon(Ext.getBody(), 'click', function(el, e){
me.close(me.closeAction);
}, me, { delegate: '.x-mask' });
}
});
You can listen all click events, then check if click position is out of the window
Ext.define('myWindow', {
extend: 'Ext.Container',
alias: 'widget.myWindow',
floating: true,
modal: true,
initComponent: function () {
this.initEvents();
this.callParent();
},
initEvents: function () {
//make sure your window is rendered and have sizes and position
if(!this.rendered) {
this.on('afterrender', this.initEvents, this, {single: true});
return;
}
this.mon(Ext.getBody(), 'click', this._checkCloseClick, this);
}
_checkCloseClick: function (event) {
var cx = event.getX(), cy = event.getY(),
box = this.getBox();
if (cx < box.x || cx > box.x + box.width || cy < box.y || cy > box.y + box.height) {
//clean up listener listener
this.mun(Ext.getBody(), 'click', this._checkCloseClick, this);
this.close();
}
}
}
You can try this also:
Ext.getBody().on('click', function(e, t){
var el = win.getEl();
if (!(el.dom === t || el.contains(t))) {
win.close();
}
});
I found adding a listener to the body and checking css classes felt a little hackey to me. You can actually override the private method _onMaskClick of Ext.ZIndexManager (see, completely not hackey). Which allows you to add your own configuration parameter (and even event) to all windows.
Ext.define('MyApp.ux.ZIndexManager_maskClick', {
override: 'Ext.ZIndexManager',
_onMaskClick: function ()
{
if (this.front)
{
var allowed = this.front.fireEvent('maskclick', this.front, this.mask);
if (allowed !== false && this.front.closeOnMaskClick)
this.front.close();
}
return this.callParent(arguments);
},
});

Resources