bio photo

Email

Concept

getAway plans your weekend away for you (at the best price for the budget you choose. It’s human powered so the options we give keep you at the center of the experience).

Build

The first weeks of HTML, CSS, viewport & bootstrap build looked like this:

Functionality includes multi-selecting buttons, sliders and taking their data input into function calls to travel agents.

Update the CSS to replicate Poncho.is,

Poncho gives weather updates - a website that gives simple information but its UI connects with your mood and environment. Its fluid, colorful and incremental interaction makes two-way interaction easy.

Great, but…

This is what their Style.css looks like:

{color:#ccc;color:rgba(255,255,255,.4)}}@-o-keyframes controlAnimation-3{0%{color:#ccc;color:rgba(255,255,255,.4)}33.3%,9.5%{color:#fff;color:rgba(255,255,255,.8)}100%,42.9%{color:#ccc;color:rgba(255,255,255,.4)}}@keyframes controlAnimation-3{0%{color:#ccc;color:rgba(255,255,255,.4)}33.3%,9.5%{color:#fff;color:rgba(255,255,255,.8)}100%,42.9%{color:#ccc;color:rgba(255,255,255,.4)}}@-webkit-keyframes galleryAnimation-3{0%{opacity:0}33.3%,9.5%{opacity:1}100%,42.9%{opacity:0}}@-o-keyframes galleryAnimation-3{0%{opacity:0}33.3%,9.5%{opacity:1}100%,42.9%{opacity:0}}@keyframes galleryAnimation-3{0%{opacity:0}33.3%,9.5%{opacity:1}100%,42.9%{opacity:0}}@-webkit-keyframes controlAnimation-4{0%{color:#ccc;color:rgba(255,255,255,.4)}25%,7.1%{color:#fff;color:rgba(255,255,255,.8)}100%,32.1%{color:#ccc;color:rgba(255,255,255,.4)}}@-o-keyframes controlAnimation-4{0%{color:#ccc;color:rgba(255,255,255,.4)}25%,7.1%{color:#fff;color:rgba(255,255,255,.8)}100%,32.1%{color:#ccc;color:rgba(255,255,255,.4)}}@keyframes controlAnimation-4{0%

I started putting something together and this is what it looks like right now,

and if you scroll down,

Buttons

Getting buttons to click and stay pressed and have a function is complicated

   buttonClick: function(button){
        if (button.className == "btn-info") {
            button.className = "btn btn-primary"
        } else {
            button.className = "btn-info"
        }

        //color change on button click
        var tags = document.getElementsByName('services');
            for (var i=0; i<tags.length; ++i){
        var b = tags[i];
            if(b.className.indexOf("btn-info") == 0){
            console.log(b.innerHTML + " is selected");
            }
        }
    }, 

	//submit values in first page form "Talk to an Agent" (budget, family, transport, hotel, activities selections)
    requestCheck: function(){

        var transport = (document.getElementById('transport').className.indexOf("btn-primary") !== -1);
        console.log(transport);

        var hotels = (document.getElementById('hotels').className.indexOf("btn-parimary") !== -1);
        console.log(activity);

        var activity = (document.getElementById('activity').className.indexOf("btn-parimary") !== -1);
        console.log(hotels);

        document.getElementById("final").value = "";

            if (transport){
                document.getElementById("final").value += "transport,";
                } if (hotels) {
                document.getElementById("final").value += "hotels,";
                } if (activity) {
                document.getElementById("final").value += "activity";
            }

             console.log(document.getElementById('final'));

            //checking if at least one button option selected
            var tags = document.getElementByTagName('button');

            if (tags[0].className.indexOf("btn-primary") == -1 &&
                tags[1].className.indexOf("btn-primary") == -1 &&
                tags[2].className.indexOf("btn-primary") == -1){
                console.log("please select an option");
                }

            //i dont recall
            if (weather){
            document.getElementById("final").value += "weather,";
            } if (remoteness){
            document.getElementById("final").value += "remoteness,";
            } if (activities) {
            document.getElementById("final").value += "activities";
            }
            console.log(document.getElementById('final'));

            //i dont recall
            document.getElementById("mainform").submit();
            return true;
    },

Speech bubble

Isn’t too far behind, no pngs here, apparently most chat apps make use of funky css tricks to do the bubbles and their pointed parts.

/*css speech bubble*/
p.speech {
  padding: 6px 7px 8px 9px;
  margin-top:50px;
  /*margin-right:30px;*/
  margin-bottom: 5px;
  position: relative;
  width: 200px;
  height: 40px;
  text-align: left;
  vertical-align: baseline;
  font-size: 100%;
  font-style: inherit;
    font-variant: inherit;
    font-weight: inherit;
    font-stretch: inherit;
    line-height: inherit;
    font-family: inherit;

  background-color: #dcf8c6;
  -webkit-border-radius: 4px;
  -moz-border-radius: 4px;
 
  -webkit-box-shadow: 2px 2px 4px #888;
  -moz-box-shadow: 2px 2px 4px #888;
  
}

 p.speech:before {
    content: '';
    position: absolute;
    padding:-1px;
    margin:-1em;
    line-height: 100px;
    left: 0px;
    bottom: -10px;
    width: 10px;
    height: 14px;
    background-position: 50% 50%;
    background-repeat: no-repeat;
    background-size: contain;
    background-color: #dcf8c6;
    border: 0px solid #777;
    -webkit-border-radius: 2px;
    -moz-border-radius: 4px; 
    -webkit-box-shadow: 2px 2px 4px #888;
    -moz-box-shadow: 2px 2px 4px #888;
    border-radius: 2px;
  
    }

I spent a lot of time trying to get it to look like

Sliders

For some reason

 <input type="range"> 

(Sliders in plain English) weren’t visible in phoneGap.

Where there’s a will, or a final the next day, there’s a way:

/*start slider css*/
div.slider {
vertical-align: middle;
text-align: center;
}

input[type=range]{
    -webkit-appearance: none;
    vertical-align: middle;
}

input[type=range]::-webkit-slider-runnable-track {
    width: 300px;
    height: 5px;
    background: #ddd;
    border: none;
    border-radius: 3px;
    vertical-align: middle;
}

input[type=range]::-webkit-slider-thumb {
    -webkit-appearance: none;
    border: none;
    height: 16px;
    width: 16px;
    border-radius: 50%;
    background: goldenrod;
    margin-top: -4px;
    vertical-align: middle;
}

input[type=range]::-ms-fill-lower {
    background: #797979;
    border-radius: 10px;
    vertical-align: middle;
}

input[type=range]::-ms-fill-upper {
    background: #dcdcdc;
    border-radius: 10px;
    vertical-align: middle;
}


input[type=range]:focus {
    outline: none;
}

input[type=range]:focus::-webkit-slider-runnable-track {
    background: #ccc;
}
div.form-group {
    text-align: center;
}
/*end slider css*/

Now it shows fine in Mozilla,Safari and Chrome browsers and to add an extra touch the slider you’re interacting with has a slightly different color.

Animation

Here: you look at it

    onLoad: function() {
        //canvas init
    var canvas = document.getElementById("canvas");
    var ctx = canvas.getContext("2d");
    
    //canvas dimensions
    var W = window.innerWidth;
    var H = window.innerHeight;
    canvas.width = W;
    canvas.height = H;
    
    //snowflake particles
    var mp = 25; //max particles
    var particles = [];
    for(var i = 0; i < mp; i++)
    {
        particles.push({
            x: Math.random()*W, //x-coordinate
            y: Math.random()*H, //y-coordinate
            r: Math.random()*4+1, //radius
            d: Math.random()*mp //density
        })
    }
    
    //Lets draw the flakes
    function draw()
    {
        ctx.clearRect(0, 0, W, H);
        
        ctx.fillStyle = "rgba(255, 255, 255, 0.8)";
        ctx.beginPath();
        for(var i = 0; i < mp; i++)
        {
            var p = particles[i];
            ctx.moveTo(p.x, p.y);
            ctx.arc(p.x, p.y, p.r, 0, Math.PI*2, true);
        }
        ctx.fill();
        update();
    }
    
    //Function to move the snowflakes
    //angle will be an ongoing incremental flag. Sin and Cos functions will be applied to it to create vertical and horizontal movements of the flakes
    var angle = 0;
    function update()
    {
        angle += 0.01;
        for(var i = 0; i < mp; i++)
        {
            var p = particles[i];
            //Updating X and Y coordinates
            //We will add 1 to the cos function to prevent negative values which will lead flakes to move upwards
            //Every particle has its own density which can be used to make the downward movement different for each flake
            //Lets make it more random by adding in the radius
            p.y += Math.cos(angle+p.d) + 1 + p.r/2;
            p.x += Math.sin(angle) * 2;
            
            //Sending flakes back from the top when it exits
            //Lets make it a bit more organic and let flakes enter from the left and right also.
            if(p.x > W+5 || p.x < -5 || p.y > H)
            {
                if(i%3 > 0) //66.67% of the flakes
                {
                    particles[i] = {x: Math.random()*W, y: -10, r: p.r, d: p.d};
                }
                else
                {
                    //If the flake is exitting from the right
                    if(Math.sin(angle) > 0)
                    {
                        //Enter from the left
                        particles[i] = {x: -5, y: Math.random()*H, r: p.r, d: p.d};
                    }
                    else
                    {
                        //Enter from the right
                        particles[i] = {x: W+5, y: Math.random()*H, r: p.r, d: p.d};
                    }
                }
            }
        }
    }
    
    //animation loop
    setInterval(draw, 33);
}