Plan and done for June-11-2017

What will I learn today?

  1. Dive into JS.

Done

  1. What is this all about - http://al1s.github.io/posts/plan-and-done-for-may-25-2017/.

    Day 13 - show pictures only if they are in a visible part of a screen. And yes it is not a screen, it's a viewport - visible part of a document. Its dimensions are properties either window or document.documentElement objects (here is excerpts from spec - https://stackoverflow.com/a/7205786), so the task is simple - check on scroll if relative element position less then a viewport. How to find relative position? Here is a method getBoundingClientRect(). And to toggle classes on an element I have classList methods - add and remove.

    More broad solution - lazy images loading - is here - https://css-tricks.com/snippets/javascript/lazy-loading-images/.

Plan and done for June-09-2017

What will I learn today?

  1. Dive into JS.

Done

  1. What is this all about - http://al1s.github.io/posts/plan-and-done-for-may-25-2017/.

    Day 12 - Draw unicorns all around the page on KONAMI code key sequence. Here is about KONAMI code - https://en.wikipedia.org/wiki/Konami_Code. And here is cornifier - https://github.com/Cornify/Cornify/blob/master/js/cornify.js.

    User story:

    • As a user, I want to press key sequence (KONAMI), so that I'll get a unicorn or a rainbow on the page.
    • As a user, I want to press than any key, so that I'll get more unicorns and rainbows on the page, one per each key pressed.

    Done. It was the simplest one among JS30. Here is a little about keypress event and the right property to get key code - https://css-tricks.com/snippets/javascript/javascript-keycodes/.

Plan and done for June-08-2017

What will I learn today?

  1. Dive into JS.

Done

  1. What is this all about - http://al1s.github.io/posts/plan-and-done-for-may-25-2017/.

    Day 11 - Custom video player. Here is MDN manual on media element control - https://developer.mozilla.org/en/docs/Web/API/HTMLMediaElement. And here is a walkthrough on building custom player - https://developer.mozilla.org/en-US/Apps/Fundamentals/Audio_and_video_delivery/cross_browser_video_player.

    Done. What were interesting:

    • to set progress bar to position relative to movie position I used setInterval with percentage number rounded with custom round function which supports arbitrary precision.
    • to make progress bar controllable (it's a simple colored div with flexible width with another div as a wrapper) I had to find position of the mouse relative to element. Here is example - https://stackoverflow.com/a/10109204 - how to get it.

    Used JS elements:

    • querySelector;
    • addEventListener, removeEventListener;
    • setInterval, clearInterval;
    • mediaElement.play, mediaElement.pause, mediaElement.currentTime, mediaElement.duration, mediaElement.volume, mediaElement.playbackRate.

Plan and done for June-07-2017

What will I learn today?

  1. Dive into JS.

Decided to clear the TODO list to keep focused.

Done

  1. Tried another approach:

    • on any keypress on input element, put it into an array;
    • if Shift is pressed, set all elements between two last items in the array to checked state.

    Encountered weird misunderstanding - I push elements with each keypress but when I want to check if an element in the array in some cases it says - NO, there is no such element. And when I log the array, I can easily spot it. WTFj

    The reason of weirdness was simple - name for array in JS is just a pointer. I added elements to an array inside the loop. I've checked the last two array's elements on equality to my loop variable. And yes, I've just pushed array's elements out of the search scope. Moved out array initialization out of the search loop and made it immutable in some way - no addition to it at all.

    Done.

    Learnt how to use console.group() to make logs grouping in Chrome console. Learnt it from the Dat 9.

Plan and done for June-06-2017

What will I learn today?

  1. Make menu hide only on tablet and desktop versions or add input-label to hide JS-function.
  2. Fix quirks in Safari: icons have become too small, everything become a mess on a wide screen.
  3. Fix a masthead height on resolution wider 640px.
  4. Fix an offer body text align for the gift message - now it aligns to center on resolutions less than 570.
  5. Build additional pages - hotels, impression, blog.
  6. Style the form on impression page.
  7. Dive into JS.
  8. Implement form validation.

Done

  1. Day 10 of JS30 (day 9 was about web dev panel utilization, without any assignment). Build a checkbox's list with ability to select the range of items with Shift pressed. My plan:

    • iterate through the list of checkboxes (divs in this case);
    • find first checked input element;
    • set flag and start to put this and all following input elements into array;
    • if next checked found, release flag and finish iteration;
    • if flag released, Shift pressed, and array of elements is not empty - set checked property to true for all of them.

    It would work for a list of unchecked items, but if I already have checked items the approack will fail. Try something new.

Plan and done for June-05-2017

What will I learn today?

  1. Make menu hide only on tablet and desktop versions or add input-label to hide JS-function.
  2. Fix quirks in Safari: icons have become too small, everything become a mess on a wide screen.
  3. Fix a masthead height on resolution wider 640px.
  4. Fix an offer body text align for the gift message - now it aligns to center on resolutions less than 570.
  5. Build additional pages - hotels, impression, blog.
  6. Style the form on impression page.
  7. Dive into JS.
  8. Implement form validation.

Done

  1. Still on the day 8 of JS30 (https://javascript30.com) - fighting with canvas drawing. I want to implement smooth width change dependant on a mouse speed. Tried to bind it directly to the speed - it works but it's far from expected smoothness.

    Here is a snippet from MDN (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/round) to make round in JS behave like in other languages - with precision:

    var myNamespace = {};
    
    myNamespace.round = function(number, precision) {
        var factor = Math.pow(10, precision);
        var tempNumber = number * factor;
        var roundedTempNumber = Math.round(tempNumber);
        return roundedTempNumber / factor;
    };
    

    Want to try to calculate a mouse acceleration and bind width to it.

    And again finally I've got something, that looks not as planned. Ok. Let's move on - perfection kills has some answers and techniques - http://perfectionkills.com/exploring-canvas-drawing-techniques/ (one is exactly about quadratic bezier curve - https://codepen.io/kangax/pen/zofsp) and here is SO answer - https://stackoverflow.com/a/10661872. I've completed it to look like Wes Bos example.

    Done:

    • recalled some math primitives - get an angle between two vectors, get point's coordinates;
    • applied ternary operator, prototype enhencement by new functions implementation, utilizing hsl() command in coloring shapes, canvas drawing.

Plan and done for June-04-2017

What will I learn today?

  1. Make menu hide only on tablet and desktop versions or add input-label to hide JS-function.
  2. Fix quirks in Safari: icons have become too small, everything become a mess on a wide screen.
  3. Fix a masthead height on resolution wider 640px.
  4. Fix an offer body text align for the gift message - now it aligns to center on resolutions less than 570.
  5. Build additional pages - hotels, impression, blog.
  6. Style the form on impression page.
  7. Dive into JS.
  8. Implement form validation.

Done

  1. To arms! Looked through the code of spline drawing example - http://scaledinnovation.com/analytics/splines/aboutSplines.html, it's not complicated but I want to build something even simpler utilizing cubic bezier curve - only one control point for each pair of mouse movement captured points. I have to find the coordinates of that control point and my idea is:

    • to take three points with every event;
    • to calculate distance between these three points;
    • to build auxiliary similar triangle on the base of the segment connecting first two points;
    • to calculate an angle between first and third segments - it's the same angle as in my auxiliary triangle;
    • to find coordinates of the control point.

    Tried different options for calculating control point coordinates (this for example - https://math.stackexchange.com/a/1989113). All I've got is a wavy line with skips. Then I just decided to take every three points and to use middle point as a control point. It works but in a weird way - I've got two twisted lines.

    Finally I've checked what Wes Bos has in the tutorial on Day 8. It's easy! Much easier than I did - just straight lines from one point to another. I overcomplicate things - when I see a task, my approach is sometimes too twisted, too overthinked. Why am I so appealed by complex answers? Have to train, to learn myself to be open to simple solutions first. For example, the task is to implement smooth width increasing/decreasing while drawing in HTML5 canvas depending on the mouse speed. My approach leads to visual steps in line width change. But what I really need is to increament value by one step at a time in a given interval. After the tutorial all is clear and the only thing left is to rebuild from scratch.

    Get the last element of array (from SO - https://stackoverflow.com/a/9050353) by enhancing Array.prototype:

    if (!Array.prototype.last){
      Array.prototype.last = function(){
          return this[this.length - 1];
      };
    };
    

Plan and done for June-02-2017

What will I learn today?

  1. Make menu hide only on tablet and desktop versions or add input-label to hide JS-function.
  2. Fix quirks in Safari: icons have become too small, everything become a mess on a wide screen.
  3. Fix a masthead height on resolution wider 640px.
  4. Fix an offer body text align for the gift message - now it aligns to center on resolutions less than 570.
  5. Build additional pages - hotels, impression, blog.
  6. Style the form on impression page.
  7. Dive into JS.
  8. Implement form validation.

Done

  1. The next JS30 assignment is to build a free drawing tool using HTML5 canvas element. The plan is to implement:

    • draw circle function with two supporting functions: the first should get a mouse position and the second should get a mouse velocity. The first I need to draw circle in a place where mouse is located in a moment and the second - to manage line width: the faster the mouse is moved - the thinner line is drawn;
    • spline interpolation - to make the line drawn looks more natural. Without it I have only dots with intervals which depend on a mouse velocity.

    Here is a manual on canvas drawing - https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API/Tutorial/Basic_usage. An example on mouse movement tracking - https://stackoverflow.com/a/7790764. It's a bit weird - uses both event driven and interval scanning, but I didn't get how the last works. How to measure velocity - https://stackoverflow.com/a/19794374. How to work with a bezier curve - http://scaledinnovation.com/analytics/splines/aboutSplines.html.

    Got stuck a little - spline code do the job, but I don't want so complex logic, I want to try to implement the drawing canvas only with cubic bezier curve, so I want to calculate control point position. I know coordinates of two other points, I can find the distance between them, I can set the distance from to the desired control point voluntary and calculate its coordinates accordingly. Here is description of the process - https://math.stackexchange.com/a/544025.

Plan and done for May-30-2017

What will I learn today?

  1. Make menu hide only on tablet and desktop versions or add input-label to hide JS-function.
  2. Fix quirks in Safari: icons have become too small, everything become a mess on a wide screen.
  3. Fix a masthead height on resolution wider 640px.
  4. Fix an offer body text align for the gift message - now it aligns to center on resolutions less than 570.
  5. Build additional pages - hotels, impression, blog.
  6. Style the form on impression page.
  7. Dive into JS.
  8. Implement form validation.

Done

  1. Tried to implement plain text parser. I want to get JSON-like data as output. Stuck with map because it returns the whole object but I need only one element of it. Found the solution here - https://stackoverflow.com/questions/36120265/how-to-convert-text-file-to-json-in-javascript. KISS!

    I had some issues with understanding how to get only part of the keys in JSON object. Tried to rebuild object using map and forEach but failed. And the funniest part was that I couldn't find the answer in Google! I know, I know - a question has and answer or at least part of it, so the question was wrong. And then I just realized that it's better to use notions of set theory as it applies to Databases. What if I would ask to fine subset of JS object such as JSON. And finally I've found the solution - https://stackoverflow.com/a/39333479. And the approach is very neat, not much longer or trickier then in declarative languages (SQL for example).

    Another obstacle was how to get data from node.js fs.readFile function. It seemed unnatural not to get data in return statement, but it's just another paradigm of programming and interrelation between objects in an async world. Here is an explanation on how to do it better - https://stackoverflow.com/questions/10058814/get-data-from-fs-readfile.

Plan and done for May-29-2017

What will I learn today?

  1. Make menu hide only on tablet and desktop versions or add input-label to hide JS-function.
  2. Fix quirks in Safari: icons have become too small, everything become a mess on a wide screen.
  3. Fix a masthead height on resolution wider 640px.
  4. Fix an offer body text align for the gift message - now it aligns to center on resolutions less than 570.
  5. Build additional pages - hotels, impression, blog.
  6. Style the form on impression page.
  7. Dive into JS.
  8. Implement form validation.

Done

  1. Today's JS30 challange is to build photo gallery with an animation on click:

    • expand the clicked picture if it wasn't expanded before;
    • shrink the clicked picture if it was expanded before;
    • make a hidden text appear (or disappear as it's in the normal state).

    The first interesting stop on the route - how to expand the picture no matter if the mouse clicked on picture or on the text in front of it. An event listener returns different objects as a target in such case: div with picture or p for the text clicked.

    My first thought was just to prevent events if p element is clicked, but it's bad UX - sometimes a user clicks the picture and it works, sometimes - it doesn't. The next thought - maybe I accidentally attach event handlers to all elements down the tree starting from my target div? I need to check if it's true, so how to get all event listeners on a page? Google says it has it right inside DevTool of Chrome - https://developers.google.com/web/tools/chrome-devtools/console/events. I've checked - no way, neither Chrome nor Canary. They both have tab called Event Listeners, but there is only events of active element in the Inspector, not all of them even if I tap body element. I've found (https://gist.github.com/danburzo/9254630#gistcomment-1942033) the code which shows exactly what I need:

    const items = Array.from(document.querySelectorAll('*')).map(element => {
    const listeners = getEventListeners(element);
    
    return {
      element: element,
      listeners: Object.keys(listeners).map(key => {
        return {
          event: key,
          listeners: listeners[key]
        };
      })
    };
    
    }).filter(item => item.listeners.length);
    

    Checked it - only the divs with pictures have listeners and that's exactly what I want to get as all listeners on the page. My next step was to dive into Event capturing/bubbling threads - https://www.kirupa.com/html5/event_capturing_bubbling_javascript.htm. But it didn't bring any useful fruits, so I've switched to another tutorial - https://www.kirupa.com/html5/handling_events_for_many_elements.htm and found currentTarget element which is exactly what I need! Here is a great visualization - http://joequery.me/code/event-target-vs-event-currenttarget-30-seconds/ which I implemented from scratch in my playground - https://codepen.io/alstof/full/gWNOdr/.

    I've implemented shrinking by reseting flex rule of each picture element to the default value: flex: 1 1 auto. And I've animated text in the same way - just reseting initial value of first and third text child elements of transform: translateY(+-20vh) to undefined on transitionend event (look here - https://developer.mozilla.org/en-US/docs/Web/Events/transitionend, and there is no any reason to use whichTransitionEnd by David Walsh - https://davidwalsh.name/css-animation-callback, because we have full support in all modern browsers - http://caniuse.com/#search=transitionend).

    Done in almost 7 hours most part of which I tried to get how events behave in browser.

Spontaneous. Here are tons of dev-tool screencasts - https://umaar.com/dev-tips/.