tappatappa Posted October 18, 2016 Share Posted October 18, 2016 TUniCalendar: 1) Highlight specific days (for example: holidays, events etc..) during rendering, or (even better) dynamically, like the events on a calendarpanel 2) [bug/Missing Feature?] Change the Date attribute on month/year change: the "select" and "click" events are triggered only when the user clicks on a cell (a day), while visually the day does change example: Date is Today 18 Oct 2016, the user clicks on the right arrow (next month), the component shows "18 November 2016" but server-side Date is still 18/10 until the user clicks on "18", then it updates to 18/11. This is confusing for the user, and we received more than one complaint for this. I did some research, this seems to be an ExtJS issue. 3) [Feature Request] Resizing the component. At run time the Calendar is completely different from what I see in the IDE and it stays the same, is it immutable? 4) [Feature Request] Switch to compact/week view, something like this __________________________________ | < October 2016 > | ///change month| < M T W T F S S > | ///change week| 17 18 19 20 21 22 23 | ///select day |_________________________________| Link to comment Share on other sites More sharing options...
tappatappa Posted October 21, 2016 Author Share Posted October 21, 2016 I see that with the v1.0 coming out features request (2-4) are not likely to be processed, still I'd appreciate an input for point 1. Please Link to comment Share on other sites More sharing options...
Sherzod Posted October 21, 2016 Share Posted October 21, 2016 I see that with the v1.0 coming out features request (2-4) are not likely to be processed, still I'd appreciate an input for point 1. Please Hi, Like this?!: Best regards. Link to comment Share on other sites More sharing options...
tappatappa Posted October 21, 2016 Author Share Posted October 21, 2016 Exactly that! Link to comment Share on other sites More sharing options...
Sherzod Posted November 2, 2016 Share Posted November 2, 2016 Exactly that! Hi, For now can you try this implementation?!: 1. uses ... DateUtils; 2. type THighlightDates = record dt: TDate; title: string; end; 3. ... public { Public declarations } HighlightDates: array of THighlightDates; procedure HighlightDatesPush(ADt: TDate; ATitle: string); end; 4. procedure TMainForm.UniFormDestroy(Sender: TObject); begin SetLength(HighlightDates, 0); end; 5. procedure TMainForm.HighlightDatesPush(ADt: TDate; ATitle: string); var I, aLength: Integer; CalendarPickerJSName: string; dateExists: Boolean; begin CalendarPickerJSName := UniCalendar1.JSName + '.items.items[0]'; dateExists := False; for I := 0 to High(HighlightDates) do if CompareDate(HighLightDates[I].dt, ADt) = 0 then begin dateExists := True; Break; end; if dateExists then begin UniSession.AddJS(CalendarPickerJSName + '.highlightDates['+ IntToStr(I) +'].title = "' + ATitle + '";'+ CalendarPickerJSName + '.update(' + CalendarPickerJSName+ '.value, true);' ); end else begin aLength := High(HighlightDates) + 1; SetLength(HighlightDates, aLength + 1); HighlightDates[aLength].dt := ADt; HighlightDates[aLength].title := ATitle; UniSession.AddJS(CalendarPickerJSName + '.highlightDates.push('+ '{dt: new Date("'+FormatDateTime('mm"/"dd"/"yyyy', ADt)+'"), title: "'+ ATitle +'"}'+ '); '+ CalendarPickerJSName + '.update(' + CalendarPickerJSName+ '.value, true);' ); end; end; 6. UniCalendar -> ClientEvents -> UniEvents -> Ext.picker.Date [picker] -> beforeInit fn: function picker.beforeInit(sender, config) { config.highlightDates = []; Ext.override(Ext.DatePicker, { update: function(date, forceRefresh) { this.callParent(arguments); var me = this; me.highlightDates.forEach(function(dates) { me.cells.each(function(el) { if (Ext.Date.clearTime(dates.dt, true).valueOf() == el.dom.firstChild.dateValue) { if (el.hasCls(me.activeCls)) { el.addCls('x-datepicker-highlight'); } else { el.addCls('x-datepicker-highlight-prevnext'); } el.dom.title = dates.title; return false }; }); }) } }) } 7. UniServerModule -> CustomCSS: .x-datepicker-highlight { background: #FFA500 none repeat scroll 0 0; border-color: #bfa52f; } .x-datepicker-highlight-prevnext { background: #fff4bf none repeat scroll 0 0; border-color: #bfa52f; } Best regards. 1 Link to comment Share on other sites More sharing options...
Sherzod Posted November 2, 2016 Share Posted November 2, 2016 TUniCalendar: 2) [bug/Missing Feature?] Change the Date attribute on month/year change: the "select" and "click" events are triggered only when the user clicks on a cell (a day), while visually the day does change example: Date is Today 18 Oct 2016, the user clicks on the right arrow (next month), the component shows "18 November 2016" but server-side Date is still 18/10 until the user clicks on "18", then it updates to 18/11. This is confusing for the user, and we received more than one complaint for this. I did some research, this seems to be an ExtJS issue. Also for now you can try this: UniCalendar -> ClientEvents -> UniEvents -> Ext.picker.Date [picker] -> beforeInit fn: function picker.beforeInit(sender, config) { config.highlightDates = []; Ext.override(Ext.DatePicker, { update: function(date, forceRefresh) { this.callParent(arguments); var me = this; me.highlightDates.forEach(function(dates) { me.cells.each(function(el) { if (Ext.Date.clearTime(dates.dt, true).valueOf() == el.dom.firstChild.dateValue) { if (el.hasCls(me.activeCls)) { el.addCls('x-datepicker-highlight'); } else { el.addCls('x-datepicker-highlight-prevnext'); } el.dom.title = dates.title; return false }; }); }); // add this: Ext.defer(function() { me.fireEvent("select"); }, 200); } }) } 1 Link to comment Share on other sites More sharing options...
zilav Posted November 5, 2016 Share Posted November 5, 2016 Why do you SetLength(HighlightDates, 0) in destroy event? Aren't arrays are ref counted in Delphi or I'm missing something? Link to comment Share on other sites More sharing options...
Sherzod Posted November 5, 2016 Share Posted November 5, 2016 Hi, Why do you SetLength(HighlightDates, 0) in destroy event? Aren't arrays are ref counted in Delphi or I'm missing something? Yes sorry, you are right, this code is rather pointless... We could use to clear the array when we need it, for example: var CalendarPickerJSName: string; begin SetLength(HighlightDates, 0); CalendarPickerJSName := UniCalendar1.JSName + '.items.items[0]'; UniSession.AddJS(CalendarPickerJSName + '.highlightDates = [];'+ CalendarPickerJSName + '.update(' + CalendarPickerJSName+ '.value, true);' ); end; Best regards. Link to comment Share on other sites More sharing options...
tappatappa Posted November 9, 2016 Author Share Posted November 9, 2016 Finally I had a chance to test your code. It works great!I have two questions: 1) procedure TMainForm.HighlightDatesPush(ADt: TDate; ATitle: string); what is the point of the string "Title"? In my code I removed it from server side and from JS and the days are still highlighted as expected. Is it the content of the tooltip when the user moves the mouse over the day? 2) In my project I actually load the days in blocks, so my procedure looks something like void TForm1::highlightDates(std::vector<TDateTime>& dt_vec) { for (size_t i = 0; i < dt_vec.size(); ++i) { UniSession->AddJS(.......); } } is there a way to shrink the js code instead of making n calls to highlightDates.push(...); picker.update()?something likepicker.items.items[0].highlightDates.push(___vector_of_dates___); picker.items.items[0].update(....) Link to comment Share on other sites More sharing options...
Sherzod Posted November 9, 2016 Share Posted November 9, 2016 1) procedure TMainForm.HighlightDatesPush(ADt: TDate; ATitle: string); what is the point of the string "Title"? In my code I removed it from server side and from JS and the days are still highlighted as expected. Is it the content of the tooltip when the user moves the mouse over the day? Yes Link to comment Share on other sites More sharing options...
Sherzod Posted November 10, 2016 Share Posted November 10, 2016 Hi, 2) In my project I actually load the days in blocks, so my procedure looks something like void TForm1::highlightDates(std::vector<TDateTime>& dt_vec) { for (size_t i = 0; i < dt_vec.size(); ++i) { UniSession->AddJS(.......); } } is there a way to shrink the js code instead of making n calls to highlightDates.push(...); picker.update()?something likepicker.items.items[0].highlightDates.push(___vector_of_dates___); picker.items.items[0].update(....) You can use something like this: var I: Integer; mLength: Integer; str: string; CalendarPickerJSName: string; begin CalendarPickerJSName := UniCalendar1.JSName + '.items.items[0]'; mLength := High(HighlightDates); for I := 0 to mLength do begin str:=str+'{dt: new Date("'+FormatDateTime('mm"/"dd"/"yyyy', HighlightDates[I].dt)+'")}'; if I<mLength then str:=str+','; end; if mLength>-1 then UniSession.AddJS(CalendarPickerJSName + '.highlightDates.push('+str+');'+ CalendarPickerJSName + '.update(' + CalendarPickerJSName+ '.value, true);'); end; Best regards. Link to comment Share on other sites More sharing options...
tappatappa Posted November 10, 2016 Author Share Posted November 10, 2016 The day highlight is just what I needed, thank you. I ported the code to my project and it works. I noticed something odd with the addition of // add this: Ext.defer(function() { me.fireEvent("select"); }, 200); It does fix the month change, but the regular day click fires twice, and when the component is first rendered also it fires the event multiple times. Problem is I don't know what the snippet does, since I am quite an ExtJS newbie, so I am not capable of fixing it. Can you confirm this? Link to comment Share on other sites More sharing options...
Sherzod Posted November 10, 2016 Share Posted November 10, 2016 Hi, I noticed something odd with the addition of // add this: Ext.defer(function() { me.fireEvent("select"); }, 200); It does fix the month change, but the regular day click fires twice, and when the component is first rendered also it fires the event multiple times. Problem is I don't know what the snippet does, since I am quite an ExtJS newbie, so I am not capable of fixing it. Can you confirm this? Then try this: function picker.beforeInit(sender, config) { config.highlightDates = []; Ext.override(Ext.DatePicker, { isAnotherMonthView: function(date) { var activeDate = this.activeDate || date; return date.getYear() != activeDate.getYear() || date.getMonth() != activeDate.getMonth(); }, update: function(date, forceRefresh) { var me = this; monthViewChange = me.isAnotherMonthView(date); this.callParent(arguments); me.highlightDates.forEach(function(dates) { me.cells.each(function(el) { if (Ext.Date.clearTime(dates.dt, true).valueOf() == el.dom.firstChild.dateValue) { if (el.hasCls(me.activeCls)) { el.addCls('x-datepicker-highlight'); } else { el.addCls('x-datepicker-highlight-prevnext'); } el.dom.title = dates.title; return false }; }); }); if (monthViewChange) { Ext.defer(function() { me.fireEvent("select"); }, 200); } } }) } Best regards. Link to comment Share on other sites More sharing options...
tappatappa Posted November 10, 2016 Author Share Posted November 10, 2016 Ok I tested it and I confirm that it works. So, this ....beforeInit... Ext.override(Ext.DatePicker, { //....stuff is it altering this particular instance, or does it change Ext.DatePicker globally? Link to comment Share on other sites More sharing options...
tappatappa Posted November 10, 2016 Author Share Posted November 10, 2016 Well, it is global. This Ext.Override is pretty destructive it breaks every other picker in the application Link to comment Share on other sites More sharing options...
Sherzod Posted November 10, 2016 Share Posted November 10, 2016 Hi, At the moment the solution above, is it OK for you ?! Best regards. Link to comment Share on other sites More sharing options...
tappatappa Posted November 10, 2016 Author Share Posted November 10, 2016 Found a solution: 1) Put this early in the application (for instance at the construction/show of the main form) Ext.override(Ext.DatePicker, { highlightDates:[], enablePickerHighlight:false, isAnotherMonthView: function(date) { var activeDate = this.activeDate || date; return date.getYear() != activeDate.getYear() || date.getMonth() != activeDate.getMonth(); }, update: function(date, forceRefresh) { var me = this; monthViewChange = me.isAnotherMonthView(date); this.callParent(arguments); if(me.enablePickerHighlight){ me.highlightDates.forEach(function(dates) { me.cells.each(function(el) { if (Ext.Date.clearTime(dates.dt, true).valueOf() == el.dom.firstChild.dateValue) { if (el.hasCls(me.activeCls)) { el.addCls('x-datepicker-highlight'); } else { el.addCls('x-datepicker-highlight-prevnext'); } //enable this if you wish custom title /*el.dom.title = dates.title;*/ return false; }; }); }); if (monthViewChange) { Ext.defer(function() { me.fireEvent('select'); }, 200); } } } }); 2) in the particular picker, beforeInit function picker.beforeInit(sender, config){ config.highlightDates = []; config.enablePickerHighlight=true; } Thanks for your patience, I learned a lot, actually. Link to comment Share on other sites More sharing options...
Sherzod Posted November 10, 2016 Share Posted November 10, 2016 Perfect! Link to comment Share on other sites More sharing options...
allenchow Posted November 11, 2016 Share Posted November 11, 2016 When I try, I got error as attached Link to comment Share on other sites More sharing options...
tappatappa Posted November 11, 2016 Author Share Posted November 11, 2016 In order to make it work you need to separate two steps: 1) the Ext.override code and the beforeInit ....let the JS component render 2) UniSession->AddJS(...) This is necessary because if you fire both at the same time (for instance at form first Show) the JS code can't find the ExtJS DatePicker. In practice, try to execute TMainForm.HighlightDatesPush(ADt: TDate; ATitle: string) after a Timer fires (once) or on button click Link to comment Share on other sites More sharing options...
allenchow Posted November 11, 2016 Share Posted November 11, 2016 It works ! Thanks ! Link to comment Share on other sites More sharing options...
allenchow Posted November 11, 2016 Share Posted November 11, 2016 OH No! After I open the frame with this highlight, I can't open other frame with unicalendar components ! It blank all . Please help Link to comment Share on other sites More sharing options...
Sherzod Posted November 11, 2016 Share Posted November 11, 2016 Hi, Can you tell us the sequence of your actions or can you make a small test case for this ?! Best regards. Link to comment Share on other sites More sharing options...
allenchow Posted November 11, 2016 Share Posted November 11, 2016 I think the problem was just like previous message mentioned: it's global and destructive ... Link to comment Share on other sites More sharing options...
allenchow Posted November 11, 2016 Share Posted November 11, 2016 Found a solution: 1) Put this early in the application (for instance at the construction/show of the main form) Ext.override(Ext.DatePicker, { highlightDates:[], enablePickerHighlight:false, isAnotherMonthView: function(date) { var activeDate = this.activeDate || date; return date.getYear() != activeDate.getYear() || date.getMonth() != activeDate.getMonth(); }, update: function(date, forceRefresh) { var me = this; monthViewChange = me.isAnotherMonthView(date); this.callParent(arguments); if(me.enablePickerHighlight){ me.highlightDates.forEach(function(dates) { me.cells.each(function(el) { if (Ext.Date.clearTime(dates.dt, true).valueOf() == el.dom.firstChild.dateValue) { if (el.hasCls(me.activeCls)) { el.addCls('x-datepicker-highlight'); } else { el.addCls('x-datepicker-highlight-prevnext'); } //enable this if you wish custom title /*el.dom.title = dates.title;*/ return false; }; }); }); if (monthViewChange) { Ext.defer(function() { me.fireEvent('select'); }, 200); } } } }); 2) in the particular picker, beforeInit function picker.beforeInit(sender, config){ config.highlightDates = []; config.enablePickerHighlight=true; } Thanks for your patience, I learned a lot, actually. It works ! Thx !! Link to comment Share on other sites More sharing options...
Recommended Posts
Please sign in to comment
You will be able to leave a comment after signing in
Sign In Now