ExtJS4- Year and month date picker - disable all future dates - extjs

I am using a Ext.picker.Month.
Setting maxDate does not disable dates which are grater than the maxDate value, but causes a validation error when selecting one.
How can I disable all future dates?
See fiddle -
1. Set maxDate to new Date()
2. Use ExtJS 4.2

You are instantiating a MonthPicker, not a DatePicker, yet you are using dozens of config options that are only available for a DatePicker.
You can see here how to instantiate a MonthPicker. As you can see there and especially in the docs, MonthPicker does not provide a config option to disable anything. Also, if you check the DatePicker behaviour, you see that disabledDates option does not change anything in MonthPicker, only AFTER the month has been selected, all days in the DatePicker are disabled.
So you would be on your own in implementing disabledDates for the MonthPicker, which I would do by looking at the code from DatePicker and MonthPicker, and trying to transfer.

Try this one...working on ExtJS 6.0.0.
You need to override 'Ext.picker.Month'
find attached image
Accepted values -
new RegExp('(?:)'); disable all month/year
new RegExp('^((?!^Apr/2016$|^May/2016$|^Jun/2016$|^Jul/2016$).)*$') disable all values other than Apr/May/Jun/Jul 2016
CSS -
.x-monthpicker-disabled {
background-color: #eee !important;
cursor: default !important;
color: #bbb !important;
}
disabledCls: Ext.baseCSSPrefix + 'monthpicker-disabled',
disabledMonthYearsRE: null,
disabledMonthYearsText: 'Disabled',
updateBody: function () {
//default Extjs code
if (me.rendered) {
//default Extjs code
//remove disabled cls and tooltip
years.removeCls(disabledCls);
months.set({
'data-qtip': ''
});
years.set({
'data-qtip': ''
});
months.removeCls(disabledCls);
//default Extjs code
if (dmyMatch) {
if (month == null && year == null) {
months.set({
'data-qtip': dmyText
});
months.addCls(disabledCls);
}
yrInView = false;
for (y = 0; y < yLen; y++) {
yr = yearNumbers[y];
el = Ext.fly(yearItems[y]);
if (dmyMatch.toString().indexOf(yr) == -1) {
el.dom.setAttribute('data-qtip', dmyText);
el.addCls(disabledCls);
}
if (yr == year) {
yrInView = true;
}
}
if (year != null && yrInView) {
for (m = 0; m < mLen; m++) {
mNo = m;
if (mNo < monthOffset) {
mNo = mNo * 2;
} else {
mNo = (mNo - monthOffset) * 2 + 1;
}
mt = months.elements[mNo];
if (dmyMatch.test(mt.text + "/" + year)) {
mt.setAttribute('data-qtip', dmyText);
mt.className = disabledCls + ' ' + mt.className;
}
}
} else {
//Add tooltip 'disabled'
months.set({
'data-qtip': dmyText
});
months.addCls(disabledCls);
}
}
}
},
//Disable month and year click for disabled values
onMonthClick: function (target, isDouble) {
var me = this;
if (!me.disabled && !Ext.fly(target).hasCls(me.disabledCls)) {
//default Extjs code
}
},
onYearClick: function (target, isDouble) {
var me = this;
if (!me.disabled && !Ext.fly(target).hasCls(me.disabledCls)) {
//default Extjs code
}
}

Related

Display day with hours in Angularjs

Here are date and time.
Date 2018-05-25T10:35:04.000Z
Expected Output = 3 days 12 hours
I want to display date and time same like as a give above. Currently, I am using moment.js. Is there any way to display like above?
Alternatively to Zvi's suggestion, you could use the AngularJS date filter
Say in your controller you have 2 dates:
app.controller('AppCtrl', function($scope) {
ctrl = this;
ctrl.date1 = new Date("2018-05-22T22:35:04.000Z");
ctrl.date2 = new Date("2018-05-25T10:35:04.000Z");
});
And in HTML, you'd display the difference with the date filter:
{{ctrl.date2 - ctrl.date1 | date:"dd 'days' HH 'hours'"}}
Here's a working JSFiddle example
You can use this moment-precise-range.
Here's full example:
calcDiff = (date : string) => {
let diff_in_string = '';
let original_date = moment(date);
let date_time_now = moment();
let diff_in_object: any = moment-presice.preciseDiffBetweenDates(original_date, date_time_now, true);
if (diff_in_object.days > 0) {
diff_in_string = diff_in_string + diff_in_object.days + ' ';
if (diff_in_object.days === 1) {
diff_in_string += 'Day '
} else {
diff_in_string += 'Days '
}
}
if (diff_in_object.hours > 0) {
if (diff_in_object.days > 0) {
diff_in_string += 'and ' + diff_in_object.hours + ' '
} else {
diff_in_string += diff_in_object.hours + ' '
}
if (diff_in_object.hours === 1) {
diff_in_string += 'Hour '
} else {
diff_in_string += 'Hours '
}
}
diff_in_string += 'ago'
return diff_in_string;
}
You should consider using The HumanizeDuration library (you can check this answer).
It allows you to translate in any language you want the difference between two dates the way you want.
For example :
var yourdate= moment().set({'year': 2018, 'month': 5, 'day': 22});
var today = moment();
var duration = moment.duration(today.diff(yourdate));
var humanized = humanizeDuration(duration, { units: ['d', 'h'], language: language, round: true });
You can also format it with spacers, etc.

Arbitrary Timeline in Cesium?

Cesium has a nice timeline at the bottom of the screen that changes the current astronomical phenomena and changes model positions and animation based on their model. What it doesn't have, and what I really need, is a way to plot events in arbitrary time. I'd like to start at time 00:00:00, and advance from there in real time, and rewind back to 00:00:00. At the moment, I don't care about astronomical activity, including solar and lunar activity. The API is set up to accept Julian Time, not set up for some arbitrary time. Is it possible to get an arbitrary timeline inserted in place of the normal timeline?
Give this a try. Internally it still uses JulianDates from some arbitrary date, but the user only ever sees the time, not the date.
var viewer = new Cesium.Viewer('cesiumContainer', {
navigationInstructionsInitiallyVisible: false,
skyBox: false
});
var clock = viewer.clock;
clock.clockRange = Cesium.ClockRange.LOOP_STOP;
clock.startTime = Cesium.JulianDate.fromIso8601('2016-01-01T00:00:00Z');
clock.stopTime = Cesium.JulianDate.fromIso8601('2016-01-01T23:59:59Z');
clock.currentTime = clock.startTime;
function twoDigits(num) {
return ((num < 10) ? ('0' + num.toString()) : num.toString());
}
var animationViewModel = viewer.animation.viewModel;
animationViewModel.dateFormatter = function() { return ''; };
animationViewModel.timeFormatter = function(date, viewModel) {
var gregorianDate = Cesium.JulianDate.toGregorianDate(date);
var millisecond = Math.round(gregorianDate.millisecond);
return Cesium.sprintf("%02d:%02d:%02d.%03d", gregorianDate.hour,
gregorianDate.minute, gregorianDate.second, millisecond);
};
viewer.timeline.makeLabel = function(time) {
var gregorian = Cesium.JulianDate.toGregorianDate(time);
var millisecond = gregorian.millisecond, millisecondString = '';
if ((millisecond > 0) && (this._timeBarSecondsSpan < 3600)) {
millisecondString = Math.floor(millisecond).toString();
while (millisecondString.length < 3) {
millisecondString = '0' + millisecondString;
}
millisecondString = '.' + millisecondString;
}
return twoDigits(gregorian.hour) + ':' + twoDigits(gregorian.minute) + ':' +
twoDigits(gregorian.second) + millisecondString;
};
viewer.timeline.updateFromClock();
viewer.timeline.zoomTo(clock.startTime, clock.stopTime);
html, body, #cesiumContainer {
width: 100%; height: 100%; margin: 0; padding: 0; overflow: hidden;
font-family: sans-serif;
}
<link href="http://cesiumjs.org/releases/1.18/Build/Cesium/Widgets/widgets.css"
rel="stylesheet"/>
<script src="http://cesiumjs.org/releases/1.18/Build/Cesium/Cesium.js">
</script>
<div id="cesiumContainer"></div>

ng-grid - Keep overall width the same when altering column widths

I have an ng-grid with 6 columns in it, and as a default set up each column is 100px, so the grid itself is 600px. The columns are resizable but I want to keep the overall grid width the same, to ensure that there are no horizontal scroll bars. So, for example, if I change the second columns width to 150px I would want the overall width to stay at 600px (so maybe an adjacent cell will change size to 50px) - this way I don't get a scroll bar.
Does anybody know if there is a plugin that can do this/help me accomplish this?
I've included a plunker: http://plnkr.co/edit/4LRHQPg7w2eDMBafvy6b?p=preview
In this example, I would want to keep the table width at 600px, so if I expand "Field 2" you will see "Field 4" go off the edge of the viewable area for the grid and a horizontal scroll bar appear. The behaviour I want is for a different column (probably the adjacent column - "Field 3") to shrink in size automatically, so that the grid stays at 600px and the horizontal scroll bar doesn't appear.
After a lot of time searching the web for an answer, I started with Paul Witherspoon idea of watching the isColumnResizing property and after reading about ng-grid plugins I came up with this plugin solution:
Plunker: http://plnkr.co/edit/Aoyt73oYydIB3JmnYi9O?p=preview
Plugin code:
function anchorLastColumn () {
var self = this;
self.grid = null;
self.scope = null;
self.services = null;
self.init = function (scope, grid, services) {
self.grid = grid;
self.scope = scope;
self.services = services;
self.scope.$watch('isColumnResizing', function (newValue, oldValue) {
if (newValue === false && oldValue === true) { //on stop resizing
var gridWidth = self.grid.rootDim.outerWidth;
var viewportH = self.scope.viewportDimHeight();
var maxHeight = self.grid.maxCanvasHt;
if(maxHeight > viewportH) { // remove vertical scrollbar width
gridWidth -= self.services.DomUtilityService.ScrollW;
}
var cols = self.scope.columns;
var col = null, i = cols.length;
while(col == null && i-- > 0) {
if(cols[i].visible) {
col = cols[i]; // last column VISIBLE
}
}
var sum = 0;
for(var i = 0; i < cols.length - 1; i++) {
if(cols[i].visible) {
sum += cols[i].width;
}
}
if(sum + col.minWidth <= gridWidth) {
col.width = gridWidth - sum; // the last gets the remaining
}
}
});
}
}
and in the controller
$scope.gridOptions = {
data: 'myData',
enableColumnResize: true,
plugins: [new anchorLastColumn()],
columnDefs: $scope.columnDefs
};
It is not a perfect solution but works for me and I hope that it will help others.
I found a way to do this using a watch on the isColumnResizing property:
$scope.$watch('gridOptions.$gridScope.isColumnResizing', function (newValue, oldValue) {
if (newValue === false && oldValue === true) { //on stop resizing
$scope.ColResizeHandler($scope.gridOptions.$gridScope.columns);
}
}, true);
then I was able to resize the columns in the resize handler I created:
$scope.ColResizeHandler = function (columns) {
var origWidth;
var col1 = undefined;
var col2 = undefined;
var widthcol2;
var found = false;
var widthDiff = 0;
angular.forEach(columns, function (value) {
if (col2 == undefined && value.visible) {
if (found) {
origWidth += value.width;
col2 = value;
colSizeLimits(col2, widthDiff);
found = false;
}
if (value.origWidth != undefined && value.origWidth != value.width && col2 == undefined) {
found = true;
col1 = value;
widthDiff = value.width - value.origWidth;
origWidth = value.origWidth;
}
}
});
if (col2 == undefined) {
//this was the last visible column - don't allow resizing
col1.width = origWidth;
}
else {
//ensure limits haven't been blown to cope with reizing
if (col1.width + col2.width != origWidth) {
var diff = (col1.width + col2.width) - origWidth;
colSizeLimits(col1, diff);
}
}
col1.origWidth = col1.width;
col2.origWidth = col2.width;
}
There are 2 issues with this.
1 - if you resize and drag the column sizer outside of the grid (i.e. all the way over and out of the ng-grid viewable area) the isColumnResizing watch doesn't execute when you stop dragging and release the resizer. (I think this may be a bug in ng-grid because it does actually resize the column to where you have dragged the resizer, even if it is outside the grids viewable area, it just doesn't fire the watch code).
2 - if you avoid this issue and just drag within the viewable grid area then the columns will resize but only after you finish dragging the resizer, so the ui looks a little funny (i.e. if I expand a column then the adjacent column will not shrink until I click off the resizer and stop dragging).
I'll be working on these issues and will post any updates/fixes I find.

Angular ui bootstrap current date (today) highlight without selecting

I am using Angular.UI Bootstrap Datepicker (http://angular-ui.github.io/bootstrap/#/datepicker)
Now I am challenging one problem: the client always wants to see current date highlighted, even if it is not selected. Just like in this example (http://angular-ui.github.io/ui-date/).
Tried to google this problem, but no solution found for Angular.UI Bootstrap Datepicker.
There is no way, to switch to ui-date. Any ideas?
Thank you!
Replace in the datepicker control this
var days = getDates(firstDate, numDates), labels = new Array(7);
for (var i = 0; i < numDates; i++) {
var dt = new Date(days[i]);
days[i] = makeDate(dt, format.day, (selected && selected.getDate() === dt.getDate() && selected.getMonth() === dt.getMonth() && selected.getFullYear() === dt.getFullYear()), dt.getMonth() !== month);
}
with
var today = new Date();
var days = getDates(firstDate, numDates), labels = new Array(7);
for (var i = 0; i < numDates; i++) {
var dt = new Date(days[i]);
var highlight = (selected && selected.getDate() === dt.getDate() && selected.getMonth() === dt.getMonth() && selected.getFullYear() === dt.getFullYear());
if(!highlight) {
highlight = (today.getDate() === dt.getDate() && today.getMonth() === dt.getMonth() && today.getFullYear() === dt.getFullYear());
}
days[i] = makeDate(dt, format.day, highlight, dt.getMonth() !== month);
}
You can also use the custom-class attribute of the datepicker.
Like this:
<datepicker custom-class="isToday(date, mode)" show-weeks='false' class="well well-sm" ng-model="selectedDate" ng-change="onDateSelect()"></datepicker>
Then you add the function on the controller:
$scope.isToday = function(date, mode) {
var today = new Date();
today.setHours(12,0,0,0);
if(today.toDateString() == date.toDateString() ){
return 'today';
}
};
(another option is comparing day, month and year if you prefer)
Now just the css you want to evidence the day:
.today button{
background-color: #BCBCBC;}
PS: This will show the day if you change the date from today, if you want to have the current day highlighted always just make a stronger css selector to override the default '.active' class.

ExtJS 4: Excel-style keyboard navigation in an editable Grid

Using ExtJS 4 I would like to create a grid into which the user will enter a long list of numbers. I would like the user to be able to finish editing one cell by pressing "Enter" and then automatically move to the cell below and start editing.
Ext.grid.plugin.CellEditing seems to work well for the purpose of editing, but I can't find a way to detect and handle the keyUp event.
I tried approaching the matter using the "edit" event with this code:
selType: 'cellmodel',
plugins: [
Ext.create('Ext.grid.plugin.CellEditing', {
clicksToEdit: 1,
listeners: {
edit: function (editor, e, eOpts) {
// If the event is fired by pressing "Enter", the column and row associated with event will
// be the same as the currently selected row and column
if (e.grid.selModel.position.column == e.colIdx && e.grid.selModel.position.row == e.rowIdx){
// Check if we are in the final row
if (e.rowIdx+1 == e.grid.getStore().getTotalCount()){
return true;
}
editor.startEditByPosition({row: e.rowIdx+1, column: e.colIdx});
return false;
}
}
}
})
],
The problem with this approach is that if the user starts editing the cell, then clicks on a GUI element outside of the Grid, the edit event does not distinguish this from the "Enter" key being pressed. Can this be fixed?
Perhaps I should be trying to implement a custom SelectionModel instead? How does one go about starting with that approach?
something like this ???
when editing try using tab, shift + tab, enter, and shift + enter
what i did is override the cellediting and selection.rowmodel
actually, i have had a similar question with you. and #Lionel Chan help me solve it.
and my solution above is base on his idea.
Note : only work with Extjs 4.0.7
EDIT (if my jsfiddle broken, here's the override)
Ext.override(Ext.grid.plugin.CellEditing,{
onSpecialKey: function(ed, field, e) {
var grid = this.grid,sm;
if (e.getKey() === e.TAB) {
e.stopEvent();
sm = grid.getSelectionModel();
if (sm.onEditorTab)sm.onEditorTab(this, e);
}else if(e.getKey() === e.ENTER){
e.stopEvent();
sm = grid.getSelectionModel();
if (sm.onEditorEnter)sm.onEditorEnter(this, e);
}
}
});
Ext.override(Ext.selection.RowModel, {
lastId:null,
onEditorTab: function(ep, e) {
var me = this,
view = me.view,
record = ep.getActiveRecord(),
header = ep.getActiveColumn(),
position = view.getPosition(record, header),
direction = e.shiftKey ? 'left' : 'right',
newPosition = view.walkCells(position, direction, e, false),
newId=newPosition.row,
grid=view.up('gridpanel');
if (me.lastId!=newId && me.lastId!=null){
deltaX = me.lastId<newId? -Infinity : Infinity;
header=grid.headerCt.getHeaderAtIndex(newPosition.column);
if(header){
while(!header.getEditor()){
newPosition= view.walkCells(newPosition,direction, e, false);
header=grid.headerCt.getHeaderAtIndex(newPosition.column);
}
}
}else{
deltaX = ep.context.column.width * (direction== 'right' ? 1 : -1);
}
grid.scrollByDeltaX(deltaX);
me.lastId=newPosition.row;
Ext.defer(function(){
if (newPosition)ep.startEditByPosition(newPosition);
else ep.completeEdit();
}, 100);
},
onEditorEnter:function(ep,e){
var me = this,
view = me.view,
record = ep.getActiveRecord(),
header = ep.getActiveColumn(),
position = view.getPosition(record, header),
direction = e.shiftKey ? 'up' : 'down',
newPosition = view.walkCells(position, direction, e, false),
newId=newPosition.row,
grid=view.up('gridpanel');
deltaY=20 * (direction== 'down' ? 1 : -1);
grid.scrollByDeltaY(deltaY);
me.lastId=newPosition.row;
Ext.defer(function(){
if (newPosition)ep.startEditByPosition(newPosition);
else ep.completeEdit();
}, 100);
}
});
Starting with the suggestion of "Warung Nasi 49",
I Wrote this override:
Ext.define('Override.Ext.grid.plugin.CellEditing',
{
override: 'Ext.grid.plugin.CellEditing',
onSpecialKey: function (ed, field, e) {
var grid = this.grid,
nbCols = grid.columns.length - 1, //start from 0
nbRows = grid.getStore().getTotalCount() - 1, //start from 0
currentCol = this.context.colIdx,
currentRow = this.context.rowIdx;
//forward
if (!e.shiftKey && (e.getKey() === e.ENTER || e.getKey() === e.TAB)) {
e.stopEvent();
//Detect next editable cell
do {
if (this.startEdit(currentRow, currentCol + 1))
break;
else {
currentCol++;
if (currentCol >= nbCols) {
currentRow++;
currentCol = -1;
}
}
} while (currentRow <= nbRows);
}
//backward
if (e.shiftKey && (e.getKey() === e.ENTER || e.getKey() === e.TAB)) {
e.stopEvent();
//Detect previous editable cell
do {
if (this.startEdit(currentRow, currentCol - 1))
break;
else {
currentCol--;
if (currentCol < 0) {
currentRow--;
currentCol = nbCols+1;
}
}
} while (currentRow >=0);
}
}
},
null);
This override allow both TAB and ENTER navigation (forward/backward via SHIFT).
When the last cell of row is reached, the firt editable cell of the next row is focused.

Resources