Ext 4.1 form panel loadRecord - ext4

I have a grid with actioncolumn. On click of actioncolun it shows a menu with edit and delete items. When i click on Edit it should display a modal-popup window with form panel. The row data should be displayed in fields. I'm able to achieve the above thing by using loadRecord method.
The code i'm using is
actioncolumn.on('click', function (grid, td, rowIndex, eve, e) {
var rec = grid.getStore().getAt(rowIndex);
if (!this.menu) {
this.menu = Ext.create('Ext.menu.Menu', {
width: 100,
height: 70,
plain: true,
floating: true,
items: [{
text: 'Edit',
icon: 'images/Edit.png',
handler: function (a, b, c, d) {
var view = Ext.widget('userwindow');
view.down('baseform').loadRecord(rec);
}
}
}
But the problem is when i'm clicking on edit for second time form panel is displaying the data which is loaded for first time.
Can anybody help
Thanx in advance

I achieved the above by setting the record into a separate variable like
actioncolumn.on('click', function (grid, td, rowIndex, eve, e) {
actioncolumn.rec = grid.getStore().getAt(rowIndex);
if (!this.menu) {
this.menu = Ext.create('Ext.menu.Menu', {
width: 100,
height: 70,
plain: true,
floating: true,
items: [{
text: 'Edit',
icon: 'images/Edit.png',
handler: function (a, b, c, d) {
var view = Ext.widget('userwindow');
view.down('baseform').loadRecord(actioncolumn.rec);
}
}
Regards
Url

Related

Print only the panel content

I'm using ExtJS to show an barcode image. I wanna print that image using the print dialog after do click in a button.
I have a function like this:
function barcode_impr(pkIdGuess){
var win = new Ext.Window({
title: 'Barcode',
layout: 'fit',
autoScroll: true,
y: 120,
width: 300,
height: 300,
modal: true,
closeAction: 'hide',
items:
[{
xtype: 'panel',
//height:'100px',
docked: 'bottom',
html: 'Here goes an image...',
scrollable: true,
renderTo: document.body,
id: 'panel_print',
tools: [{
type: 'print',
handler: function() {
window = Ext.getCmp('panel_print');
window.print();
}
}]
}]
});
win.show();
}
but that show all not only the panel content. What am I doing wrong?
I have made a function doPrint with 2 parameters pnlId (the id of the panel in which your bar code image is placed) and win (the window reference)
We can use this function like below:-
doPrint('panel_print', win);
This function creates an iframe and print the content which we want and then it destroy the iframe.
Working example
Code snippet:-
function doPrint(pnlId, win) {
var pnl = Ext.getCmp(pnlId);
var iFrameId = "printerFrame";
var printFrame = Ext.get(iFrameId);
if (printFrame == null) {
printFrame = Ext.create('Ext.Component', {
id: iFrameId,
autoEl: {
tag: "iframe"
}
});
printFrame.addCls('x-hidden');
win.add(printFrame);
}
var cw = printFrame.el.dom.contentWindow;
// get the contents of the panel and remove hardcoded overflow properties
var markup = pnl.body.dom.innerHTML;
while (markup.indexOf('overflow: auto;') >= 0) {
markup = markup.replace('overflow: auto;', '');
}
var str = Ext.String.format('<html><head>{0}</head><body><img src="resources/images/gabar-logo.gif">{1}</body></html>', '', markup);
// output to the iframe
cw.document.open();
cw.document.write(str);
cw.document.close();
// remove style attrib that has hardcoded height property
// cw.document.getElementsByTagName('DIV')[0].removeAttribute('style');
// print the iframe
cw.print();
// destroy the iframe
Ext.fly(iFrameId).destroy();
};
Hope this will help.

FullCalendar and Flot Resize Conflict

I've successfully integrated both a Flot line graph and an instance of FullCalendar into my site. They are both on separate pages (although the pages are loaded into a div via AJAX).
I've added the Flot Resize plugin and that works perfectly, re-sizing the line graph as expected. However, it seems to cause an error when resizing the calendar.
Even if I load the calendar page first, when I resize the window I get this error in the console (also, the calendar does not resize correctly):
TypeError: 'undefined' is not an object (evaluating 'r.w=o!==c?o:q.width()')
I was struggling to work out where the error was coming from, so I removed the link to the Flot Resize JS and tried again. Of course the line graph does not resize, but when resizing the calendar, it works correctly.
The div containers for the two elements have different names and the resize function is called from within the function to draw the line graph (as required).
I have tried moving the link to the Flot Resize plugin into different places (i.e. above/below the fullCalendar JS, into the template which holds the graph), but all to no avail.
Does anyone have any idea where the conflict might be and how I might solve it??
Thanks very much!
EDIT: It seems that the error is also triggered when loading the line graph (flot) page AFTER the fullcalendar page even without resizing the window.... Now I am very confused!
EDIT 2: The code which draws the line graph. The function is called on pageload and recieves the data from JSON pulled off the server. When the graph is loaded, I still get the error about shutdown() being undefined.
function plotLineGraph(theData){
var myData = theData['data'];
var myEvents = theData['events'];
var myDates = theData['dates'];
var events = new Array();
for (var i=0; i<myEvents.length; i++) {
events.push(
{
min: myEvents[i][0],
max: myEvents[i][1],
eventType: "Calendar Entry",
title: myEvents[i][2],
description: myEvents[i][3]
}
);
}
function showTooltip(x, y, contents) {
$('<div id="tooltip">' + contents + '</div>').css( {
position: 'absolute',
display: 'none',
top: y + 5,
left: x + 5,
border: '1px solid #fdd',
padding: '2px',
'background-color': 'black',
opacity: 0.80
}).appendTo("body").fadeIn(200);
}
var previousPoint = null;
$("#placeholder").bind("plothover", function (event, pos, item) {
$("#x").text(pos.x.toFixed(2));
$("#y").text(pos.y.toFixed(2));
if ($("#enableTooltip:checked").length == 0) {
if (item) {
if (previousPoint != item.dataIndex) {
previousPoint = item.dataIndex;
$("#tooltip").remove();
var x = item.datapoint[0].toFixed(2),
y = item.datapoint[1].toFixed(2);
if(item.series.label != null){
showTooltip(item.pageX, item.pageY,
item.series.label + " of " + y);
}
}
}
else {
$("#tooltip").remove();
previousPoint = null;
}
}
});
var d1 = [
myData[0], myData[1], myData[2], myData[3], myData[4],
myData[5], myData[6], myData[7], myData[8], myData[9],
myData[10], myData[11], myData[12], myData[13], myData[14],
myData[15], myData[16], myData[17], myData[18], myData[19],
myData[20], myData[21], myData[22], myData[23], myData[24],
myData[25], myData[26], myData[27], myData[28], myData[29]
];
var markings = [
{ color: '#FFBDC1', yaxis: { from: 0, to: 2 } },
{ color: '#F2E2C7', yaxis: { from: 2, to: 3.5 } },
{ color: '#B6F2B7', yaxis: { from: 3.5, to: 5 } }
];
$.plot($("#placeholder"), [
{label: "Average Daily Rating", data: d1, color: "black"}
], {
events: {
data: events,
},
series: {
lines: { show: true },
points: { show: true }
},
legend: { show: true, container: '#legend-holder' },
xaxis: {
ticks:[
myDates[0], myDates[1], myDates[2], myDates[3], myDates[4],
myDates[5], myDates[6], myDates[7], myDates[8], myDates[9],
myDates[10], myDates[11], myDates[12], myDates[13], myDates[14],
myDates[15], myDates[16], myDates[17], myDates[18], myDates[19],
myDates[20], myDates[21], myDates[22], myDates[23], myDates[24],
myDates[25], myDates[26], myDates[27], myDates[28], myDates[29]
],
},
yaxis: {
ticks: 5,
min: 0,
max: 5
},
grid: {
backgroundColor: { colors: ["#fff", "#eee"] },
hoverable: true,
clickable: true,
markings: markings
},
selection: {
color: 'white',
mode: 'x'
},
});
$('#placeholder').resize();
$('#placeholder').shutdown();
}
EDIT 3:
The calendar is called like this:
function showCalendar() {
var date = new Date();
var d = date.getDate();
var m = date.getMonth();
var y = date.getFullYear();
$('#fullcalendar').fullCalendar({
header: {
left: 'prev',
center: 'title',
right: 'next'
},
clickable: true,
firstDay: 1,
eventSources: [
{
url: '/populate-calendar/{{theProductUuid}}/',
color: 'black',
data: {
text: 'text'
}
}
],
eventClick: function(calEvent, jsEvent, view) {
var startDate = $.fullCalendar.formatDate(calEvent.start, 'yyyy-MM-dd');
var endDate = $.fullCalendar.formatDate(calEvent.end, 'yyyy-MM-dd');
var eventId = calEvent.uuid;
$('#modal-event-title').text(calEvent.title);
$('#edit-event-name').val(calEvent.title);
$('#edit-start-date').val(startDate);
$('#edit-end-date').val(endDate);
$('#edit-event-text').val(calEvent.text);
$('#edit-event-btn').attr('data-uuid', eventId);
$('#modal-edit-event').on('click', '#delete-btn', function(){
deleteCalendarEvent(eventId);
});
$('#modal-edit-event').modal();
},
});
}
The AJAX to load the page containing the flot chart:
function loadDetailedReports(uuid){
$('#product-content').fadeOut('slow', function(){
$('#product-content').empty();
$('#whole-product-sub-nav .active').removeClass('active');
$('#detailed-reports-content').load('/detailed-reports/' + uuid + '/', function(){
$('#detailed-reports-btn').addClass('active');
$('#detailed-reports-content').fadeIn('slow', function(){
if (authorized){
setLocationHash('loadDetailedReports&' + uuid);
getChartData(uuid);
} else {
setLocationHash('');
}
});
});
});
}
And the AJAX to load the page containing the calendar:
function loadCalendar(uuid){
$('#detailed-reports-content').empty().hide();
$('#product-content').fadeOut('slow', function(){
$('#whole-product-sub-nav .active').removeClass('active');
$('#product-content').load('/calendar/' + uuid + '/', function(){
$('#calendar-btn').addClass('active');
$('#product-content').fadeIn('slow', function(){
if (authorized){
setLocationHash('loadCalendar&' + uuid);
} else {
setLocationHash('');
}
showCalendar();
});
});
});
}
The calls to .resize and .shutdown are there because I was under the impression that they are necessary to achieve the resizing function and in response to your earlier comment regarding shutdown...... They're quite possibly n00b errors........?!?!
It looks like this is triggering on line 198 of jquery-resize:
data.w = w !== undefined ? w : elem.width();
This sounds like a race-condition stemming from the way you load different content into the same div. Flot binds the resize event to the chart div, and only un-binds it if the plot is destroyed cleanly.
EDIT: Looking at your code, my first suggestion would be to get rid of the resize and shutdown calls at the end of plotLineGraph. The resize plugin doesn't require any setup; it hooks into Flot to attach automatically to any new plot. So your call to resize is actually to jQuery's resize event trigger, which may be what's causing the error.
EDIT #2: I'm still not clear on your structure, but to generalize: anywhere that you might be getting rid of #placeholder (via emptying its parent or anything like that) you should first call shutdown on the plot object. If you aren't keeping a reference to it, you can do it like this: $("#placeholder").data("plot").shutdown(); but then have to account for the fact that it's undefined prior to the creation of your first plot.
If that still doesn't work, I'd need to see a live (simplified) example to make any further suggestions.

how can i show an iconCls based icon using actioncolumn in extjs 4 with 3 decisions?

I'm trying to show an icon depending on the value, if the value is 0 then it won't show any icon, when is 1 or something bigger than 0 it will show an icon with a handler that supports click event, that event will show another icon, the icon is not an image is an styled square using iconCls parameter in actioncolumn.
So my main problem right now is that I cannot make the actioncolumn to stop showing the icon if the value is 0, it just shows the two squares one over the other and is a complete mess. I tried different approach using renderer and still the result is weird. So this is my code so far. This exercise is the same as here, but with an extra decision.
http://www.learnsomethings.com/2011/09/25/the-new-extjs4-xtype-actioncolumn-in-a-nutshell/
`this.columns = [
{header: 'Estado', dataIndex:'icon', renderer:this.renderIcon, width:35},
{
header:'Geo',
width:35,
xtype:'actioncolumn',
items: [{
iconCls:'showGeofence',
tooltip:'Geocerca Visible.',
handler: function(grid, rowIndex, colIndex) {
var rec = grid.getStore().getAt(rowIndex);
grid.getStore().getAt(rowIndex).set('geo', 0);
grid.getSelectionModel().select(rowIndex);
},
getClass: function(value,metadata,record){
var closed = record.get('geo');
if (closed == 0) {
return 'x-hide-display';
} else {
return 'x-grid-center-icon';
}
}
},{
iconCls:'hideGeofence',
tooltip:'Geocerca no Visible.',
handler: function(grid, rowIndex, colIndex) {
var rec = grid.getStore().getAt(rowIndex);
grid.getStore().getAt(rowIndex).set('geo', 1);
grid.getSelectionModel().select(rowIndex);
},
getClass: function(value,metadata,record){
var closed = record.get('geo');
if (closed == 1) {
return 'x-hide-display';
} else {
return 'x-grid-center-icon';
}
}
},{
iconCls:'noGeofence',
tooltip:'Geocerca no Configurada.',
getClass: function(value,metadata,record){
var closed = record.get('geo');
if(closed !== undefined && typeof(closed)==number){
return 'x-hide-display';
}else{
return 'x-grid-center-icon';
}
}
}]
},
{header: 'Descripcion', dataIndex:'descripcion',flex:1},
{header: 'id', dataIndex:'id', hidden:true}
];`
Based on 3 decisions I had made this awful workaround, it works but, honestly is horrible... The trick is just play with the values the handler set up after a click behaviour. So based on that fact, I did this. I hope maybe this might by helpful to anybody in the future, or maybe it could work as an example of horrible programming for future generations.
cheers.
`this.columns = [
{header: 'Estado', dataIndex:'icon', renderer:this.renderIcon, width:35},
{
header:'Geo',
width:35,
xtype:'actioncolumn',
items: [{
iconCls:'hideGeofence',
tooltip:'Geocerca Visible.',
action:'hidegeofence',
handler: function(grid, rowIndex, colIndex) {
var rec = grid.getStore().getAt(rowIndex);
Ext.example.msg("Informacion","Mostrando Geocerca.");
grid.getStore().getAt(rowIndex).set('id_geocerca','a');
grid.getSelectionModel().select(rowIndex);
},
getClass: function(value,metadata,record){
var closed = record.get('id_geocerca');
if(closed>0){
return 'x-grid-center-icon';
}else{
return 'x-hide-display';
}
}
},{
iconCls:'showGeofence',
tooltip:'Geocerca Visible.',
handler: function(grid, rowIndex, colIndex) {
var rec = grid.getStore().getAt(rowIndex);
Ext.example.msg("Informacion","Ocultando Geocerca.");
grid.getStore().getAt(rowIndex).set('id_geocerca',1);
grid.getSelectionModel().select(rowIndex);
},
getClass: function(value,metadata,record){
var closed = record.get('id_geocerca');
if(closed=='a'){
return 'x-grid-center-icon';
}
if(closed>0 || closed==0){
return 'x-hide-display';
}
}
}]
},
{header: 'Descripcion', dataIndex:'descripcion',flex:1},
{header: 'id', dataIndex:'id', hidden:true}
];`
When you also specify an icon using getClass the actioncolumn handler function doesn't get called on click. I have an empty icon declared in the css.
.x-action-col-icon{
width: 30px;
vertical-align: bottom;
}
.../ Add you remaining css for x-grid-center-icon and x-hide-display
in actioncolumn definition add
icon: '',

stopEvent() not working on drag event

I have a container that I made draggable with this in its config :
draggable: {
direction: 'horizontal',
constraint: {
min: { x: 0, y: 0 },
max: { x: parseInt(screen.width-57), y: 0 }
},
listeners: {
dragstart: function(panel, e, offset){
},
drag: function(panel, e, offset){
},
dragend: function(panel, e, offset){
},
scope: this
},
}
It's work fine. Now I would like to prevent the user from dragging the panel when the drag event is being fired. It might sound stupid but, this is to prevent the user to drag the panel directly, he would have to put his finger on the toolbar to drag the panel.
I've already tried a few things like
return false;
e.stopEvent();
e.stopPropagation();
e.preventDefault();
But none of them worked. Does anyone have an idea why ?
I finally changed the dragstart event to
dragstart: {
fn: function(){
},
order: 'before'
},
and return false; worked fine...

ExtJS How to add a click event to Pie Chart pieces

I have created a Pie chart using the Pie chart example in sencha ExtJS website , I wanted to add a click event to the each Pie slice so that i get handle to the contextual data on that slice. I was able to add a click listener to the Pie but not sure how to get the data on the slice.
Below is the ExtJS code.
Ext.onReady(function(){
var store = Ext.create('Ext.data.JsonStore', {
fields: ['name', 'data1', 'data2', 'data3', 'data4', 'data5'],
data: [{
'name': 'January',
'data1': 10
}, {
'name': 'February',
'data1': 7
}, {
'name': 'March',
'data1': 5
}, {
'name': 'April',
'data1': 2
}, {
'name': 'May',
'data1': 27
}]
});
Ext.create('Ext.chart.Chart', {
renderTo: Ext.getBody(),
width: 800,
height: 600,
animate: true,
store: store,
theme: 'Base:gradients',
legend: { // Pie Chart Legend Position
position: 'right'
},
series: [{
type: 'pie',
field: 'data1',
showInLegend: true,
tips: {
trackMouse: true,
width: 140,
height: 28,
renderer: function(storeItem, item){
//calculate and display percentage on hover
var total = 0;
store.each(function(rec){
total += rec.get('data1');
});
this.setTitle(storeItem.get('name') + ': ' + Math.round(storeItem.get('data1') / total * 100) + '%');
}
},
highlight: {
segment: {
margin: 5
}
},
label: {
field: 'name',
display: 'rotate',
contrast: true,
font: '18px Arial'
},
listeners: {//This Doesnt Work :(
itemclick: function(o){
alert('clicked at : ' + o);
}
}
}],
listeners: { //This Event handler works but I am not sure how to figure how which slice i have clicked ..................................
click: {
element: store, //bind to the underlying el property on the panel
fn: function(o, a){
alert('clicked' + o + a + this);
}
}
}
});
});
Kindly help.
Regards,
Lalit
Here is how you get data of the clicked slice. The series class supports listeners via the Observable syntax and they are:
itemmouseup When the user interacts with a marker.
itemmousedown When the user interacts with a marker.
itemmousemove When the user iteracts with a marker.
afterrender Will be triggered when the animation ends or when the series has been rendered completely.
I will make use of the itemmousedown event to capture the clicked slice. Here is my listener method:
series: [{
.
.
.
listeners:{
itemmousedown : function(obj) {
alert(obj.storeItem.data['name'] + ' &' + obj.storeItem.data['data1']);
}
}
.
}]
Note that I have placed my listener inside the series and not the chart! Now, the obj variable holds lot of information. For each series, the property to get data will differ. So, you will have to carefully inspect the object using firebug or some other developer tool.
Now, in case of Piecharts, you can get the slice information by using the obj:
obj.storeItem.data['your-series-variable-name']
Here is the obj from firebug..
I'm using a more selective approach, because I needed to add some custom logic in order to implement drag-and-drop for our charts. So after the chart definition I just add the following:
// Add drag-and-drop listeners to the sprites
var surface = chart.surface;
var items = surface.items.items;
for (var i = 0, ln = items.length; i < ln; i++) {
var sprite = items[i];
if (sprite.type != "circle") { continue; } // only add listeners to circles
// Additional funky checks for the draggable sprites
sprite.on("mousedown", onSpriteMouseDown, sprite); // mouse down ONLY for sprites
}
surface.on("mousemove", onSurfaceMouseMove, surface); // mouse move for the entire surface
surface.on("mouseup", onSurfaceMouseUp, surface);
Cheers!
Frank