DEV Community

loading...

Mapty App with OOP

idevbrandon profile image Brandon Ha Updated on ・3 min read

Using Geolocation API
how to track the location

if (navigator.geolocation)
  navigator.geolocation.getCurrentPosition(
    function (position) {
      const { latitude } = position.coords;
      const { longitude } = position.coords;
      console.log(latitude, longitude);
    },
    function () {
      alert("Could not get your location");
    }
  );
Enter fullscreen mode Exit fullscreen mode

Display a map with library

const coords = [latitude, longitude];
      const map = L.map("map").setView(coords, 13);
Enter fullscreen mode Exit fullscreen mode

Display a marker on the map

      // event listner
      map.on("click", function (mapEvent) {
        console.log(mapEvent);
        const { lat, lng } = mapEvent.latlng;

        L.marker([lat, lng])
          .addTo(map)
          .bindPopup(
            L.popup({
              maxWidth: 250,
              minWidth: 100,
              autoClose: false,
              closeOnClick: false,
              className: "running-popup",
            })
          )
          .setPopupContent("workout")
          .openPopup();
      });
Enter fullscreen mode Exit fullscreen mode

Rendering workout input form

  1. separate marker function from getCurrentPosition()
  2. Make global variable to access map, mapEvent mapEvent = mapE; // copy global mapEvent variable
  3. Define form type whether running or cycling

Project Architecture:
Main structure comes from class and object.
Class workout (holds common things like distance/duration)

Child class Running extends Workout (cadence, pace)

Child class Cycling extends Workout (elevationGain, speed)

Class App (holds all handling events, common objects)

Refactoring for project architecture
initial structure

class App {
  constructor() {}

  _getPosition() {}

  _loadMap() {}

  _showForm() {}

  _toggleElevationField() {}

  _newWorkout() {}
}
Enter fullscreen mode Exit fullscreen mode
  1. write down _getPosition()
  2. set const app = new App();
  3. constructor method called immd when a new object is created from this class this._getPosition(); // "this" current object
  4. set #map and #mapEvent
  5. // this._bindMap treated is as a regular function call, not a method call. // in a regular function call, this key is set to undefined (use bind) navigator.geolocation.getCurrentPosition(this._loadMap.bind(this),

Managing workout data by creating classes

  1. Create the parent class, called 'Workout' that holds constructor(coords, distance, duration) {}
  2. create sub classes (Running and Cycling) with each own functions
const run1 = new Running([39, -12], 5.2, 24, 178);
const cycling1 = new Cycling([39, -12], 27, 95, 523);
console.log(run1, cycling1);
Enter fullscreen mode Exit fullscreen mode

Creating a new workout

_newWorkout(e) {}

2 helper functions to check data validation
const validInputs = (...inputs) => {
inputs.every((inp) => Number.isFinite(inp));
};
const allPositive = (...inputs) => {
inputs.every((inp) => inp > 0);
};
// get data from form
1. const type = inputType.value;

// If activity is running, create Running object
if (type === "running") {
   // check if the data is valid (use helper func)

// If activity is cycling, create cycling object 
Enter fullscreen mode Exit fullscreen mode

if (type === "cycling") {
const elevation = +inputElevation.value;
if (
!validInputs(distance, duration, elevation) ||
!allPositive(distance, duration)
)
return alert("all except elevation has to be a positive number");
workout = new Cycling([lat, lng], distance, duration, elevation);
}

// Add new object to workout array
this.#workouts.push(workout);
console.log(workout);

// Render workout on a map marker 
this.renderWorkoutMarker(workout);
Enter fullscreen mode Exit fullscreen mode

separate renderWorkoutMarker() outside scope

// Render workout on the list
this.renderWorkoutMarker(workout);

// Hide the form + clear input fields
Enter fullscreen mode Exit fullscreen mode

Rendering workout

  1. define the renderWorkout() with Template literals
    const html = ~~
    // Render workout on the list
    this._renderWorkout(workout);

  2. Whenever a new object is being create, run this._setDescription(); in sub-classes (Running & Cycling)
    so, it can access to this.type under _setDescription()

  3. complete html for each running & cycling
    and then form.insertAdjacentHTML("afterend", html);

  4. get rid of {} in if statement

  5. hide form

  _hideForm() {
    // empty input
    inputDistance.value = inputDuration.value = inputCadence.value = inputElevation.value =
      "";

    form.style.display = "none";
    form.classList.add("hidden");
  }
Enter fullscreen mode Exit fullscreen mode

copyright by Jonas Schmedtmann's course work

Discussion (0)

Forem Open with the Forem app