I have a problem with a selection in OnDemandGrid( dojo 1.12.1) and I need some help.
A part of my grid is hidden on creation and this makes the selection 'single' works weird, the selection is active only on visible part of the content. While I scroll I have no more the highlight on my row img1.
However if I apply a sort on a column, the content is refreshed and the whole row becomes selectable.
The example on this page works for EnhancedGrid in selectionMode: 'single' without bugs on a hidden part of a content after loading.
https://dojotoolkit.org/reference-guide/1.10/dojox/grid/EnhancedGrid/plugins/Selector.html, any ideas how to acheve it?
What could I do while creating OnDemandGrid to resolve the problem? I've tried to put a css parameter box-sizing: border-box, but it didn't help me.
There are some simular issues for enchancedgrid, but the solition isn't good for me, maybe it's because I'm using the OnDemandGrid (
dojo EnchancedGrid items do not select programmatically in invisible part of the view)
require([
...
'dojo/store/Memory',
'dgrid/OnDemandGrid',
'dgrid/Selection',
'dgrid/extensions/ColumnResizer',
'dgrid/extensions/DijitRegistry'
], function (Memory, OnDemandGrid, Selection, ColumnResizer, DijitRegistry ) {
var columNs = {First_Name: {label: 'First Name'},
Last_Name: {label: 'Last Name'},
hello: {label: 'hello'},
age: {label: 'age'},
size: {label: 'size'},
name: {label: 'name'},
code: {label: 'code'},
id: {label: 'id'},
mdp: {label: 'mdp'},
username: {label: 'username'},
grid: {label: 'grid'}
};
var store = new Memory({ data: createData() });
var CustomGrid = declare([OnDemandGrid, Selection, ColumnResizer, DijitRegistry]);
var grid = new CustomGrid({
selectionMode: 'single',
cellNavigation: false,
store: store,
columns: columNs
}, 'grid');
grid.startup();
function createData() {
var data = [];
var column;
var i;
var item;
for (i = 0; i < 50; i++) {
item = {};
for (column in { First_Name: 1, Last_Name: 1, hello: 1, age: 1, size: 1, name: 1, code: 1, id: 1, mdp: 1, username: 1, grid: 1 }) {
item.id = i;
item[column] = column + '_' + (i + 1);
}
data.push(item);
}
return data;
}
});
//css
.dgrid {
height: 25em !important;
width: 100%;
}
.dgrid .dgrid-scroller {
margin-top: 24px !important;
}
.dgrid-cell {
width: 70px !important;
}
.dgrid-column-set-scroller {
display: inline-block;
overflow-x: auto;
overflow-y: hidden;
}
I could not reproduce your problem. See on the fiddle here.
One difference in that I replaced dojo/store/Memory, which was giving me an error (if you don't get this error maybe you are using a dgrid version older that 0.4 ?), with dstore/Memory.
Then the fiddle is using dojo 1.12.2 (should make no difference with 1.12.1), and dgrid / dstore 1.1.0 (that could explain the difference if you are using a significantly older version). It also uses dijit's claro.css & dgrid's dgrid.css. See below (extracted from the jsfiddle) the part of your source code that I modified:
require({
packages: [
{
name: 'dgrid',
location: '//cdn.rawgit.com/SitePen/dgrid/v1.1.0'
},
{
name: 'dstore',
location: '//cdn.rawgit.com/SitePen/dstore/v1.1.0'
}
]
},[
"dojo/_base/declare",
'dstore/Memory',
'dgrid/OnDemandGrid',
'dgrid/Selection',
'dgrid/extensions/ColumnResizer',
'dgrid/extensions/DijitRegistry'
], function (declare, Memory, OnDemandGrid, Selection, ColumnResizer, DijitRegistry ) {
Related
Ok, so I would like to have a slider that looks like this one.
Just can't figure out where we can at least have these delimiter separators? So if you see there are 7 delimiters and we have large labels on the first 4-th and the last delimeter.
How would you approach this task?
This is a rather old question but I was faced with the very same need today. Building on GenieWanted's answer, I came to this:
...
{
xtype: 'sliderfield',
maxValue: 5,
label: 'Some data',
html: '<table width="100%" align="left"><tr><td width="25%">Min</td><td width="50%" align="center">Med</td><td width="25%" align="right">Max</td></tr></table>'
}
...
which works very well for me, and avoids messing around to find the correct number of needed. Also, I suspect that results would vary from device to device using .
There is no way of adding a label inside sliderfield. However, you can indeed add HTML to acheive the required output. On the config panel, go to HTML property, and add something like this:
<div style="padding-left:1em">| | |<div>Low Average High </div></div>
The output I have got:
You just need to playaround with the alignment of your text in the HTML. That will do!
Good Luck!
You can create Custom Slider like this
Ext.ns('Ext.ux');
Ext.ux.CustomSlider = Ext.extend(Object, {
valueTextClass: 'x-slider-value-text',
showSliderBothEndValue: true,
sliderEndValueStyle: 'color: black',
constructor: function(config){
Ext.apply(this, config);
Ext.ux.CustomSlider.superclass.constructor.apply(this, arguments);
},
init: function(parent) {
var me = this;
parent.on({
painted: {
fn: function(component) {
if (me.showSliderBothEndValue) me.showSliderEndValue(this);
if (!this.valueTextEl) {
this.valueTextEl = component.element.createChild({
cls: me.valueTextClass
});
}
}
}
});
},
showSliderEndValue: function(slider) {
var sliderPosX = slider.getComponent().getThumb().element.getX();
var thumbHeight = slider.getComponent().getThumb().element.getHeight();
var sliderLength = slider.getComponent().element.getWidth();
var minValueEl = slider.getComponent().element.createChild();
minValueEl.setHtml(slider.getComponent().getMinValue());
minValueEl.applyStyles('overflow:hidden;position:absolute');
minValueEl.applyStyles(this.sliderEndValueStyle);
minValueEl.setLeft(14);
minValueEl.setTop(thumbHeight -7);
var maxValueEl = slider.getComponent().element.createChild();
maxValueEl.setHtml(slider.getComponent().getMaxValue());
maxValueEl.applyStyles('overflow:hidden;position:absolute');
maxValueEl.applyStyles(this.sliderEndValueStyle);
maxValueEl.setLeft(sliderLength-45);
maxValueEl.setTop(thumbHeight - 7);
}
});
And create slider like this
var slider = {
xtype: 'sliderfield',
flex : 6,
label: "Percentage",
name: "Percentage",
value : 50,
minValue : 0,
maxValue : 100,
labelWrap : true,
labelAlign : 'left',
increment : 10,
plugins: [new Ext.ux.CustomSlider({
showSliderBothEndValue: true
})],
listeners: {
painted: function (slider) {
var sliderPanelItems = this.parent.getInnerItems();
sliderPanelItems[1].setValue(this.getValue());
},
change: function (me,slider, thumb, newVal, oldVal, opts) {
var sliderPanelItems = this.parent.getInnerItems();
sliderPanelItems[1].setValue(newVal);
}
}
};
Result will be like this
I did this using this link
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.
I am using inline editing of enhancedgrid cells and have a NumberSpinner element. The constraints of this numberspinner don't work when editing inline. The required property works fine though.
My code:
{field: 'msorder', width: '10%', name: 'Milestone Order',editable: true, type: dojox.grid.cells._Widget, widgetClass: dijit.form.NumberSpinner, widgetProps: {required:true,smallDelta:1, editorParams:{constraints:{ min:-1000, max:1000, places:0 }} }}
I have also tried:
{field: 'msorder', width: '10%', name: 'Milestone Order',editable: true, type: dojox.grid.cells._Widget, widgetClass: dijit.form.NumberSpinner, widgetProps: {required:true,smallDelta:1, constraints:{ min:-1000, max:1000, places:0 } }}
There is an easier solution, guys:
constraint:{min:0,max:24}
{field: "hours", name: "Stunden",type: dojox.grid.cells._Widget, widgetClass: dijit.form.NumberSpinner, constraint:{min:0,max:24}, widgetProps: {smallDelta:0.25, intermediateChanges:true,}},
It has to be outside of widgetProps and in singular...
I don't know what version of Dojo you use, but there is known bug in 1.6 that constraints are ignored in grid widgets. However, I solve that problem doing a little overwriting standard NumberSpinner.
dojo.require("dijit.form.NumberSpinner");
dojo.addOnLoad(function() {
dojo.declare("mySpinner", [ dijit.form.NumberSpinner], {
validator: function(v, c){
var MIN= -1000;
var MAX = 1000;
c.min= MIN;
c.max = MAX ;
return ((v < MAX ) && (v > MIN));
},
});
var dateBox = new mySpinner({}).placeAt('foo');
dateBox.set("value", 1000);
});
(Now, in your grid structure you should use mySpinner of course, and it should do the trick).
Demo: http://jsfiddle.net/tvUaK/135/
I used another way to solve that problem. I define the type of cell as Widget and then I create the widget on get method.
{
field: 'msorder',
width: '10%',
name: 'Milestone Order',
editable: true,
type: dojox.grid.cells._Widget,
get: function(rowIndex, item) {
var store = this.grid.store,
value = store.getValue(item, 'value');
this.widget = new dijit.form.NumberSpinner({ value:0,
constraints:{ min:-1000, max:1000 }
});
return value;
}
}
With this implementation I was able to set different constraints for each cell on the grid.
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
I want to display data that i receive from a data store. One way that i have tried, is to take a text field make it disabled and then set its value with store data.
But i don't think it is the correct solution so i am trying to use label instead and I am not getting how it can be done. Can you guys can point me to correct way of doing it.? Any help appreciated .
Thanks,
Mehul Makwana.
This post is a little old but I was research the for same topic and ended up using a different approach.
I'm using Sencha Touch v2.0. I create the label and place it inside the form.Panel as one would normally do. I then configured the label tpl in designer to include the model fields. When applying the values to the formpanel, I also invoke the apply() method on the label tpl. The following working sample illustrate it.
app.js:
Ext.Loader.setConfig({
enabled: true
});
Ext.application({
views: [
'MyFormPanel'
],
name: 'MyApp',
launch: function() {
Ext.create('MyApp.view.MyFormPanel', {fullscreen: true});
}
});
view.MyFormPanel.js
Ext.define('MyApp.view.MyFormPanel', {
extend: 'Ext.form.Panel',
alias: 'widget.myformpanel',
config: {
items: [
{
xtype: 'label',
itemId: 'myLabel',
tpl: [
'Hello, {firstName} {lastName}, please change your email below:',
''
]
},
{
xtype: 'textfield',
label: 'Email:'
}
],
listeners: [
{
fn: 'onFormpanelInitialize',
event: 'initialize'
}
]
},
onFormpanelInitialize: function(component, options) {
var person = Ext.decode("{firstName: 'John',lastName: 'Dow',email: 'jd#somewhere.com'}");
// apply value to the form
this.setValues(person);
// get the updated text for the label
var label = this.down('#myLabel');
var html = label.getTpl().apply(person);
label.setHtml(html);
}
});
So the idea is save the label template in the label.tpl field, then get the runtime label value using apply() method of Template, then set the label text to it.
I recently tried to solve this problem by creating a 'label' form component. I posted about it in a blog article I wrote on Sencha/PhoneGap. Here is the code:
Ext.form.LabelField = function(config){
Ext.form.LabelField.superclass.constructor.call(this, config);
};
Ext.extend(Ext.form.LabelField, Ext.form.Field, {
isField: true,
value: '',
renderSelectors: {fieldEl: '.x-form-labelfield'},
renderTpl: [
'<tpl if="label">',
'<div class="x-form-label"><span>{label}</span></div>',
'</tpl>',
'<div class="x-form-label x-form-labelfield" style="width:70%; text-align:right"><span>{value}</span></div>',
],
setValue:function(val) {
this.value = val;
if(this.rendered){
this.fieldEl.update('<span>' + val + '</span>');
}
return this;
},
});
Ext.reg('labelfield', Ext.form.LabelField);
Let me know if this does the trick.
Thank you mistagrooves. That was exactly what I was looking for. I reccomand removing x-form-label class and using these styles:
.x-form-labelfield {
-webkit-box-flex: 1;
box-flex: 1;
width: 100%;
position: relative;
-webkit-border-radius: 0;
border-radius: 0;
padding: .4em;
border: 0;
min-height: 2.5em;
display: block;
background: white none;
-webkit-appearance: none;
}