Related
The search button works on the first click, but once it is closed either by clicking the X (close button) or by running a search (setting to close after search) it does not open, there are also no errors in the console so I am unable to determine what is wrong and how to fix it.
var previouslySelectedRow = null;
var rowIsSelected = null;
var previousRowIsSelected = null;
var currentRowId;
var currentCount;
var cancelEditing = function(theGrid) {
var lrid;
if (typeof previouslySelectedRow !== "undefined") {
// cancel editing of the previous selected row if it was in editing state.
// jqGrid hold intern savedRow array inside of jqGrid object,
// so it is safe to call restoreRow method with any id parameter
// if jqGrid not in editing state
theGrid.jqGrid('restoreRow', previouslySelectedRow);
// now we need to restore the icons in the formatter:"actions"
lrid = $.jgrid.jqID(previouslySelectedRow);
$("tr#" + lrid + " div.ui-inline-edit").show();
$("tr#" + lrid + " div.ui-inline-save, " + "tr#" + lrid + " div.ui-inline-cancel").hide();
}
};
var parsedResult = JSON.parse(DecodeAscii(result));
ShowDebugNotification("DEBUG INFO(" + ajaxCall + "): <br />" + result, false);
$("#productsTable").jqGrid({
data: parsedResult,
datatype: "local",
loadonce: true,
height: 'auto',
marginLeft: 'auto',
colNames: [
'Product Id', 'Add', 'Product Name', 'Product Code', 'Customer Price'
],
colModel: [
{ name: 'Id', width: 0, hidden:true },
{ name: "actions", template: "actions", width: 50, formatoptions:{
delbutton: false,
editbutton: false
} },
{ name: 'Name', index: 'Name', width: 550, search: true, searchoptions:{sopt:['eq','bw','bn','cn','nc','ew','en']} },
{ name: 'ProductCode', index: 'ProductCode', width: 150, search: true, searchoptions:{sopt:['eq','bw','bn','cn','nc','ew','en']} },
{ name: 'Price', index: 'Price', width: 100, search: false, formatter: 'currency', formatoptions:{decimalSeparator:".", thousandsSeparator: ",", decimalPlaces: 2, prefix: "$"}}
],
rowNum: 15,
rowList: [5, 10, 15, 20],
pager: true,
gridView: true,
viewrecords: true,
iconSet: "jQueryUI",
sortname: 'Name',
sortorder: 'asc',
inlineEditing: { keys: false },
actionsNavOptions: {
addToCarticon: "ui-icon-cart",
addToCarttitle: "Add item to the cart",
custom: [
{ action: "addToCart", position: "first", onClick: function (options) {
var rowData = $('#productsTable').getRowData(options.rowid);
var cartButton = $(".ui-icon", "#jAddToCartButton_"+options.rowid);
if(cartButton.hasClass("ui-icon-cancel")){
cart.shift(rowData);
cartButton.removeClass("ui-icon-cancel");
cartButton.addClass("ui-icon-cart");
}
else if(cartButton.hasClass("ui-icon-cart")){
cart.push(rowData);
cartButton.removeClass("ui-icon-cart");
cartButton.addClass("ui-icon-cancel");
}
}
}]
},
loadComplete: function() {
$("#add-product-dialog-loading-message").hide();
$(".spinner").hide();
$("#add-product-dialog-form").dialog("open");
//for each object in cart
//if prodcut ID matches product Id in product
//grid then set button to a cancel icon
if(cart.length !== 0){
var cartIds = [];
var jsonCart = JSON.stringify(cart);
var parsedJsonCart = JSON.parse(jsonCart);
var productsInCart = $.grep(parsedJsonCart, function(el, i){
cartIds.push(el.Id);
});
var currentRows = $('#productsTable').getRowData();
var shownProductsThatAreInCart = $.grep(currentRows, function (el, i) {
return $.inArray(el.Id, cartIds) !== -1;
});
if(shownProductsThatAreInCart.length > 0){
var rowIds = $(this).jqGrid('getDataIDs');
$.each(rowIds, function(k, v) {
rowData = $('#productsTable').getRowData(v);
if($.inArray(rowData['Id'], cartIds) !== -1){
alert("Matched Product:\nRowData['id'] = " + rowData['Id'] + "\nto\nProduct in cart: " + cartIds.Id);
$(".ui-icon", "#jAddToCartButton_"+v).removeClass("ui-icon-cart");
$(".ui-icon", "#jAddToCartButton_"+v).addClass("ui-icon-cancel");
}
});
}
}
},
gridComplete: function() {
}
});
$("#productsTable").jqGrid("navGrid", {edit:false,add:false,del:false},
{},// use default settings for edit
{},// use default settings for add
{},// delete instead that del:false we need this
{multipleSearch:false,overlay:false,ignoreCase:true,closeAfterSearch:true,closeOnEscape:true,showQuery:true});
I don't think its a bug as I have seen many demos demonstrating how it is supposed to work, I am guessing I have a mis-configuration, please have a look over my code and help determine the issue.
One thing to keep in mind is I am getting the data to load the grid via an ajax call that returns json, all manipulation is done on the client, there is no posting data back to server at all.
Thank you!
The main problem is the combination of Searching options which you use:
{
multipleSearch: false, // it's default and can be removed
overlay: false, // !!! the option make the problem
ignoreCase: true, // it's not exist at all
closeAfterSearch: true,
closeOnEscape: true,
showQuery: true
}
The usage of the option overlay: false is bad because it makes another option toTop: true not working and the Searching dialog will be placed as the children of jQuery UI Dialog. If you remove the option then one can work with the Searching Dialog more easy and the second problem (a bug in calculation of position of jqGrid Searching Dialog) will not exist. Look at the modified demo:
https://jsfiddle.net/OlegKi/su7mf5k9/3/
UPDATED: It seems one have the problem in creating modal jqGrid dialog inside of modal jQuery UI dialog. The problem could be solved by removing modal: true option from the outer jQuery UI dialog. See https://jsfiddle.net/OlegKi/su7mf5k9/3/
In general one could create hybrid solution which changes the type of jQuery UI dialog from modal to non-modal dynamically, but it could be tricky https://jsfiddle.net/OlegKi/su7mf5k9/5/
I've just started working with Sencha Touch over the past couple days and I've run into a few questions. The main one is, when working with anything that doesn't regularly have user click interaction (titlebar, html text, etc for some random examples), is it possible to click on things like this and get a panel to appear.
I know that with buttons and other things, you have a tap, itemtap, etc, but I'm not sure about instances like this. Any help would be appreciated with examples.
Yes you can. Check out my blog post here: http://www.senchahackers.com/touch/multiple-tap-listeners-one-xtemplate/ that explains exactly how to do that.
Basically you can listen for a tap event on any element, as long as you add it to the list of 'delegates'
In your view:
listeners: {
tap: {
element: 'element',
delegate: '.app-box, .doc-box, .bubble-holder',
fn: function(e){
var url = e.target.name,
divClassName = e.delegatedTarget.className,
appbox = "app-box",
docbox = "doc-box",
bubble = "bubble-holder";
console.log(divClassName);
switch(divClassName){
case docbox :
//lets say you have an element '.doc-box' that you want to click and show the panel
// show the panel, which is a separate file, shown below
var profileController = YourApp.getController('YourController');
//call the showProfilePanelPopup() method in your controller, passing in this as the element that shows it
profileController.showProfilePanelPopup(this);
break;
case appbox :
alert(appbox);
break;
case bubble :
alert(bubble);
break;
}
}
}
}
Then in your controller:
extend: 'Ext.app.Controller',
config: {
refs: {
profilePanelPopup: {
autoCreate: true,
selector: '#profilePanelPopup',
xtype: 'profilePanelPopup'
}
}
},
showProfilePanelPopup: function(btn, action, values) {
var me = this;
var popup = me.getProfilePanelPopup();
popup.showBy(btn);
popup.on('hide', function () {
popup.destroy();
}, this);
}
Assuming you some Panel in your views directory like this:
Ext.define('App.view.ProfileNowPop', {
extend : 'Ext.Panel',
alias: 'widget.profileNowPop',
xtype: 'profilePanelPopup',
config: {
height: (Ext.os.deviceType != "Desktop") ? "35%" : 253,
cls:'profilePop',
left: '1%',
padding: 0,
top: '1%',
width: (Ext.os.deviceType != "Desktop") ? '40%' : '36%',
hideOnMaskTap: true,
modal: {
cls:'opaquemask'
},
scrollable: false,
store: 'ProfilePopStore',
model: 'App.model.ProfilePopModel',
items:[
{
xtype: 'fieldset',
items: [
{
xtype: 'textfield',
id: 'gradePopField0',
cls: 'gradePopField',
style: 'background: #f7f7f5',
listeners: {
initialize: function(ele, eOpts) {
this.setReadOnly(true);
}
}
}
]
}
]
},
initialize: function() {
this.callParent(arguments);
}
});
I was wondering if it's possible to not to allow the user to close the item again when it's open, meaning to let it close only when i click on another item in the accordion.
hope it's clear enough.
I'm adding the code:
Ext.define('application.view.SystemHealth', {
extend: 'Ext.Container',
alias: 'widget.globalSynchronization',
requires: ['infra.view.views.BoxHeader',
'application.view.SystemStatusHeader',
'application.model.SystemHealth',
'application.store.SystemHealth',
'infra.utils.pvs.SyncJobRunningStep',
'application.view.CostCalculation',
'application.view.SystemStatusHeader',
'application.view.DataCollector',
'application.view.PublicCloudConnection',
'Ext.layout.container.Accordion'
],
layout:{
type:'vbox',
align:'stretch'
},
header: false,
cls: ['global-synchronization'],
syncJobStatus: null,
initComponent: function() {
var me = this;
me.store = Ext.create('itfm.application.store.SystemHealth');
me.store.load({scope: me, callback: me.onLoadDone});
Ext.apply(me, {
items: [
{
xtype: 'boxHeader',
width: '100%',
title: itfm.application.T.GlobalSynchronizationTitle
},
{
xtype: 'label',
width: '90%',
html: itfm.application.T.GlobalSynchronizationDescription,
margin: "0 0 30 10"
}
]
});
me.callParent(arguments);
},
onLoadDone: function(records, operation, success){
var me =this;
var accordionItemsMargin = '0 0 30 0';
me.accordion = Ext.create('Ext.panel.Panel', {
margin: "0 0 30 10",
defaults:[{
layout:'fit',
height:'100%',
width:'100%'
}] ,
layout: {
type: 'accordion',
titleCollapse: false,
animate: true,
activeOnTop: true,
fill : true,
collapseFirst :true
},
items: [
{
height: 180,
xtype: 'dataCollector',
autoScroll:true,
margins: accordionItemsMargin,
store: records[0].dcModule()
}
,
{
xtype: 'costCalculation',
margins: accordionItemsMargin,
store: records[0].ccModule()
},
{
xtype: 'publicCloudConnection',
margins: accordionItemsMargin,
store: records[0].pcModule()
}
]
});
me.add( me.accordion);
}
});
thanks for the help
What you want is that nothing happens when the user click on the currently expanded panel, instead of collapsing and expanding the next one, is that right?
Unfortunately, there's no built-in option for that... If you really want it, you'll have to override Ext.layout.container.Accordion and implement it yourself.
Edit
In fact most of the collapsing/expanding code lies in the Ext.panel.Panel class.
This simple override seems to be enough to do what you want. Apparently this method is used only for collapse listeners, so it shouldn't have any adverse effect (unless the method is also used somewhere in your code...).
Ext.define('Ext.ux.Panel.JQueryStyleAccordion', {
override: 'Ext.panel.Panel'
,toggleCollapse: function() {
if (this.collapsed || this.floatedFromCollapse) {
this.callParent();
}
}
});
See this fiddle.
I was able to override the accordion with the following
Ext.define('itfm.application.view.SystemHealthAccordion', {
extend: 'Ext.layout.container.Accordion',
alias: ['layout.systemHealthAccordion'] ,
constructor: function() {
var me = this;
me.callParent(arguments);
},
onComponentExpand: function(comp) {
var me = this;
me.callParent(arguments);
var button = comp.down('tool');
button.setDisabled(true);
},
onComponentCollapse: function(comp) {
var me = this;
me.callParent(arguments);
var button = comp.down('tool');
button.setDisabled(false);
}
});
inside the class of the first item of the accordion, there is a need to do the following:
me.on('boxready', me.disableTools);
},
// disable the click on the item in case it's open
disableTools: function(){
var me = this;
var button = me.getHeader().down('tool');
button.setDisabled(true);
}
so when the first item is open it will have the same behaviour
I want to show message box when user click (X) button of ext window, and on 'ok' button of message box window will close. I wrote the code but it closes window first than show message box. Here is the code:
var assignReportFlag = 0;
var assignReportLoader = function(title,url){
var panel = new Ext.FormPanel({
id: 'arptLoader',
height: 485,
border: false,
layout: 'fit',
autoScroll: true,
method:'GET',
waitMsg: 'Retrieving form data',
waitTitle: 'Loading...',
autoLoad: {url: url,scripts: true}
});
var cqok = new Ext.Button({
text:'OK',
id:'1',
handler: function(){
if(assignReportFlag == 1){
assignReportFlag = 0;
Ext.MessageBox.alert('Status', 'Changes has been saved successfully',showResult);
}else{
assignReportWindow.close();
}
}
});
var assignReportWindow = new Ext.Window({
layout:'fit',
title: title,
height:Ext.getBody().getViewSize().height - 60,
width:Ext.getBody().getViewSize().width-20,
closable: true,
modal:true,
resizable: false,
autoScroll:true,
plain: true,
border: false,
items: [panel],
buttons: [cqok],
listeners:{
beforeclose:function(){
if(assignReportFlag == 1){
assignReportFlag = 0;
Ext.MessageBox.alert('Status', 'Changes has been saved successfully',showResult);
}else{
assignReportWindow.destroy();
}
}
}
});
function showResult(btn){
assignReportWindow.destroy();
};
assignReportWindow.show();
};
Thanks
In your beforeclose listener return false to stop the close event being fired.
This works fine for me.Have a look
http://jsfiddle.net/DrjTS/266/
var cqok = new Ext.Button({
text:'OK',
id:'1',
handler: function(){
Ext.MessageBox.alert('Status', 'Changes has been saved successfully',showResult);
}
});
Ext.create('Ext.panel.Panel', {
title: 'Hello',
width: 200,
renderTo: Ext.getBody(),
items:[
{
xtype:'button',
text:'SUBMIT',
handler:function(thisobj)
{
Ext.create('Ext.window.Window', {
id:'W',
height: 200,
width: 400,
layout: 'fit',
buttons: [cqok],
listeners:{
beforeclose:function(){
Ext.MessageBox.alert('Status', 'Changes has been saved');
}
}
}).show();
}
}
]
});
function showResult(btn){
Ext.getCmp('W').destroy();
};
I'm new in ExtJS and I'm trying to display a window with a combo, a cancel and an OK button but the combo does not seem to be working properly: It's not showing the label and when I click the picker (or the trigger) it does not show the list.
I need the combo to either accept free text and selected values but I don't know what I'm doing wrong. I went over Sencha api and forums but I can't work this out.
I hope you guys have a solution for this. Thanks and sorry if my English is not good enough.
function new_filter()
{
var ds_filter2 = new Ext.data.JsonStore({
url: 'forms-combobox-data-filters.php?user='+user_id,
fields: ['id', 'name'],
autoLoad: true/*,
totalProperty: "results"*/
});
var dlg = new Ext.Window(
{
title: 'Save Current Settings as a Filter',
id: 'frmFilter',
width: 350,
y: 200,
height: 120,
minWidth: 350,
minHeight: 100,
iconCls: 'save',
bodyStyle:'padding:0px 0px 0px 0px; background-color:#F5F5F5;',
modal: true,
resizable: false,
maximizable: false,
draggable:false,
closable: true,
closeAction: 'close',
hideMode: "offsets",
constrainHeader: true,
//autoLoad: { url : 'filter_form2.php', scripts: true},
keys: [
{ key: [Ext.EventObject.ENTER], handler: function() {
create_new_filter();
}
},
{ key: [Ext.EventObject.ESCAPE], handler: function() {
dlg.close();
}
}],
buttons:[
{
text : 'OK',
handler: function()
{
var selectedValue = Ext.getCmp('combo-new-filter').value; //selectedValue => Nombre
var rec = ds_filter2.getById(selectedValue); //rec => ID
//alert('rec: '+rec+'\nselected value: '+selectedValue);
if (rec == undefined ) //si el valor seleccionado no se encuentra en combo
{
create_new_filter(selectedValue);
dlg.close();
}
else
{
//alertar con el message box si se desea sobre escrbir el filtro
//ok---> grabar
//cancel--->cancelar
var selected_text = rec.get('name');
var id = rec.get('id');
//alert("selected text: "+selected_text);
Ext.MessageBox.confirm('Confirm','Are you sure you want to overwrite this filter "'+selected_text+'"?', function(btn)
{
if (btn=='yes')
{
var url = 'deleteFilter.php?filter='+id;
var mnmxmlhttp = Array ();
mnmxmlhttp = new myXMLHttpRequest ();
if (mnmxmlhttp)
{
mnmxmlhttp.open ("POST", url, true);
mnmxmlhttp.setRequestHeader ('Content-Type', 'application/x-www-form-urlencoded');
mnmxmlhttp.send ("");
mnmxmlhttp.onreadystatechange = function ()
{
if (mnmxmlhttp.readyState == 4)
{
create_new_filter(selected_text);
}
}
}
}
});
}
}
},
{
text : 'Cancel',
handler: function() {
dlg.close();
}
}
],
items:[
/*{
xtype: 'label',
forId: 'myFieldId',
text: 'Name of saved filter:',
},*/
{
id:'combo-new-filter',
labelAlign: 'left',
fieldLabel: 'Filter Name:',
xtype: 'combo',
store: ds_filter2,
//queryMode: 'local',
displayField:'name',
valueField: 'id',
//editable: true,
x: 110,
y: 20,
listeners: {
/*beforerender: function(combo){
combo.setValue("Select saved filter to apply");
},
select:{fn:function(combo, value) {
if (combo.getValue()>0){onSelectFilter(combo.getValue());}
}
}*/
}
}
]
});
dlg.show();
}
Your window needs to have the layout: 'form' configuration. In order to display fields, combos, etc, the layout that contains them needs to be a form one.