ExtJs on click fires number of times the window is opened - extjs

In the before render event of the window. i have this code
Ext.define('Ext.view.ReaderWindow', {
extend: 'Ext.window.Window',
alias: 'widget.reader',
id1: 0,
file_path: '',
id: 'reader',
itemId: 'reader',
maxHeight: 800,
maxWidth: 900,
minHeight: 300,
minWidth: 500,
layout: {
type: 'anchor'
},
title: 'File Reader',
modal: true,
initComponent: function() {
var me = this;
Ext.applyIf(me, {
items: [{
xtype: 'form',
anchor: '100% 100%',
itemId: 'reader_form',
maxHeight: 800,
maxWidth: 900,
minHeight: 300,
minWidth: 500,
autoScroll: true,
bodyPadding: 10,
items: [{
xtype: 'displayfield',
anchor: '100%',
itemId: 'file_contents',
maxWidth: 900,
minWidth: 50,
hideLabel: true,
name: 'file_contents'
}]
}],
listeners: {
beforerender: {
fn: me.reader_windowBeforeRender,
scope: me
}
}
});
me.callParent(arguments);
},
reader_windowBeforeRender: function(component, eOpts) {
Ext.model.FileReaderModel.load(this.id1, {
params: {
'file': this.file_path
},
success: function(file_reader) {
var form_panel = current.query('#reader_form');
var contents_field = form_panel[0].getComponent('file_contents');
var contents = file_reader.get('file_contents');
var pattern = /(\/.*?\.\S*)/gi;
contents = contents.replace(pattern, "<a href='#' class='sample'>$1</a>");
contents_field.setValue('<pre>' + contents + '</pre>');
Ext.select('.sample').on('click', function() {
var path = this.innerHTML;
var Id1 = this.id1;
var reader = Ext.create('Ext.view.ReaderWindow', {
id1: Id1,
file_path: path
});
reader.show();
});
},
failure: function(file_reader, response) {
}
});
},
});
for "a tag" i have assigned "sample" class. When a link is clicked, it opens a new window (but the same window is used to show the content).
The problem is if i click the a tag first time, then on click is called once. Then after i close the window and click a tag again..this time it fires twice. So depending on number of times i open and close..the click event is called so many times.
It looks like every time i open the window same event is registered multiple times. But i want to register the event only once.Any time i click a link, only once it should call the click event.

Related

Extjs how to get the cursor position in a textareafield

I'm new to Extjs, I need to know how to get te position of the cursor in a textareafield.
I've been googleing an I found these links:
EXTJS 5: Get the current cursor position in a textfield or lookupfield
and
In ExtJs, how to insert a fixed string at caret position in a TextArea?
From there I got this:
Ext.application({
name: 'Fiddle',
launch: function() {
Ext.define({
xtype: 'container',
renderTo: Ext.getBody(),
layout: 'vbox',
padding: 20,
defaults: {
xtype: 'button',
margin: '0 0 12 0'
},
items: [
{
xtype: 'textareafield',
grow: false,
width: 545,
height: 120,
name: 'message',
fieldLabel: '',
id: 'mytextarea',
anchor: '100%'
},
{
xtype: 'button',
text: 'Go',
scale: 'medium',
id: 'mybutton',
listeners: {
click: function() {
var zone = Ext.getCmp('mytextarea');
var text = zone.getValue();
var posic = zone.el.dom.selectionStart;
console.log(posic); // undefined
}
}
}
]
});
}
});
this fiddle
Oh, and I'm using Ext 6.x, Linux Mint, Firefox and Chromium.
But always posic will return undefined... How can I solve this?
You may try with the following approach:
Ext.application({
name : 'Fiddle',
launch : function() {
Ext.define('Trnd.TestWindow', {
extend: 'Ext.window.Window',
closeAction: 'destroy',
border: false,
width: 400,
height: 500,
modal: true,
closable: true,
resizable: true,
layout: 'fit',
title: 'Close window to see the position',
getCaretPos: function() {
var me = this;
var el = me.myTextArea.inputEl.dom;
if (typeof(el.selectionStart) === "number") {
return el.selectionStart;
} else if (document.selection && el.createTextRange){
var range = document.selection.createRange();
range.collapse(true);
range.moveStart("character", -el.value.length);
return range.text.length;
} else {
throw 'getCaretPosition() not supported';
}
},
initComponent: function() {
var me = this;
me.callParent(arguments);
me.myTextArea = Ext.create('Ext.form.field.TextArea', {
width: 500,
height: 500,
editable: true,
selectOnFocus: false,
listeners: {
afterrender: function() {
this.focus(true);
var cursorPos = this.getValue().length;
this.selectText(cursorPos, cursorPos);
}
}
});
me.panel = Ext.create('Ext.panel.Panel', {
items: [
me.myTextArea
]
});
me.add(me.panel);
},
listeners: {
'close': function() {
var me = this;
alert(me.getCaretPos());
}
}
});
var win = new Trnd.TestWindow({
});
win.show();
}
});
Test example with this fiddle.
Use Ext.getDOM() instead of Ext.getCmp() like this:
var myTextArea = Ext.getDom('mytextarea');
var textInArea = myTextArea.value;
var caretPosition = myTextArea.selectionStart;
console.log(caretPosition);
EDIT:
Also xtype of the field must be changed to textarea. In this case your initial example should work too.

Window is not closing properly second time

I want to open a new window on click of button. On cclick on button window is opening and closing fine but second time it is not closing properly.
Here is my code
var formPanel = new Ext.FormPanel({
height: 125,
autoScroll: true,
id: 'formpanel',
defaultType: 'field',
frame: true,
title: 'CheckOut from SVN',
items: [{
fieldLabel: 'SVN Path'
}],
buttons: [{
text: 'Submit',
minWidth: 75,
handler: function() {
var urlTemp = './Export?' + '&' + fp.getForm().getValues(true);
formPanel.getForm().submit({
url: urlTemp,
method: 'Post',
success: successFn1,
timeout: 18000000,
failure: otherFn
});
}
}, {
text: 'Reset',
minWidth: 75,
handler: function() {
formPanel.getForm().reset();
}
}]
});
function buildWindow() {
var win = new Ext.Window({
id: 'newWindow',
layout: 'fit',
width: 300,
height: 200,
closeAction: 'hide',
plain: true,
stateful: false,
items: [formPanel]
});
win.show();
}
var extSVN = new Ext.Button({
text: 'Checkout from SVN',
minWidth: 75,
handler: function() {
buildWindow();
}
});
Ext.create('Ext.panel.Panel', {
renderTo: Ext.getBody(),
width: 400,
height: 300,
items: [extSVN]
});
you are using closeAction: 'hide' on your window which mean that when you close it it will not be destroyed but hidden.
The problem is that when you reopen the window you create a new one so your formPanel ends up in 2 different windows which causes the error.
You can :
remove the closeAction: 'hide', but your formPanel will also be
destroy when you close the window, so you'll have to recreate
another too
or keep the closeAction: 'hide' and only create the
windows one time
You have provided id to your form and window. And inside window you have set config closeAction: 'hide' that means whenever your press close button window is hiding.
And on again on-click of Checkout from SVN button you creating a same window and form with same id's so instead of creating of new window you can use previous window and show again.
In this FIDDLE, I have created a demo using your code and put some modifications.
CODE SNIPPET
Ext.onReady(function () {
var formPanel = new Ext.FormPanel({
height: 125,
autoScroll: true,
id: 'formpanel',
defaultType: 'field',
frame: true,
title: 'CheckOut from SVN',
items: [{
fieldLabel: 'SVN Path'
}],
buttons: [{
text: 'Submit',
minWidth: 75,
handler: function () {
var urlTemp = './Export?' + '&' + fp.getForm().getValues(true);
formPanel.getForm().submit({
url: urlTemp,
method: 'Post',
success: successFn1,
timeout: 18000000,
failure: otherFn
});
}
}, {
text: 'Reset',
minWidth: 75,
handler: function () {
formPanel.getForm().reset();
}
}]
});
function buildWindow(btn) {
if (!btn.win) {
btn.win = new Ext.Window({
layout: 'fit',
id: 'newWindow',
modal: true,
width: 300,
height: 200,
closeAction: 'hide',
plain: true,
stateful: false,
items: [formPanel]
});
}
btn.win.show();
}
var extSVN = new Ext.Button({
text: 'Checkout from SVN',
minWidth: 75,
handler: buildWindow
});
new Ext.Panel({
title: 'SVN Chekcout',
renderTo: Ext.getBody(),
width: 200,
height: 130,
items: [extSVN],
renderTo: Ext.getBody()
});
});

extjs proper way to replace main center panel

In ExtJS, on a menu toolbar button, I am trying to remove the current panel in my center window, then recreate it with the new selection. I do not understand the proper way to do this. So far when I click the menu item, it removes whatever is currently there successfully, then it will add the new panel successfully. The problem is the 2nd time I hit the button I get the following error:
REGISTERING DUPLICATE COMPONENT ID 'mainportalID'.
I realize its telling me I already used this ID, but then what would be the correct way to remove the current panel, and replace with a new one?
Here is my view controller:
selectMenuButton: function (button, e) {
console.log('select menu button section was hit')
console.log(button);
console.log(e);
var optionString = button.text;
var myDetailsPanel = Ext.getCmp('navview');
console.log(myDetailsPanel);
var count = myDetailsPanel.items.items.length;
if (count > 0) {
myDetailsPanel.items.each(function (item, index, len) {
myDetailsPanel.remove(item, false);
});
}
myDetailsPanel.add({
xtype: optionString
});
}
var myStore = Ext.create('ExtApplication1.store.PositionsStore');
var gridSummary = Ext.create('Ext.grid.Panel', {
store: myStore,
width: 600,
title: 'my first grid',
columns: [
{
text: 'AcctNum',
dataIndex: 'AcctNum',
width: 100
},
{
text: 'AcctShortCode',
dataIndex: 'AcctShortCode',
flex: 1
},
{
text: 'Exchange',
dataIndex: 'Exchange',
width: 200
}
]
});
This is my view
Ext.define('ExtApplication1.view.main.MainPortal', {
extend: 'Ext.panel.Panel',
xtype: 'mainportal',
alias: 'widget.mainportal',
id: 'mainportalID',
html: 'user... this is the main portal window',
autoScroll: true,
bodyPadding: 10,
items: [
gridSummary
]
});
adjusted panel
Ext.define('ExtApplication1.view.main.MainPortal', {
extend: 'Ext.panel.Panel',
xtype: 'mainportal',
alias: 'widget.mainportalAlias',
reference: 'gridtextfield',
//id: 'mainportalID',
html: 'user... this is the main portal window',
autoScroll: true,
bodyPadding: 10,
items: [
gridSummary
]
});
adjusted view controller
onComboboxSelect: function (combo, record, eOpts) {
console.log('new listener was hit');
//return selected Item
var selectedValue = record.get('ClientName');
var selectedCID = record.get('ClientID');
//find the grid that was created
var me = this;
console.log(me);
var xxx = this.lookupReference('gridtextfield');
debugger;
//debugger;
var mainPortalView = Ext.getCmp('mainportalID');
var targetGrid = mainPortalView.down('grid');
//find the store associated with that grid
var targetStore = targetGrid.getStore();
//load store
targetStore.load({
params: {
user: 'stephen',
pw: 'forero',
cid: selectedCID
}
//callback: function (records) {
// Ext.each(records, function (record) {
// console.log(record);
// });
// console.log(targetStore);
//}
});
},
added listeners to MainPortal.js
var myStore = Ext.create('ExtApplication1.store.PositionsStore');
var gridSummary = Ext.create('Ext.grid.Panel', {
store: myStore,
width: 600,
title: 'my first grid',
columns: [
{
text: 'AcctNum',
dataIndex: 'AcctNum',
width: 100
},
{
text: 'AcctShortCode',
dataIndex: 'AcctShortCode',
flex: 1
},
{
text: 'Exchange',
dataIndex: 'Exchange',
width: 200
}
],
listeners: {
destroy: function () {
debugger;
}
}
});
Ext.define('ExtApplication1.view.main.MainPortal', {
extend: 'Ext.panel.Panel',
xtype: 'mainportal',
alias: 'widget.mainportalAlias',
//id: 'mainportalID',
itemId: 'mainportalID',
html: 'user... this is the main portal window',
autoScroll: true,
bodyPadding: 10,
items: [
gridSummary
],
listeners: {
destroy: function () {
debugger;
}
}
});

ExtJS 5 - Keep scroll position of grid when datastore reloads

Can anyone tell me how I can keep the position of my scroll bar when my datastore reloads? Below is the code I have for the window/grid and refresh code. Everytime refreshActions executes the scroll bar scrolls to the top of the grid:
preserveScrollonRefresh does not work in this scenario
View
Ext.define('Tool.view.ActionView',{
extend: 'Ext.window.Window',
xtype: 'toolactions',
requires:[
'Tool.view.ActionController'
],
controller: 'actions',
viewModel: {},
layout: { type: 'border' },
closeAction: 'hide',
title: 'Actions',
store: 'Task',
width: 1500,
height: 800,
items: [{
id: 'ChangeLog',
xtype: 'grid',
selType: 'rowmodel',
split: true,
title: 'Log',
region: 'south',
width: 600,
height: 300,
bind: {store: '{tasks}'},
columns: {
defaults: {
width: 175
},
items: [
{ text: 'Script Command', dataIndex: 'command_script', flex: 1},
{ text: 'Output', dataIndex: 'command_output', width: 250, flex: 1 },
{ text: 'Status', dataIndex: 'state', width: 250, flex: 1 }]
},
bbar: ['->',{
xtype: 'button',
text: 'Refresh',
listeners: {
click: 'refreshActions'
}
}
]
}]
Refresh Code
refreshActions: function() {
var me = this;
this.currentRecord.tasks().load(function(records, operation, success) {
if(!operation.wasSuccessful()) {
var message = "Failed to load data from server.";
if(operation.hasException())
message = message + " " + operation.getError();
var app = Tool.getApplication();
app.toast(message,'error');
}
else {
me.configureButtons();
me.configureAutoRefresh();
}
});
}
Detect for Auto Refresh
configureAutoRefresh: function() {
var autoRefresh = false;
var maxId = this.getMaximumId(this.currentRecord.tasks());
var maxRecord = this.currentRecord.tasks().getById(maxId);
if(maxRecord.data.state=='1' || maxRecord.data.state=='0') {
autoRefresh = true;
}
if(autoRefresh == true) {
if(this.autoRefreshTask == null) {
var me = this;
var task =
{
run: function() {
me.refreshActions();
return true;
},
interval: 2000 // 2 seconds
};
this.autoRefreshTask = Ext.TaskManager.start(task);
}
}
else if(this.autoRefreshTask != null) {
Ext.TaskManager.stop(this.autoRefreshTask);
this.autoRefreshTask = null;
}
}
As I see it you have 2 options that not necessarily exclude each other:
If a grid row is selected:
Before the store reload get the selected record using getSelection() method and after the action is complete use the ensureVisible( record, [options] ) method to scroll that record into view.
If no row is selected:
Before the store reload get the current scroll position (I assume in your case is X) using the getScrollX() method and after the action is complete use setScrollX(x, [animate]) to get back to the previous scroll position.

ExtJs open a view from the same view

I am opening a view using the following code
var reader = Ext.create('Ext.view.ReaderWindow', {});
reader.show();
Inside the ReaderWindow view on clicking an a tag element,i am opening the same view (using the code above) again but with different content.
Once i close the ReaderWindow which i opened second. I could not able to see the ReaderWindow which i opened first.
My question is how to use the same view twice. In other words how to open the same view from the view itself.
Ext.define('Ext.view.ReaderWindow', {
extend: 'Ext.window.Window',
alias: 'widget.reader',
id: 0,
file_path: '',
file_title: '',
file_type: '',
id: 'reader',
itemId: 'reader',
maxHeight: 800,
maxWidth: 900,
minHeight: 300,
minWidth: 500,
layout: {
type: 'anchor'
},
title: 'File Reader',
modal: true,
initComponent: function() {
var me = this;
Ext.applyIf(me, {
items: [
{
xtype: 'form',
anchor: '100% 100%',
id: 'reader_form',
itemId: 'reader_form',
maxHeight: 800,
maxWidth: 900,
minHeight: 300,
minWidth: 500,
autoScroll: true,
bodyPadding: 10,
items: [
{
xtype: 'displayfield',
anchor: '100%',
id: 'file_contents',
itemId: 'file_contents',
maxWidth: 900,
minWidth: 50,
hideLabel: true,
name: 'file_contents'
}
]
}
],
dockedItems: [
{
xtype: 'toolbar',
anchor: '100% 5%',
dock: 'bottom',
id: 'reader_toolbar',
itemId: 'reader_toolbar',
items: [
{
xtype: 'tbfill'
},
{
xtype: 'button',
handler: function(button, event) {
me.destroy();
},
id: 'close_btn',
itemId: 'close_btn',
text: 'Close',
tooltip: 'Close the file reader window.'
}
]
}
],
listeners: {
beforerender: {
fn: me.reader_windowBeforeRender,
scope: me
}
}
});
me.callParent(arguments);
},
reader_windowBeforeRender: function(component, eOpts) {
this.setTitle(this.file_title + ' for ID ' + this.id);
this.setFormTitle(this.file_path);
Ext.model.FileReaderModel.load(this.id, {
params: {
'file': this.file_path,
'file_type': this.file_type
},
success: function(file_reader) {
var contents_field = Ext.ComponentQuery.query('[name=file_contents]')[0];
var contents = file_reader.get('file_contents');
var pattern = /(\/.*?\.\S*)/gi;
contents = contents.replace(pattern, "<a href='#' class='samplefile'>$1</a>");
contents_field.setValue('<pre>' + contents + '</pre>');
Ext.select('.samplefile').on('click', function() {
var sample_file_path = this.innerHTML;
var Id = this.id;
var reader = Ext.create('Ext.view.ReaderWindow', {
id: Id,
file_path: sample_file_path,
file_title: 'Sample File',
file_type: 'output'
});
reader.show();
});
},
failure: function(file_reader, response) {
}
});
},
setFormTitle: function(file_path) {
var form_panel = Ext.ComponentQuery.query('#reader_form');
form_panel[0].setTitle('File is: ' + file_path);
}
});
One big problem I see is that you are giving some of your components a non-unique id property. When an id is specified, ExtJS uses it as the ID of the underlying DOM element instead of generating a unique one. This is almost certainly not what you want on a reusable component given that IDs need to be unique within the DOM.
Even if you are generating a unique id when you construct the top-level Window object, its child components (reader_form, file_contents, etc) are not getting a unique id.
In other words, when your second window is shown, you now have multiple DOM elements with the same ID and that breaks the DOM. In my ExtJS application, I've yet to find a valid use case for overriding the id property, but that doesn't mean there isn't one. It would most likely be for global scaffolding elements or something where your application guarantees only one instance of a particular component will ever be instantiated.
You can use itemId because that's an ExtJS construct that doesn't get translated into the DOM. It gives you similar features to having an ID on a DOM element, except that it behaves more intuitively in the context of the ExtJS component hierarchy and selector APIs.
My recommendation is to remove the id property from your components and let ExtJS generate unique ones for you and leverage itemId only where you absolutely must have a known identifier on your component.

Resources