HTML5 To Do shopping list app

Posted by on February 22nd, 2018  •  0 Comments  •  Full Article

I’ve been using both Evernote and Wunderlist for years. I’ve built a ToDo list before in jQuery that came close to Wunderlist. It had draggable list items, and delete item checkboxes. But when studying JavaScript, jQuery is considered cheating.

So I was pleased to see this one show up in my latest online lesson. I prettied it up with some style sheets. I’m waiting until later in my studies to figure out how to connect it to a database, hopefully with something like Node.js. For now though, it just works in the browser session memory. It’s cool to make useful things that actually work. This one embedded in WordPress has some extra padding related to WordPress styles, but the direct link outside of WordPress works as intended.

Shopping list


You can also access it here as a direct link outside of WordPress.

Custom HTML5 video player controls

Posted by on February 22nd, 2018  •  0 Comments  •  Full Article

We had an inch of snow today. I took a brisk walk around the block on the sunny, but slippery sidewalks before getting back to work programming.

Yesterday our exercise was to remove the default html5 video player controls, then substitute a handbuilt controller. As an added challenge, they asked if we could program in a clickable playhead. They gave us a couple clues, but thinking it through was a  brain squeezer. There was a 190 pixel wide area where the progress bar walked across as the video played.

Somehow that area needed to become clickable. When clicked, the video should play at that percentage. Meaning, if you click half way across the progress bar area, the video should jump to the halfway point.

I can’t post the video here in WordPress without a lot of trouble from width properties. So instead I’m linking to it here as an external page. But the code is shown below. The magic in the  clickable progress bar is on line 157: function jumpTo(e){…}

My solution isn’t a true draggable playhead, but it does at least navigate, and displays a nice red bar when clicked.

var media = document.querySelector('video');
var controls = document.querySelector('.controls');

var play = document.querySelector('.play');
var stop = document.querySelector('.stop');
var rwd = document.querySelector('.rwd');
var fwd = document.querySelector('.fwd');

var timerWrapper = document.querySelector('.timer');
var timer = document.querySelector('.timer span');
var timerBar = document.querySelector('.timer div');
var intervalRwd;
var intervalFwd;
//removes the default html5 controls
media.removeAttribute('controls');
controls.style.visibility = 'visible';

play.addEventListener('click', playPauseMedia);

function playPauseMedia(){

  /*below fixes a problem that occurs if they try to stop
  while fast forward or fast reverse is running*/
  rwd.classList.remove('active');
  fwd.classList.remove('active');
  clearInterval(intervalRwd);
  clearInterval(intervalFwd);

  if(media.paused) {
    play.setAttribute('data-icon', 'u');
    media.play();
  } else {
    play.setAttribute('data-icon','P');
    media.pause();
  }
}//end function playPauseMedia

stop.addEventListener('click', stopMedia);
media.addEventListener('ended', stopMedia);

function stopMedia() {
  media.pause();
  media.currentTime = 0;
  play.setAttribute('data-icon','P');

  /*below fixes a problem that occurs if they try to stop
  while fast forward or fast reverse is running*/
  rwd.classList.remove('active');
  fwd.classList.remove('active');
  clearInterval(intervalRwd);
  clearInterval(intervalFwd);
}

rwd.addEventListener('click', mediaBackward);
fwd.addEventListener('click', mediaForward);

function mediaBackward(){
  clearInterval(intervalFwd);
  fwd.classList.remove('active');

  if(rwd.classList.contains('active')){
    rwd.classList.remove('active');
    clearInterval(intervalRwd);
    media.play();
  } else {
    rwd.classList.add('active');
    media.pause();

    /*
    If it hasn't yet been set, we add the active
    class to the rwd button using classList.add(),
    pause the video using HTMLMediaElement.pause(),
    then set the intervalRwd variable to equal
    a setInterval() call. When invoked, setInterval()
    creates an active interval, meaning that
    it runs the function given as the first
    parameter every x milliseconds,
    where x is the value of the 2nd parameter.
    So here we are running the windBackward()
    function every 200 milliseconds — we'll
    use this function to wind the video backwards
    constantly. To stop a setInterval() running,
    you have to call clearInterval(),
    giving it the identifying name of the
    interval to clear, which in this case
    is the variable name intervalRwd
    */
    intervalRwd = setInterval(windBackward, 200);
  }
}//end function mediaBackward

function mediaForward(){
  clearInterval(intervalRwd);
  rwd.classList.remove('active');

  if(fwd.classList.contains('active')){
    fwd.classList.remove('active');
    clearInterval(intervalFwd);
    media.play();
  } else {
    fwd.classList.add('active');
    media.pause();
    intervalFwd = setInterval(windForward, 200);//setInterval() takes two parameters: a function & milliseconds
  }
}//end function mediaForward

function windBackward(){
  if(media.currentTime <= 3){
    //rwd.classList.remove('active');
    //clearInterval(intervalRwd);
    stopMedia();
  } else {
    media.currentTime -= 3;
  }
}//end function windBackward

function windForward(){
  if(media.currentTime >= media.duration - 3){
    //fwd.classList.remove('active');
    //clearInterval(intervalFwd);
    stopMedia();
  } else {
    media.currentTime += 3;
  }
}//end function windBackward

media.addEventListener('timeupdate', setTime);

function setTime(){
  var minutes = Math.floor(media.currentTime / 60);//floor rounds down to nearest integer, if 90 seconds, returns: 1
  var seconds = Math.floor(media.currentTime - minutes * 60);//if 90 seconds, returns: 30
  var minuteValue;
  var secondValue;

  if(minutes < 10){
    minuteValue = '0' + minutes;
  } else {
    minuteValue = minutes;
  }

  if (seconds < 10){
    secondValue = '0' + seconds;
  } else {
    secondValue = seconds;
  }

  var mediaTime = minuteValue + ':' + secondValue;
  timer.textContent = mediaTime;

  //any elements width is found via: element.clientWidth
  var barLength = timerWrapper.clientWidth * (media.currentTime/media.duration);
  timerBar.style.width = barLength + 'px';
}//end function setTime()

timerWrapper.addEventListener('click', jumpTo)
var durationPercent;
function jumpTo(e){
  durationPercent = Math.floor((e.x - 273) / 2);
  media.currentTime = durationPercent * (media.duration / 100);
  timerBar.classList.add('playHead');
  console.log('xMouse: ' + e.x) + ', ' +  console.log('yMouse: ' + e.y);
}

// timerWrapper.onclick = function(e){
//   console.log('xMouse: ' + e.x) + ', ' +  console.log('yMouse: ' + e.y);
// }