using SVG on your web

SVG Scalable Vector Graphics is an XML-based vector image format for two-dimensional graphics with support for interactivity and animation. Because of its scalable native, especially with very high graphical screens(example: retinal screen for Mac) these days, we need solutions for images or graphics to be display on these screens.

Well these are many ways to resolve these, such as using large image 2x of your current size and scale down to smaller dimension on web, or for icons we use Font-icons. Since SVG was widely used on most modern browsers including IE9, and its pretty lightweight we should make use of it.

How we can use SVG on the web and why we will use it.

We are include/embed svg like what we can to images.

on HTML: we can include as an image or XML code, for example:

1
<img src=“mysvgfile.svg” alt=“svg file” /> // if you need to scale add width and height…

or you want to use XML, the good part using xml is you have control over some svg settings such as fill, colors and so on…

Well, one thing you need to make sure when you are using xml is that if your web page contains multiple same svg that I would suggest you embed them as image because the image file will only be downloaded 1 time, whereas xml will add more weights to html when it was downloaded from server.

1
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><path fill=“red” d="M12 3C8.032 3 7 4.8 7 7.8c1.642-3 4.157-2.795 5-2.795V3zm0-2v6l3-3-3-3z"></path><path fill=“green” d="M14 7v4c0 1.113-.9 2-2.01 2H4.01C2.9 13 2 12.105 2 11V5c0-1.113.9-2 2.01-2H7.2c-.597.56-1.05 1.23-1.384 2H4v6h8V9l2-2zm-3-2h-.04l.04-.01V5z"></path></svg>

SVG can also be included from css side like what we did to images normally.

1
2
3
4
5
6
.container {
  background:url(mysvgfile.svg) no-repeat;
  background-size:100px 100px; // adjust svg size
  width:100px;
  height:100px;
}

Alternatively we can also include svg as xml from css:

1
2
3
4
5
6
.container {
 background: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='30' height='30'><circle cx='15' cy='15' r='10' /></svg>")  no-repeat;
  background-size:100px 100px; // adjust svg size
  width:100px;
  height:100px;
}

Well this works well in most browsers, however Internet Explorer refuses to work with it, so we need to convert them into base64, you can read more about base64 on: http://stackoverflow.com/questions/201479/what-is-base-64-encoding-used-for

1
2
3
4
5
6
.container {
 background: url("data:image/svg+xml;charset=utf-8;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIzMCIgaGVpZ2h0PSIzMCI+PGNpcmNsZSBjeD0iMTUiIGN5PSIxNSIgcj0iMTAiPjwvY2lyY2xlPjwvc3ZnPg==")  no-repeat;
  background-size:100px 100px; // adjust svg size
  width:100px;
  height:100px;
}

There are many svg to base64 convertor out there, one of it I use it a lot is: https://dopiaza.org/tools/datauri/index.php

Optimizing Svg files is rather easy, we mentioned svg is just XML file, so you can open it on Text editors such as sublime and so on, you will see lines of code, and as we all know to reduce file size for code is to keep them into one line, and this apply to SVG too, just convert them into one line and you save 40-70% of file size, or if you want to optimise them in bulk, you can use open source tools “svgo” from github https://github.com/svg/svgo, either in CLI or GUI: https://github.com/svg/svgo-gui

Fixing a broken image alt

When your image is broken in browser, it will show Alt text from the image attribute if you are using

1
<img src=“yourimageurl” alt=“Image descriptions” />

a quick fix for this is really simple, change your image background and color to transparent.

1
2
3
4
img {
  color: transparent;
  background-color: transparent;
}

that is it, and enjoy.

gmail clipping float right

While doing email marketing and when you send out email with long contents and its annoying to see gmail clipped it and it ask you to click to view entire email Screen Shot 2016-06-28 at 11.05.41 AM

And yet for me happened to have this problem, this message goes to right side of my content. Screen Shot 2016-06-28 at 11.10.00 AM

After playing around for sometime, all you need to do is add overflow:auto to your tag, after all Google will convert this to tag to div.

CSS3 right offset

Did you realised that when you need to place your background image on the right side and it always touches the corner of the right, CSS3 to save, you can actually do a offset of right by doing this:

1
2
3
  .class {
    background-position:right 10px center;  // this will offset a 10px from right side.
  }

Magento 2 install sample data error

If you ever faced magento 2 installing sample data error using MAMP on local,

1
2
3
4
5
6
7
Zend_Db_Adapter_Exception]

SQLSTATE[HY000] [2002] No such file or directory

[PDOException]

SQLSTATE[HY000] [2002] No such file or directory

here’s a solution for you, provided you are using composer to install magento, this happened to me while updating the sample data, php magentoFolder/bin/magento setup:upgrade

1
ln -s /Applications/MAMP/tmp/mysql/mysql.sock /tmp/mysql.sock

Display all products in woocommerce admin

Woocommerce is good start for ecommerce beginners, easy to install and get start with, I was using CSV importer to import thousands of SKU however I realised that it will not update the current tax that you have. So in order to fix that we need to update the tax again in each product, you can do quickly using bulk action, and click Edit

Screen Shot 2015-08-30 at 2.15.42 pm

 

By default woocommerce only allow you to show 20 products per page, you can open up the screen option button at the top right, and change the number of items per page, easy fix.

Screen Shot 2015-08-30 at 2.18.31 pm

 

New Meteor launch page package

I wrote a quick launch for meteor, that anyone can quickly add a launch page on meteor, you can also change the contents from as the options.


https://github.com/maxlibin/watcfylaunch

watcfy

Add active state on meteor.js menu

Imaging you have already created a menu in meteor js framework, somewhere in your header, something like this

1
2
3
4
5
<ul>
    <li><a href="/home">Home</a></li>
    <li><a href="/about-us">About Us</a></li>
    <li><a href="/contact-us">Contact Us</a></li>
</ul>

SO you want to make the menu to be active when you are on current route, one of the simple solution is to create a template helper, Register a template helper by adding a file on client folder called helper.js

then inside helper.js register a template helper (Template.registerHelper), which previously called UI.registerHelper.

1
2
3
4
5
6
7
  Template.registerHelper('isActive', function(){ // take in some params to determine the stats
    // assume that you are using iron-router, if not please install "meteor install iron:router"
    var currentRoute = Router.current().route.getName();
    if(currentRoute == parms){
      return "current";
    }
  })

with this helper, you can add to your template.

1
2
3
4
5
<ul>
    <li class="{{isActive "home"}}"><a href="/home">Home</a></li> // Notice the home as argument which you defined on your iron router name.
    <li class="{{isActive "about-us"}}"><a href="/about-us">About Us</a></li>
    <li class="{{isActive "contact-us"}}"><a href="/contact-us">Contact Us</a></li>
</ul>

now your li class will return active when you are on that page/route.

Becareful with jquery on or bind event.

When you do jQuery and sometime you would bind some functions on an event outside appended DOM elements, and rerun the function again like this:

1
2
3
4
5
6
7
8
9
10
11
12
<ul>
    <li>
        <p>test</p>
    </li>
    <li>
        <p>test</p>
    </li>
    <li>
        <p>test</p>
    </li>
</ul>
<button></button>

for example we want to change the text to something else when we click on each of the li, maybe lets change to “run test …”;

1
2
3
4
5
6
function changeText(){
  $(this).find('p').text("run test");
}

$('li').on('click', changeText);
//$('li').bind('click', changeText);

now you want append a new li and allow function on that appended li like this:

1
2
3
4
$('button').click(function(){
  $('ul').append('<li><p>New text</p></li>');
  $('li').on('click', changeText);
})

this situation it works well, however what actually happened is that you create the function two times on each event (‘click’), if you click button again second time, you create three function for each li click, and so on…
so what you want to do is off the click first, then on again, like this.

1
2
3
4
5
$('button').click(function(){
  $('li').off('click');
  $('ul').append('<li><p>New text</p></li>');
  $('li').on('click', changeText);
})

let me know if you have anything to comment below.

Meteor Async from server to client

Sometime you want to do async call from api and make call or reactive on the client side, so how do you do it?
first create a method on server side, I would always recommend using methods rather allow / denied from client side, lets give a method name asyncMethods

1
2
3
4
5
6
7
8
9
10
11
12
13
// Server side
Meteor.methods({
  asyncMethods: function(){
    var url = "http://example.net/api/" // your api url
    HTTP.get(url, function(err, res){
      if(err){
        throw new Meteor.error('apiError', err.reason);
      } else {
        console.log(res);
      }
    })
  }
})

Ok now run this client side method call

1
2
3
4
// Client side
Meteor.call('asyncMethods', function(err, res){
  console.log(res);
})

you will notice 2 things, on your console.log for client will become undefined, and on server side log you properly see some results.
so lets say you want to return result after api was called, meteor provided a very helpful method call Meteor.wrapAsync(), which basically returns your async call to synchronous call, so you could call it from client side, change your server code to this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// Server side
Meteor.methods({
  asyncMethods: function(){
    var url = "http://example.net/api/" // your api url
   
    function asyncCall(){
      HTTP.get(url, function(err, res){
        if(err){
          throw new Meteor.error('apiError', err.reason);
        } else {
          return res;
        }
      })
    }
    var syncCall = Meteor.wrapAsync(asyncCall);
    var res = syncCall();
   
    // now you can return the result to client.
    return res;
  }
})
Page 1 of 912345...Last »