Skip to content
This repository was archived by the owner on Sep 18, 2020. It is now read-only.

Frontend View Aktuelle Route

Markus Thömmes edited this page Jan 30, 2015 · 21 revisions

← zurück zur Übersicht

Aktuelle Route

Modul: happyHour.views.currentRoute
Controllerdatei: views/current-route/current-route.js
Templatedatei: views/current-route/current-route.html
Route: /currentRoute
Autor: Markus Thömmes

Abhängigkeiten

AppStatusPersistenceService
Zum Speichern der generierten Route im AppStatus
$location
Zum Weiterleiten auf andere Ansichten
BackendService
Zum Laden der Bars aus dem Backend
RouteGeneratorService
Zum Generieren der Route
RoutesPersistenceService
Zum lokalen Speichern der Routen
rating
Direktive zum Anzeigen von Bewertungen auf Foursquare
input-day
Direktive zum Auswählen des Wochentags
input-slider
Direktive zum Auswählen von Werten mithilfe eines Sliders
input-places
Direktive zum Auswählen von Orten mit einer Autovervollständigung
bar-slider
Direktive zum Auswählen von alternativen Bars
formatTime
Dient dem Formatieren von Zeiträumen
## Funktionsweise

Beim Öffnen der Ansicht wird zunächst die aktuelle Route aus dem AppStatus geladen.

$scope.route = AppStatusPersistenceService.getRoute();

Bei jeder Änderung der Route wird sie erneut lokal persistiert, um immer eine aktuelle Version im lokalen Speicher zu haben. Es wird auf die String-Version des Objekts gewatched um deep-watching zu vermeiden und Performanceeinbrüche zu vermeiden.

$scope.$watch(function() {
  return JSON.stringify($scope.route);
}, function() {
  AppStatusPersistenceService.setRoute($scope.route);
});

Bars laden

Initial werden die zur Auswahl stehenden Bars aus dem Backend geladen und pro Timeframe in das bars-Array geschrieben. Werden keine gefunden, wird ein Popup angezeigt. Diese Abfrage wird jedesmal wiederholt, wenn die Sidebar geschlossen wird und sich relevante Optionen (route.options.location, route.options.radius, route.options.weekday) geändert haben.

$scope.bars = [];
BackendService.getBars($scope.route.options.location, $scope.route.options.radius, $scope.route.options.weekday).then(function(bars) {
  possibleBars = bars;

  if(possibleBars.length > 0) {
    _.forEach($scope.route.timeframes, function() {
      $scope.bars.push(possibleBars);
    });
  }
  else {
    $scope.noBarPopupOpen = true;
  }
});

Timeframes neuberechnen

Sobald sich etwas an den Start- und Endzeiten und/oder der Verweildauer ändern, wird versucht, die Bars der alten Timeframes auf die neuen Timeframes zu übernehmen, um die entsprechende Route nicht vollständig zu verlieren.

Dazu werden zunächst die neuen Timeframes aus den Optionen generiert.

while(isBeforeOverNight(startTime, endTime)) {
  newTimeframes.push({
    startTime: startTime.toString(),
    endTime: startTime.add($scope.route.options.stayTime, 'hours').toString(),
    bar: null
  });
}

Nun wird über die neuen und alten Timeframes iteriert und verglichen, ob sich neuer und alter Timeframe überschneiden. Wenn ja wird die Bar aus dem alten Timeframe in den neuen übernommen.

if(
  newStartTime.isBefore(oldStartTime) && newEndTime.isAfter(oldStartTime) ||
  newEndTime.isAfter(oldStartTime) && newStartTime.isBefore(oldEndTime) ||
  newStartTime.isSame(oldStartTime) || newEndTime.isSame(oldEndTime)
) {
  timeframe.bar = oldTimeframe.bar;
}

Route neuberechnen

Um die Route komplett neuzuberechnen, wird über den Reload-Button die reloadRoute-Methode aufgerufen, die sich die Bars nach aktuellsten Optionen aus dem Backend zieht und anschließend an den Algorithmus übergibt, um eine neue Route zu generieren. Werden keine Bars gefunden, wird eine entsprechende Fehlermeldung ausgegeben.

BackendService.getBars($scope.route.options.location, $scope.route.options.radius, $scope.route.options.weekday).then(function(bars) {
  if(bars.length > 0) {
    var route = RouteGeneratorService.createRoute(bars, $scope.route.options);
    $scope.route = route;
  }
  else {
    $scope.noBarPopupOpen = true;
  }
});

Bars

Bardetails anzeigen

Wird eine Bar angeklickt wird die frameClicked-Methode ausgeführt und es werden Details der Bar angezeigt. Dies geschieht über das Setzen der is__expanded-Klasse auf dem HTML-Listenelement.

$scope.frameClicked = function(index) {
  if(index === $scope.openFrameIndex) {
    $scope.openFrameIndex = -1;
  }
  else {
    $scope.openFrameIndex = index;
  }
};
ng-class="{is__expanded : $parent.openFrameIndex === $index}"

Bar löschen

Wird über eine Bar nach links geswiped, oder wird im erweiterten Zustand der Löschen-Knopf betätigt wird die Bar durch die removeBar-Methode aus dem Timeframe entfernt. Des Weiteren wird diese Bar mittels der toDelete-Variable zum Löschen vorgemerkt, was bedeutet, dass der Bar austauschen-Button angezeigt wird.

$scope.removeBar = function(index) {
  $scope.route.timeframes[index].bar = null;
};
ng-class="{is__backside : toDelete}"

Bar austauschen

Das Austauschen der Bar läuft über die BarPickerDirective. Diese schreibt die Auswahl in den entsprechenden Timeframe.

<bar-slider bars="bars[$index]" result="timeframe.bar">

Bar melden

Wird der Melden-Button geklickt erscheint ein Popup, das es ermöglicht einen Meldetext einzugeben und an das Backend abzusenden. Es wird zusätzlich die ID der Bar gespeichert, um sie im globalen Kontext identifizieren zu können und die Meldung entsprechend absetzen zu können.

ng-click="$parent.reportPopupOpen = true; $parent.reportBarId = timeframe.bar.id;

Das Absenden des Popups führt zu einem Aufruf der reportBar-Methode, die die Meldung an das Backend sendet und das Popup wieder schließt, falls eine Meldung eingegeben wurde.

$scope.reportBar = function(barId, reportBarText) {
  if(reportBarText.length > 0) {
    BackendService.reportData(barId, reportBarText);
    $scope.reportPopupNotification = true;
  }
};

Sidebar

Lokation setzen

Das Auswählen einer Lokation erfolgt über die PlacesAutocompleteDirective. Sie speichert ihr Ergebnis direkt im Routenobjekt.

<input-places result="route.options.location" />

Klickt der Nutzer auf das Lokationsicon neben dem Eingabefeld, so wird seine aktuelle Position mittels GPS abgefragt und in der Route gespeichert. Dies geschieht mit der setLocationToDevice-Methode.

$scope.setLocationToDevice = function() {
  navigator.geolocation.getCurrentPosition(function(position) {
    $scope.$apply(function() {
      $scope.route.options.location.longitude = position.coords.longitude;
      $scope.route.options.location.latitude = position.coords.latitude;
    });
  });
};

Wochentag auswählen

Die Auswahl eines Wochentags erfolgt durch die DayPickerDirective, die ihr Ergebnis direkt im Routenobjekt hinterlegt.

<input-day result="route.options.weekday" /

Radius/Verweilzeit ändern

Radius und Verweilzeit werden durch die SliderDirective ausgewählt und das Ergebnis sofort in das Routenobjekt überführt.

<input-slider options="{min:0.1, max:10, step:0.1, from:1, hide_min_max:true}" result="route.options.radius" />

<input-slider options="{min:0.5, max:6, step:0.5, from:1, hide_min_max:true}" result="route.options.stayTime" />

Start- und Endzeit wählen

Auch Start- und Endzeit werden über die SliderDirective gewählt, das Ergebnis (ein Array aus Strings) wird jedoch zunächst in das notwendige Format gebracht, um es dann in das Routenobjekt zu schreiben.

<input-slider options="{type:'double', values: ['18:00','19:00','20:00','21:00','22:00','23:00','24:00','01:00','02:00','03:00','04:00'], from:0, to:6, min_interval:1, max_interval: 10, hide_min_max:true}" result="routeTime" />
$scope.$watch('routeTime', function(routeTime) {
  $scope.route.options.startTime = routeTime[0];
  $scope.route.options.endTime = routeTime[1];
});

Route sharen

Beim Klick auf Sharen wird die Route durch die shareRoute-Methode an das Backend gesendet, der entsprechende Link generiert und dieser dann in einem Popup für den Nutzer angezeigt.

$scope.shareRoute = function() {
  BackendService.saveRoute($scope.route).then(function(hash) {
    $scope.shareLink = $location.protocol() + '://' + $location.host() + ':' + $location.port() + '/#/openRoute/' + hash;
    $scope.sharePopupOpen = true;
  });
};

Route offline speichern

Beim Klick auf Offline speichern wird zunächst ein Popup geöffnet, das es ermöglicht der Route einen Namen zu geben. Anschließend wird die saveRoute-Methode aufgerufen, die die Route speichert, sofern der Name den Anforderungen genügt und der lokale Speicher noch nicht ausgeschöpft ist. Ist dies der Fall wird eine entsprechende Warnung angezeigt.

$scope.saveRoute = function() {
  if(RoutesPersistenceService.isFull()) {
    $scope.saveErrorPopupOpen = true;
    $scope.namePopupOpen = false;
  }
  else {
    if($scope.routeName !== '' && $scope.routeName.length <= 50) {
      $scope.route.name = $scope.routeName;
      RoutesPersistenceService.add($scope.route);
      $scope.namePopupOpen = false;
    }
  }
};

Impressum

Beim Klick auf Impressum wird ein entsprechendes bildschirmfüllendes Popup geöffnet.

ng-click="showImpressum = true"

Clone this wiki locally