Coinmarket API

I built a thing which stores and displays digital currency market data

Note: this is a deprecated API and doesn’t work anymore but fear not, I’ve moved this general project into a new API and made it a WordPress plugin which you can check out here: https://github.com/haa-gg/Crypto-Price-WP-Plugin

Grab the OG repo and mess around with it here: https://github.com/haa-gg/Coin-Market-API-Example

More specifically, the goal is to create a script which talks to the Coin Market API (https://api.coinmarketcap.com/v1/ticker/), gets the relevant data for all 1000-something digital currencies out in the wild and puts the current values into a SQL database that I can reference later. The live feed was more of a bi-product that I got attached to.

The heavy lifting of this project was to set up a database, write a SQL command to input the relevant data from the API into the database, then set the command to run once a day by means of a cron job.

Here’s the code you need to make the live feed section work, all neat n’ tidy

index.php

Here’s what makes the back end tick:

dbupdate.php (where the real action is)


Evite

Knowing people are invited is the major function

But if that were the only function, then why not 12 point Times New Roman? The other purpose this invitation serves is to give an idea of what Sage is all about– why you would want to meet them at this booth.

The reason is glass. Sage creates an incredibly striking and energy efficient glass that you can control the tint on with the flick of a switch– pretty neat, eh? The invitation works to clue the reader in as to whether they should talk to Sage based on how relevant the product is to them.

If the products are up their alley, they read below for the specifics.


Olafsen Ethics

The Olafsen Ethics Symposium

Is an event held up at UND every year with the intention of demonstrating ethics in business. It was my job to put together a promotional poster for the event and the only specifications I had were to get across the speakers name, and key event info (date, purpose, relevance).

The business administration turned me loose after that and what I decided was the most key information was what this speaker had done. Creating 1.6 million glasses just to help people out catches your attention and gives the reader an idea of what the presentation is going to be about.

I made the whole thing pop by using high contrast colors, a sharp font, and a clear hierarchy of information.


Window LP

G & P Windows feels clean, functional, and to the point

The photos of their work should do most of the talking while the rest of the page words to fill the reader in on the specifics of how the product works and establish a sense of trust.

From a design perspective, the project was quite straight forward: send over some inital mockups to get us talking, adjust the mockups till everybody is happy then move it all into code.

On the coding side, the project was just a treat– the big sets of images played very will with Foundation and its lovely flex display properties. The SASS is really succinct, coming in at just over 400 lines which can be easily shark down to around 300 if I didn’t enjoy my line breaks so much! You can check that out below.

If you want to see the page in action, just head on over to: https://designerofstuff.com/example-window-landing-page/

  
  
  /*================================================================

Content stylesheet

================================================================*/


/*================================================================

Content Universal Styling

================================================================*/

.box {
  height: 310px;
  width: 210px;
  background-image: url('../images/flip1.jpg');
  background-size:cover;
  background-repeat:no-repeat;
  position: relative;
  overflow: hidden;
  border:5px solid #fff;
  margin:0 auto;
}

.overlay {
  background-image:url('../images/flip2.jpg');
  background-size:cover;
  background-repeat:no-repeat;
  height:300px;
  position: absolute;
  width: 100%;
  left: -270px;
  margin-left: 520px;
  bottom: 0;
  transition: left 400ms linear, margin-left 400ms ease-out;
}

.toggleClass{
  left: 0;
  margin-left: 0;
  transition: left 400ms ease-out;
}

.span-darkgray{
  background-color:$gray;
  color:#fff;
}

.span-lightgray{
  background-color:$lightgray;
}


body{
  font-family: 'Abel', sans-serif;
}

h1,h2,h3,h4,h5,h6{
  font-family: 'Anton', sans-serif;
}

.logo-wrap:before{
  content: " ";
  position: absolute;
  z-index: -20;
  top: 0;
  width: 9999rem;
  right: 74%;
  background: #fff;
  height: 100%;
}

.logo-wrap{

}

.header{
  position:relative;
  z-index:100;

  .bbb{
    width:70%;
    margin:0 auto;
    display:block;
  }

  h2{
    font-size:2.0rem;
    color:#fff;
    text-align:right;

    a{
      color:#fff;
      font-size:1.9rem;
      letter-spacing:0rem;
    }
  }
}

.r1-logo{
  position: relative;
  left: 0;
  -moz-animation-name: dropHeader;
  -moz-animation-iteration-count: 1;
  -moz-animation-timing-function: ease-out;
  -moz-animation-duration: 0.3s;
  -webkit-animation-name: dropHeader;
  -webkit-animation-iteration-count: 1;
  -webkit-animation-timing-function: ease-out;
  -webkit-animation-duration: 0.3s;
  animation-name: dropHeader;
  animation-iteration-count: 1;
  animation-timing-function: ease-out;
  animation-duration: 0.3s;
}

h1{
  font-size:2.5rem;
  text-align:center;
  margin-bottom:0;
}

.span-hero{
  background-image:url('../images/hero-bg.jpg');
  background-size:cover;
  background-repeat:no-repeat;
}

.hero{
  /* Permalink - use to edit and share this gradient: http://colorzilla.com/gradient-editor/#000000+0,1a2330+100&0.83+0,0+100 */
  background: -moz-linear-gradient(left,  rgba(0,0,0,0.83) 0%, rgba(26,35,48,0) 100%); /* FF3.6-15 */
  background: -webkit-linear-gradient(left,  rgba(0,0,0,0.83) 0%,rgba(26,35,48,0) 100%); /* Chrome10-25,Safari5.1-6 */
  background: linear-gradient(to right,  rgba(0,0,0,0.83) 0%,rgba(26,35,48,0) 100%); /* W3C, IE10+, FF16+, Chrome26+, Opera12+, Safari7+ */
  filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#d4000000', endColorstr='#001a2330',GradientType=1 ); /* IE6-9 */
  color:#fff;


  ul{
    font-size:1.8rem;
    line-height:130%;

    li{
      margin-bottom:10px;
    }
  }
}

.picbar{
  position:relative;

  .pic-qs{
    position:absolute;
    background-color:rgba(255,255,255,0.8);
    text-align:center;
    width:100%;
    bottom:0;
  }
}

.trust{
  p{
    font-size:2rem;
    text-align:center;
  }

  .trust-list{
    @include justify;
    list-style-type:none;
    
    .tall{
      max-width:120px;
    }

    .wide{
      max-width:200px;
    }
  }
}

.video{
  text-align:center;
  padding: 1rem 0;
}

.gallery{
  padding:1rem 0;
}

.testimonial{

  font-size:1.2rem;

  .test-wrap{
    background-color:$lightgray;
    padding:2rem 1rem;
    border-radius:8px;
    height:100%;
    display: -webkit-flex;
    display: flex;
    -webkit-justify-content: space-between;
    justify-content: space-between;
    -webkit-align-items: center;
    align-items: center;
    list-style: none;
    position:relative;
  }

  .test-wrap:after{
content:"";
    position:absolute;
    top:100%;
    left:25px;
    border-width:30px 30px 0 0;
    border-style:solid;
    border-color:$lightgray transparent;
    /* css3 extras */
    -webkit-transform:skewX(-15deg);
       -moz-transform:skewX(-15deg);
        -ms-transform:skewX(-15deg);
         -o-transform:skewX(-15deg);
            transform:skewX(-15deg);
  }
}

/*================================================================

Content Desktop Styling

================================================================*/

@media (min-width:1024px){
  .hero{
    padding-top:3rem;
    padding-bottom:7rem;
  }

  .offset{
    position:relative;
    top:-6rem;
  }

  .gal-pics{

    img{
      width:24.7%;
      margin:0;
      padding:0;
    }
  }

} 


/*================================================================

Content Tablet Styling

================================================================*/
@media screen and (min-width: 40em) and (max-width: 63.9375em) {

  body{
  
  .picbar{

    .pic-qs{

      h3{
        font-size:1rem;
        padding:.5rem 0;
      }
    }
  }




  .tall{
    width:66%;
    margin:0 auto;
    display:block;
    padding-bottom:1rem;
  }


}

  }

/*================================================================

Content Mobile Styling

================================================================*/

@media (max-width:1023px){

.logo-wrap:before{
  content: " ";
  position: absolute;
  z-index: -20;
  top: 0;
  width: 9999rem;
  right: 60%;
  background: #fff;
  height: 100%;
}

.mobile-call{
padding:.5rem 0;
background-color:$lightgray;

  h2{
    margin-bottom:0;
    letter-spacing:.00rem;

    a{
      color:#000;
    }
  }
}

.headline{
  background-color:#fff;

  h1{
    font-size:1.5rem;
    text-align:left;
  }
}

.span-hero{
  background-image:url('../images/hero-bg-mobile.jpg');
  background-repeat:no-repeat;
  padding-top:15rem;

  .hero{
    background-color:rgba(0,0,0,.5);
    padding:.5rem .25rem;
  }

  .mob-qs{
    padding-left:1rem;

    h2{
      font-size:2rem;
      text-shadow:2px 2px 5px rgba(0,0,0,0.7);
    }

    ul{
      letter-spacing:.05rem;
      line-height:110%;
      font-size:1.2rem;

      li{
        margin-bottom:0px;
      }
    }
  }
} 

.picbar{

  .columns{
    padding:0;
  }

  img{
    width:100%;
  }

  .pic-qs{

    h3{
    font-size:.8rem;
    margin-bottom:0;
  }

  .row{
    margin-right:0;
    margin-left:0;
  }
  }
}

.trust-imgs{

  ul{


    li{
      width:47%;
    }
  }
}

.video{
  .vid1{
    margin-bottom:1rem;
  }
} 

.gal-pics{

    img{
      width:100%;
      margin:0;
      padding:0;
      
    }
  }
}

.testimonial{
  padding-top:1rem;

  .large-4{
margin-bottom:3rem;
  }
}

Woman Lake

A remote Canadian hunting lodge up in Ontario

Womanlakelodgecanada.com has been through 3 face lifts since I took over work on the site way back when.

This round’s goal was to more actively use all the awesome pictures and video footage the hunters and fishermen get when they travel up there.

The place this really shines is in the top area of the home page (better known as the hero region or jumbotron to web nerds). We have 4 slides using images and text I selected with the idea of showing off the wonderful memories made heere and the beastly fish dredged up from the depths of the surrounding lakes.

The biggest technical challenge was getting the video footage used on the first slide to not grind the site to a hault while it loads in which was accomplished by fine-tuning the resolution with a tool called FFmpeg which lets you adjust every little detail of the video format… but it’s used via command line so the usability leaves something to be desired…


U.N. Crisis

Ever want to know what is discussed in the U.N. when something crazy happens?

The University of North Dakota put together a program to simulate that event shortly after Russia invaded Crimea and tasked me with putting together promotional materials that would reflect the tone.

When I think of an international crisis, I get a sharp sense of urgency, danger, and a lot of hard work ahead. I felt the sharp, contrasting colors brought out the urgency while the grit layer helped give it an impression of the danger many people face.

Tech wise, the piece was clean and simple. The fonts, U.N. logo, and solid colors for the background were all vectors which I then used Photoshop to add a layer of grit to using a hi-res grunge texture and a multiply filter.


Regex Phone Fun

Websites are great and all but scripts can be a blast all on their own!

Here’s a phone flipping script I have been working on that will find every phone number on a page and flip them all to the same one, which is really handy for adwords tracking.

Just read through the code comments to see how the whole thing works, my end goal is to make it take in a url query, grab that number from a stored array and flip all of the numbers to that.

If you want to see it in action, check out: https://jsfiddle.net/uohx1fo3/15/

<?php  

jQuery(document).ready(function () {

//Throw the phone number you want everything to flip to right here
var swapTarget = '123-456-7890';

//This is the bit that recognises a phone number
var regex = /(((\(\d{3}\) ?)|(\d{3}-)|(\d{3}\.))?\d{3}(-|\.)\d{4})/g; 

//Tells the script where to search in the document
var text = jQuery("body:first").not('script').html();

//Makes the text var look for our regex and swap it for our new number 
text = text.replace(regex, swapTarget);

//Turns the text var loose on the DOM to switch out the phone numbers
jQuery("body").html(text);

/*===============================================
We've made it half way and nothing has erupted into flames, take a moment to pat yourself on the back and then check below to make sure you have the right vars set.
===============================================*/

//Format the swap target for an href
//swapTarget.text( swapTarget.text().replace('-', '') );
var swapTarget = '"tel:1' + swapTarget + '"';
console.log(swapTarget);

//Now to handle those pesky href numbers with a different selector...
var regex = /((\"tel:((\d{11})|(\d{10})|(((\(\d{3}\) ?)|(\d{3}-)|(\d{3}\.))?\d{3}(-|\.)\d{4}))\"))/g;

//Makes the text var look for our regex and swap it for our new number 
text = text.replace(regex, swapTarget);

//Fire the main cannons!
jQuery("body").html(text);


});

?>

Lawfirm LP

Law firm landing pages can have a great deal of dynamic content in them

The firms are also keen on looking dignified and professional so the pages can get to be quite a handful!

If you want to see this puppy in action, check out: https://designerofstuff.com/law-lp and play with the device types to see all the responsive love put into the page.

Most of the exciting bits involving putting locations in different arrays does not get used here as we don’t have addresses. However, we can swap the headline region by adding a ?camp=1 or ?camp=2 (https://designerofstuff.com/example-law-lp?camp=1) query to the end of the URL. We can also change out the geographic region from the default of “Minnesota” for something a bit more exciting like “Camelot” by adding a url query of ?geo=camelot (https://designerofstuff.com/law-lp?geo=camelot).

Take a look at what the dynamic php tends to look like to render proper geographic and headline info:

<?php  

//Setting phone as a var
$phone = "<a href=\"tel:1\">111-111-1111</a>"; 

$phonelink = "1";?>

<?php 
//Assign the $geo variable to whatever the ?geo= query is equal to
$geo = $_GET['geo'];

//Put all cities in a single array
$geo_arr = array ("minneapolis", "moscow", "camelot", "chicago", "los-angeles");

//Put the geos with small address sets in this array
$small_arr = array ();

//Put any small address geos with 2 addresses in here
$stack_arr = array ();

//This bad boy makes sure the geo query is a legit one and not some sketchy bit of SQL
if (in_array($geo, $geo_arr)){

    $geo_pos = array_search($geo, $geo_arr);

    $geo_active = $geo_arr[$geo_pos];

            //Detect if the geo has numbers in it and if it does, then go do some special formatting to it
    if (strcspn($geo_active, '0123456789') != strlen($geo_active)) {

        switch ($geo_active) {

//Throw the special snowlfake formatting cases in here
            case "twin-123":
            $geo_txt = "Twin Cities";
            break;

            case "twin-456":
            $geo_txt = "Twin Cities";
            break;

            case "twin-789":
            $geo_txt = "Twin Cities";
            break;
        }

    } 

    else{

//If the geo case is not a special snowflake, then just swap the dashes for spaces and capitalize verything properly
        $geo_txt = str_replace("-", " ",$geo_active);

        $geo_txt = ucwords($geo_txt);

    }
    
}

else{
//Putting in a default geo value in case somebody puts in a geo query we don't like or flubs the spelling
        $geo = "minnesota";

        $geo_txt = "Minnesota";
        
    }

//Checks if the active geo is supposed to be small address format
$format_var="big-addr";

if(in_array($geo_active,$small_arr)){

    $format_var="sm-addr";

}

//Extra formatting junk for small addresses w/ more than 1 address
$stack_var = "";
$stack_fmt = "";
if(in_array($geo_active,$stack_arr)){

    $stack_var="-stack";
    $stack_fmt="stack";

}

?>

<?php

//Uses gets device type in case we want something to render differently
$iphone = strpos($_SERVER['HTTP_USER_AGENT'],"iPhone");
$android = strpos($_SERVER['HTTP_USER_AGENT'],"Android");
$palmpre = strpos($_SERVER['HTTP_USER_AGENT'],"webOS");
$berry = strpos($_SERVER['HTTP_USER_AGENT'],"BlackBerry");
$ipod = strpos($_SERVER['HTTP_USER_AGENT'],"iPod");
$ipad = strpos($_SERVER['HTTP_USER_AGENT'],"iPad");

if ($iphone || $android || $palmpre || $ipod || $ipad || $berry == true) { 
           $device='mobile';
    } else {
         $device='desk';
    }

?>

<?php

//gets the &camp query and populates the headline with it
$haa_query_2 = $_GET['camp'];

switch ($haa_query_2) {

    case "1":
    $camp = 'Need Expert Legal Assistance?';
    break;

    case "2":
    $camp = 'Out To Fight A Ticket?';
    break;

    default:
    $camp = 'Are You In Trouble With The Law?';

}
?>

<?php 

    //Extra classes for the LP fed in as body classes
$extra_classes=array($device,'generic-law', $format_var, $stack_fmt); 
?>

HVM Map

Sage Electrochromics opened a new high tech facility 3 times the size of a football field

Tours of the facility are a very common thing but they did not have a map yet so it fell to me, the graphic design/ marketing intern to come up with something.

I started off by digging through the facility blueprints which turned out to be total overkill as they gave details such as where every indivdual cubicle would go and lots of information for plumbing/electrical/ HVAC which would be nice if the goal were to plan some Mission Impossible style heist but less so when you are trying to put something together so visitors know where they are.

Part 2 was to walk the facility personally and sketch it out by hand, this wound up taking 3 trips around the facility in stiff business shoes resulting in my feet looking like they had started a scrap with a belt sander. The other result of my wanderings was a good idea of the layout and spacing of the facility which I then started putting into Illustrator.

The only tricky bit left was to make the whole thing feel up to the standards of an international high tech company. If you look over their other work, you can see they put a high value on simplicity and brightness and I reflected that in my work.

The end result was something everybody was really happy with and is still being used on tours to the best of my knowledge!

Sage High Volume Manufacturing Exterior Map

Here’s a picture I took of the building:

Actual photo of sage HVM front

I know this does not really pertain to the map, but I’m really proud of the photo!


Auto Srcset

A Handy Little Widget That Builds And Loads Images Based On Device Width

So there’s this nifty little property in HTML that will let the browser determine which size image to load based on how large it needs to display it. The only hassle is that these images are tedious to build since without any automation, you have to save each image at each different size. This is about as much fun as cleaning out an attic full of bats with an air horn so I came up with a handy way to make the computer do all the heavy lifting for me (now if only I could make it deal with the bats…).

In a nutshell, my widget uses a single line in a command prompt to trigger a process which feeds all images in a directory through a program called GraphicsMagic that resizes it to your specifications and outputs the images to their own directory. Once we have the image files, we can easily reference all of them using a simple PHP function detailed below.

Now for the nitty gritty on how each bit works!

Gulp/ Node Package Manager

The dependencies are crazy simple, this is all you need in your package.json

{
  "name": "RespImg",
  "version": "1.0.0",
  "description": "Image Sizing Example",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "glen",
  "license": "ISC",
  "devDependencies": {
   
    "gulp": "^3.9.1",
    "gulp-concat": "^2.6.0",
    "gulp-responsive-images": "*"
    
  }
}

All our NPM does is download Gulp, Gulp Concat (not necessary), and the responsive image plugin (you do need to manually download the binaries though).

As for our Gulp file, the basic setup is really simple:

var gulp = require('gulp');
var responsive = require('gulp-responsive-images');
 
gulp.task('responsive-img', function () {
  gulp.src('assets/images/*.{png,gif,jpg}')
    .pipe(responsive({
       '*': [{
        width: 300,
        suffix: '-s'
      }, {
        width: 500,
        suffix: '-m'
      }, {
        width: 600,
        suffix: '-l'
      }],
      
    }))
    .pipe(gulp.dest('assets/images/adaptive'));
});

If you open a command line in your project folder after the NPM install and type “gulp responsive-img” it will generate new copies of all images in our specified folder!

Handy Dandy PHP Function

We still need a good way of writing all the mind numbing srcset markup which is where my PHP function comes into play!

     

            

             class="responsive"
                     alt="Some text"/>

                     

If you have any interest in a working set of files, you can download them here!


Website copyright 2024. All rights reser-- Nah, I'm just playing with ya, the whole thing is up on an open repo on github!

Feel free to use it, break it, fix it, trash it, change it, mail, upgrate it.