0

why does alert(this.introUpdate) give me undefined in moveNextIntro function. But i can push to this.introUpdate in runIntro function? I have two commented lines and they are both alerts of the object. Please help thank you. the lines are alert(this.introUpdate)...the first is good and i can push to it. The second is not good.

let actionOn = {
  //make decision for processes on url
  params: function () {
    const urlParams = new URLSearchParams(window.location.search);
    urlParams.get("new")
      ? this.runIntro(urlParams.get("new"))
      : console.log("check other params");
  },
  //begin the intro if new account
  runIntro: function (qS) {
    var headerString = qS.split(",");
    var target = document.getElementsByClassName("beginningTT");
    //prettier-ignore
    this.startIntro( headerString[0], this.offSet(target[0]).left + "-" + this.offSet(target[0]).top );
    for (let i = 1; i < qS.split(",").length; i++) {
      this.introUpdate.headers.push(headerString[i]);
      this.introUpdate.points.push(
        this.offSet(target[i]).left + "-" + this.offSet(target[i]).top
      );
    }
    alert(this.introUpdate); //this is good, gives me object 
  },
  //courtesy of stack overflow - traverses dom elements and adds distance between x and y values. returns both XXX - intro
  offSet: function getOffset(el) {
    var _x = 0;
    var _y = 0;
    while (el && !isNaN(el.offsetLeft) && !isNaN(el.offsetTop)) {
      _x += el.offsetLeft - el.scrollLeft;
      _y += el.offsetTop - el.scrollTop;
      el = el.offsetParent;
    }
    return { top: _y, left: _x };
  },
  //intro state XXX - intro - could concatenate the points and headers togeather
  introUpdate: {
    headers: [],
    points: [],
    count: 1,
  },
  //beginning intro XXX - intro
  startIntro: function (hS, pos) {
    var x = parseInt(pos.split("-")[0]) + 40;
    var y = pos.split("-")[1];
    var newElement = `
    <div class="alert alert-info alert-dismissible" style = "top: ${y}px; left: ${x}px; position: absolute; z-index: 1039" >
    <button type="button" class="close" data-dismiss="alert" aria-hidden="true" id = "moveNext"> Next </button> 
    <h5> <i class="icon fas fa-info"></i> Alert! </h5>
    ${hS}
    </div>`;
    document.body.innerHTML += newElement;
  },
  //event for moving next in intro XXX - intro
  moveNextIntro: function () {
    alert(this.introUpdate); //gives me undefined
    //prettier-ignore
    document.getElementById("moveNext").remove;
    //prettier-ignore
    if(this.introUpdate.count === this.introUpdate.points.length){this.endIntro; return} //? fix this
    var x = parseInt(this.introUpdate.points[count].split("-")[0]) + 40;
    var y = this.introUpdate.points[count].split("-")[1];
    var newElement = `
    <div class="alert alert-info alert-dismissible" style = "top: ${y}px; left: ${x}px; position: absolute; z-index: 1">
    <button type="button" class="close" data-dismiss="alert" aria-hidden="true" id = "moveNext"> Next </button> 
    <h5> <i class="icon fas fa-info"></i> Alert! </h5>
    ${this.introUpdate.headers[count]}
    </div>`;
    document.body.innerHTML += newElement;
    this.introUpdate.count++;
  },
  //ending the intro
  endIntro: function () {
    alert("end");
    //delete the element and show a new element
  },
};

//events
$(document).ready(function () {
  actionOn.params();
  document.getElementById("moveNext").onclick = actionOn.moveNextIntro;
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<button id="moveNext" type="button">Move Next</button>
updated code below...

different structure with a similar approach

    //running the intro if a new account ***********************************************************vertical stuff first then horizonal
introAccount = (function () {


  //state for moving -- className that matches headers is "beginningTT"
  let introUpdate = {
    headers: [
      "search for information here",
      "see recent activity",
      "check your status here",
      "subjects you can search through",
      "test your knowledge",
      "see what other users think",
      "communicate with other users",
      "update your account here",
      "your profile information",
      "your about information",
      "interact with others here"
    ],
    points: [],
    count: 1,
  };


  //push points to introUpdate
  function runIntro() {
    var target = document.getElementsByClassName("beginningTT");
    if (introUpdate.headers.length !== target.length) { alert("headers dont match elements");  return; }
    for (let i = 0; i < target.length; i++) {   introUpdate.points.push( getOffset(target[i]).left + "-" + getOffset(target[i]).top ); }
    startIntro(introUpdate.headers[0], introUpdate.points[0]);
  }


  //get position of elements to attach div
  function getOffset(el) {
    var _x = 0;
    var _y = 0;
    while (el && !isNaN(el.offsetLeft) && !isNaN(el.offsetTop)) {
      _x += el.offsetLeft - el.scrollLeft;
      _y += el.offsetTop - el.scrollTop;
      el = el.offsetParent;
    }
    return { top: _y, left: _x };
  }


  //beginning the intro
  function startIntro(hS, pos) {
    var x = parseInt(pos.split("-")[0]);
    var y = parseInt(pos.split("-")[1]) + 50;
    var currentElement = document.createElement("div");
    currentElement.setAttribute("id", "removeCurrent");
    var newElement = `
      <div id = "changeCss" class="alert alert-info" style = "top: ${y}px; left: ${x}px; position: absolute; z-index: 1039; width: 350px; height: 45px; border-radius: 0;" >
      <button class="close" type="button" id = "moveNext" style = "padding-left: 7px"> Next </button> 
      <p id = "changeText">${hS}</p>
      </div>`;
    currentElement.innerHTML = newElement;
    document.body.appendChild(currentElement);
  }


  //change attribute when click for reposition -- maybe create a for loop that changes the x and y as you go, so it diagnoally(v and h) goes across the page...just get next and current then subtract until match
  // for in x--, y-- until next point in array reached
  function attributeChange() {
    if (introUpdate.count === introUpdate.points.length) { endIntro(); return; }
    introUpdate.count === 1 ? //you can use > n < fot the vertical things then the rest are horizontal
    (y = parseInt(introUpdate.points[introUpdate.count].split("-")[1]) + 50, x = parseInt(introUpdate.points[introUpdate.count].split("-")[0]) - 200) :  //- 200 only for the top right
    (y = parseInt(introUpdate.points[introUpdate.count].split("-")[1] - 10), x = parseInt(introUpdate.points[introUpdate.count].split("-")[0]) + 120);
    document.getElementById("changeCss").style.cssText = `top: ${y}px; left: ${x}px; position: absolute; z-index: 1039; width: 350px; height: 45px; border-radius: 0;`;
    document.getElementById("changeText").innerText = `${introUpdate.headers[introUpdate.count]}`;
    introUpdate.count++;
  }


  // end intro and run confetti
  function endIntro() {
    removeEventListener();
    document.getElementById("removeCurrent").remove();
    var confTitle = document.createElement("H1");
    confTitle.setAttribute("id", "canvasIntroTitle");
    confTitle.innerHTML = "HAVE FUN!"
    document.body.appendChild(confTitle);
    introAccountCanvas.beginConfetti();
  }


  //display a slider instead if wifth less than
  function mobileSlider() {}


  //run the points reSizeFunction for new points
  function ifResize() {}


  //listener same across all functions
  document.addEventListener("click", moveForward);
  function moveForward(event) {
    var element = event.target;
    if (element.id == "moveNext") { attributeChange(); }
  }


  //removing event listeners when ending intro
  function removeEventListener(){
    document.removeEventListener("click", moveForward)
  }

  return { intro: runIntro };


})();
Ralph Dingus
  • 87
  • 1
  • 6
  • 2
    Have you tried `$("#moveNext").onclick` instead of `document.getElementById`? – Daniel_Knights Sep 26 '20 at 19:51
  • just did..it works? Do you know why? and thank you – Ralph Dingus Sep 26 '20 at 19:54
  • According to [this](https://stackoverflow.com/a/4070010/12701949), there is a difference in that one returns a DOM object and the other a jQuery object. Not sure how that applies to your code though – Daniel_Knights Sep 26 '20 at 19:57
  • Also, start habit of using `console.log()` instead of `alert()`. The former is a better debugging tool as it doesn't interrupt the application. – GetSet Sep 26 '20 at 20:03

1 Answers1

2

When you assign the handler this way:

document.getElementById("moveNext").onclick = actionOn.moveNextIntro;

this is the button itself, not actionOn. According to documentation:

When the event handler is invoked, the this keyword inside the handler is set to the DOM element on which the handler is registered. For more details, see the this keyword documentation.

(https://developer.mozilla.org/en-US/docs/Web/Guide/Events/Event_handlers)

The moveNext button has no introUpdate property so it errors. If you don't want this behavior, you can wrap your handler in another function

document.getElementById("moveNext").onclick = function() { 
    console.log(this); // on this line, "this" is move next button
    moveNextactionOn.moveNextIntro(); // inside of moveNextIntro, "this" is "actionOn" as you expect
};
chiliNUT
  • 18,989
  • 14
  • 66
  • 106