Ankündigung

Einklappen
Keine Ankündigung bisher.

Auto-Refresh: Kalender Widget

Einklappen
X
 
  • Filter
  • Zeit
  • Anzeigen
Alles löschen
neue Beiträge

    [Codebeispiel] Auto-Refresh: Kalender Widget

    Nabend,

    ich habe es endlich mal geschafft mir die Visu anzugucken und bin echt begeistert von dem was Ihr da geschafft habt. *Daumen hoch*

    Da ich in einem anderen Thread gelesen habe das sich z.B. das Kalender-Widget nicht automatisch aktualisiert habe ich mir den Code mal angesehen und eine einfache (vll. nicht perfekte) Lösung gebaut, die es ermöglicht als weiteren Parameter ein Refresh-Interval (in Minuten) anzugeben.

    Hier mal meine "calendar.html"

    Code:
    /**
     * -----------------------------------------------------------------------------
     * @package     smartVISU
     * @author      Martin Gleiß
     * @copyright   2012
     * @license     GPL <http://www.gnu.de>
     * ----------------------------------------------------------------------------- 
     */ 
                    
     
    /**
     * Displays the calendarlist
     *  
     * @param       unique id for this widget
     * @param       a title to display
     * @param       the number of displayed calendar-entries, default 25 
     * @param 		the refresh intveral in minutes
     * @param       a color for this calendar, default grey 
     */ 
    {% macro list(id, title, count, color, interval) %}
        {% set uid = uid(page, id) %}
    
        <div id="{{ uid }}" data-widget="calendar.list" class="calendarlist">
            {% if title %} <h2>{{ title }}</h2> {% endif %}
            <ul data-role="listview">
            </ul>
        </div>
    
    
        <script type="text/javascript">
    		function updateCalendar(uid) {
    			return function() {
    				$.getJSON('lib/calendar/service/{{ config_calendar_service }}.php?url={{ config_calendar_url|url_encode() }}&count={{ count|default(25) }}', function(data) {
    					var line = '';
    					var sum = 1;
    					for (var i in data) {
    						ret  = '<img style="background: ' + data[i].color + ';" class="icon" src="' + data[i].icon + '" />';
    						ret += '<div class="color" style="background: {{ color|default('#666666') }};"></div>';
    						ret += '<h3>' + data[i].title + '</h3>';
    						ret += '<p>' + data[i].weekday + ',&nbsp;' + data[i].period + '&nbsp;</p>';
    
    						if (data[i].where)
    							ret += '<span class="ui-li-count">' + data[i].where + '</span>';
    
    						ret = '<a href="' + (data[i].link ? data[i].link : '#') + '">' + ret + '</a>';
    						line += '<li data-icon="false">' + ret + '</li>';
    					}
    
    					$('#' + uid + ' ul').html(line).trigger('prepare').listview('refresh').trigger('redraw');
    				})
    				.error(notify.json);
    			}
    		}
    		
            $(document).delegate('div[data-widget="calendar.list"]', {
    			'init': function(event) {
                    var uid = this.id;
    				updateCalendar(uid)();
    				if ('{{ interval }}') {
    					setInterval(updateCalendar(uid), '{{ interval * 60000}}');
    				}
    			}
    		});
    
            $('#{{ page }}').on('pagecreate',function(event, ui){
                $('#{{ uid }}').trigger('init');
            });
       </script>
    {% endmacro %}

    Einbindung dann quasi wie gewohnt mit einem Parameter mehr:
    (hier Refresh alle 60 Minuten)
    Code:
    {% import "calendar.html" as calendar %}
        {{ calendar.list('calendarlist1', 'Kalender', 5, null, 60) }}

    Theoretisch lässt sich das auch fürs Phone und Wetter-Widget übernehmen.

    Evtl. lässt sich der Code noch optimieren, die Lösung n Closure zurückzugeben erfüllte auf die Schnelle Ihren Zweck.


    Grüße,

    Lars

    #2
    Ich habe das auch mal für Wetter (current, forecast, forecastweek) und Phone übernommen.

    Grundsätzlich funktioniert der Ansatz, was mir dann aber beim Testen aufgefallen ist:
    Der Reload lief weiter wenn das Widget nicht zu sehen ist, also wenn ich zum Beispiel in der Smarthome Demo von der Startseite (index.html) auf Hallway gewechselt bin.

    Hat man anschließend die Seite neugeladen und ist zurück zur Startseite gewechselt, so füllte sich die Console mit Fehlermeldungen, was wohl daran liegt das ich davon ausgegangen bin das jede Seite für sich existiert. Jetzt habe ich aber gesehen das beim Seitenwechsel ein neues Page-Div erzeugt wird, was natürlich den enormen Vorteil hat das jeder zukünftige Seitenwechsel schneller geht, weil kein neues DOM erzeugt werden muss. (Gute Lösung im Übrigen! *thumbs up*)


    Mein Code oben ist also nur bedingt zu empfehlen, mal sehen ob ich einen anderen Weg finde das Refreshen der Widgets zu realisieren.


    Gruß,

    Lars


    PS: Gibt es zufällig irgendwie ein "pagechange" Event mit dem man arbeiten könnte?

    Kommentar


      #3
      Auto-Refresh: Kalender Widget

      http://jquerymobile.com/demos/1.2.0/...pi/events.html

      Das pagechange event könnte dein Freund sein
      Mit freundlichen Grüßen
      Niko Will

      Logiken und Schnittstelle zu anderen Systemen: smarthome.py - Visualisierung: smartVISU
      - Gira TS3 - iPhone & iPad - Mobotix T24 - ekey - Denon 2313 - Russound C5 (RIO over TCP Plugin) -

      Kommentar


        #4
        Ah danke für den Hinweis.
        jQuery ist nicht so mein übliches Tagesgeschäft ;-)

        Mal sehen ob ich am Wochenende, neben Schlitze fräsen und Installation vorbereiten auch noch Zeit finde mir da mal ein wenig mehr anzusehen.

        Kommentar


          #5
          Anstatt einen Refresh im angegebenen Intervall könnte man es auch so machen, wie es die Uhr macht. Wenn du mal in lib/clock/jquery.jdigiclock.js schaust:

          Code:
              $.fn.displayClock = function(el) {
                  $.fn.getTime(el);
                  setTimeout(function() {$.fn.displayClock(el)}, $.fn.delay());
              }
          
              $.fn.delay = function() {
                  var now = new Date();
                  var delay = (60 - now.getSeconds()) * 1000;
                  
                  return delay;
              }
          Mittels getTime wird die Uhr gerendert. Bei setTimeout wird dann die Zeit bis zur nächsten vollen Minute bestimmt und als delay für den Timeout verwendet.

          Für die anderen Widgets bräuchte man also nur die verbleibende Zeit bis zum Tagesende nehmen und als delay für setTimeout zu verwenden.
          Mit freundlichen Grüßen
          Niko Will

          Logiken und Schnittstelle zu anderen Systemen: smarthome.py - Visualisierung: smartVISU
          - Gira TS3 - iPhone & iPad - Mobotix T24 - ekey - Denon 2313 - Russound C5 (RIO over TCP Plugin) -

          Kommentar


            #6
            @2ndsky:

            Genau das wäre der richtige Weg! Nur "einmal" aktualisieren, genau dann wenns nötig ist.

            Gruss
            Join smartVISU on facebook. Web: smartvisu.de.
            Dir gefällt smartVISU? Bitte spenden für die Weiterentwicklung.

            Kommentar


              #7
              So der nächste Versuch, aber wieder mit einem bestimmten (konfigurierbarem) Zeit-Interval.

              Die Idee da hinter ist ja, das man z.B. für die Widgets selbst Zeitspannen definieren kann zu denen aktualisiert wird. Beim Kalender reichen evtl. alle 3 oder 6 Stunden, oder nach Gusto auch alle 12 oder mehr.
              Bei der Telefonliste fände ich z.B. 5 oder 15 Minuten interessant, was aber daran liegen mag das ich aktuell überlege mir ein Tablet in den Flur zu hängen was im Grunde immer läuft, da hier nicht immer Benutzerinteraktionen stattfinden ist so ein automatisches Update hilfreich. z.B.: Wenn man nach Hause kommt kurz einmal n Blick drauf werfen was so die Anrufliste sagt ohne die Seite neu laden zu müssen.


              Ich habe das ganze jetzt mal so versucht aufzubauen, das durch das Script keine globale "loadCalendar" Funktion erzeugt wird, außerdem kann ich so relativ bequem in beiden Events ("pageshow", "pagehide") auf die Intervall-Id zugreifen.

              Nach ein paar Tests scheint diese Version deutlich robuster zu sein als mein erster Versuch. Seitenwechsel, Neuladen, etc... funktionieren ohne plötzliche Fehlermeldungen oder sich multiplizierende Aufrufe.


              calendar.html
              Code:
              *snip*

              Kommentar


                #8
                Das Problem mit dem Intervall für den Kalender ist halt, selbst wenn es nur eine Stunde ist, zuletzt aktualisiert um 11:59 Uhr siehst du nach Mitternacht fast ne Stunde lang das alte Datum. Das wäre für mich inakzeptabel. Aber dann muss ich da halt selber mal drauf schauen wenn ich Zeit habe.

                EDIT: by the way... das mit der Anrufliste hat sich erledigt, sobald ich dazu komme mein FB Plugin anzupassen. Dann werden die Daten von sh.py automatisch bei Aktualisierung in die smartVISU geschoben. Was IMHO auch der richtige Weg ist. Pollen sollte man nur machen, wenn es gar nicht anders geht.
                Mit freundlichen Grüßen
                Niko Will

                Logiken und Schnittstelle zu anderen Systemen: smarthome.py - Visualisierung: smartVISU
                - Gira TS3 - iPhone & iPad - Mobotix T24 - ekey - Denon 2313 - Russound C5 (RIO over TCP Plugin) -

                Kommentar


                  #9
                  Etwas "Quick & Dirty" - weiterhin mit optionalem Polling, zusätzlich mit Refresh beim Tageswechsel.


                  Frage: Müsste es nicht sowieso beim "pageshow" ein Update geben? Ohne die automatisierten Refresh Änderungen hab ich glaube ich noch nicht bemerkt das beim Seitenwechsel das Widget aktualisiert wird.


                  Code:
                  /**
                   * -----------------------------------------------------------------------------
                   * @package     smartVISU
                   * @author      Martin Gleiß
                   * @copyright   2012
                   * @license     GPL <http://www.gnu.de>
                   * ----------------------------------------------------------------------------- 
                   */ 
                                  
                   
                  /**
                   * Displays the calendarlist
                   *  
                   * @param       unique id for this widget
                   * @param       a title to display
                   * @param       the number of displayed calendar-entries, default 25 
                   * @param       a color for this calendar, default grey 
                   * @param 		the refresh interval in minutes, default undefined (no refresh)
                   */ 
                  {% macro list(id, title, count, color, interval) %}
                      {% set uid = uid(page, id) %}
                  
                      <div id="{{ uid }}" data-widget="calendar.list" class="calendarlist">
                          {% if title %} <h2>{{ title }}</h2> {% endif %}
                          <ul data-role="listview">
                          </ul>
                      </div>
                  
                  
                      <script type="text/javascript">
                  		(function()*{
                  			var loadCalendar = function(event) {
                  				var uid = this.id;
                  				$.getJSON('lib/calendar/service/{{ config_calendar_service }}.php?url={{ config_calendar_url|url_encode() }}&count={{ count|default(25) }}', function(data) {
                  					var line = '';
                  					var sum = 1;
                  					for (var i in data) {
                  						ret  = '<img style="background: ' + data[i].color + ';" class="icon" src="' + data[i].icon + '" />';
                  						ret += '<div class="color" style="background: {{ color|default('#666666') }};"></div>';
                  						ret += '<h3>' + data[i].title + '</h3>';
                  						ret += '<p>' + data[i].weekday + ',&nbsp;' + data[i].period + '&nbsp;</p>';
                  	
                  						if (data[i].where)
                  							ret += '<span class="ui-li-count">' + data[i].where + '</span>';
                  	
                  						ret = '<a href="' + (data[i].link ? data[i].link : '#') + '">' + ret + '</a>';
                  						line += '<li data-icon="false">' + ret + '</li>';
                  					}
                  					$('#' + uid + ' ul').html(line).trigger('prepare').listview('refresh').trigger('redraw');
                  				})
                  				.error(notify.json);
                  			};
                  		
                  			//returns the delay until dateChange in milliseconds
                  			var getDelay = function() {
                  				var now = new Date();
                  				return (23 - now.getHours()) * 3600000 + (59 - now.getMinutes()) * 60000 + (59 - now.getSeconds()) * 1000 + 2000;
                  			};
                  
                  			//trigger date change event
                  			var triggerDateChange = function() {
                  				$('#{{ uid }}').trigger('dateChange');
                  			};
                  			
                  			//trigger update event
                  			var triggerUpdate = function() {
                  				$('#{{ uid }}').trigger('update');
                  			};
                  
                  			var timeoutId = 0;
                  			$(document).delegate('div[data-widget="calendar.list"]', {
                  				'init': loadCalendar,
                  				'update': loadCalendar,
                  				'dateChange': function() {
                  					triggerUpdate();
                  					timeoutId = setTimeout(triggerDateChange, getDelay());
                  					
                  				}
                  			});
                  			
                  			//initialize on page creation
                  			$('#{{ page }}').on('pagecreate',function(event, ui){
                  				$('#{{ uid }}').trigger('init');
                  			});
                  
                  			//refresh on day change
                  			$('#{{ page }}').on('pageshow',function(event, ui){
                  				timeoutId = setTimeout(triggerDateChange, getDelay());
                  			});
                  
                  			$('#{{ page }}').on('pagehide',function(event){
                  				clearTimeout(timeoutId);
                  			});
                  			
                  			//refresh by interval
                  			if ('{{ interval }}') {
                  				var intervalId = 0;
                  				$('#{{ page }}').on('pageshow',function(event, ui){
                  					intervalId = setInterval(triggerUpdate, '{{ interval }}' * 60000);
                  				});
                  	
                  				$('#{{ page }}').on('pagehide',function(event){
                  					clearInterval(intervalId);
                  				});
                  			}
                  		})()
                     </script>
                  {% endmacro %}

                  PS: Das FB-Plugin ist dann ein von sh.py? Wenn Du soweit bist guck mir mir gern mal an wie man das mit Push vom Backend aus lösen könnte. - Aktuell bin ich net so tief im Thema, daher experimentiere ich halt mit dem was ich so finde ;-)

                  Kommentar


                    #10
                    Zitat von 2ndsky Beitrag anzeigen

                    EDIT: by the way... das mit der Anrufliste hat sich erledigt, sobald ich dazu komme mein FB Plugin anzupassen. Dann werden die Daten von sh.py automatisch bei Aktualisierung in die smartVISU geschoben. Was IMHO auch der richtige Weg ist. Pollen sollte man nur machen, wenn es gar nicht anders geht.
                    da bin ich mal gespannt, wie du das machst. das müsste ja dann eine array der eine liste sein.

                    Grüße stromie

                    Kommentar


                      #11
                      Ich hoffe auch noch auf eine Listen-Funktion für die Kombi sh.py/smartVISU...

                      Aber davon ab: Denke eher Nico wird mit einem einzelnen "Update-Item" den Lesevorgang triggern lassen...

                      Kommentar


                        #12
                        Nene, wenn dann wird das eine Liste die von sh.py übern Websocket an die smartVISU geht. Ohne es getestet zu haben, sollten sich doch eigentlich List Items ohne Probleme übertragen lassen.
                        Mit freundlichen Grüßen
                        Niko Will

                        Logiken und Schnittstelle zu anderen Systemen: smarthome.py - Visualisierung: smartVISU
                        - Gira TS3 - iPhone & iPad - Mobotix T24 - ekey - Denon 2313 - Russound C5 (RIO over TCP Plugin) -

                        Kommentar


                          #13
                          Hi Nico,

                          wenn du das tatsächlich vorhast, wäre es toll wenn du das https://knx-user-forum.de/smartvisu/...eren-kann.html mal im Hinterkopf hältst.

                          Grüße
                          Robert

                          Kommentar


                            #14
                            Auto-Refresh: Kalender Widget

                            Hallo Robert,

                            macht Sinn. Wenn es niemand vor mir macht, werde ich versuchen, das mit einzubauen.
                            Mit freundlichen Grüßen
                            Niko Will

                            Logiken und Schnittstelle zu anderen Systemen: smarthome.py - Visualisierung: smartVISU
                            - Gira TS3 - iPhone & iPad - Mobotix T24 - ekey - Denon 2313 - Russound C5 (RIO over TCP Plugin) -

                            Kommentar

                            Lädt...
                            X