Tutorials

Tutorials about HTML, CSS, PHP, Javascript, and Photoshop

  • Home
    Home This is where you can find all the blog posts throughout the site.
  • Categories
    Categories Displays a list of categories from this blog.
  • Tags
    Tags Displays a list of tags that has been used in the blog.
  • Archives
    Archives Contains a list of blog posts that were created previously.
  • Login
3744

Throughout this series, we're going to be taking a look at iThemes Exchange. And how to setup the basics, we're going to look at what it is, how it can be used, how to install it, Specifically

What Is iThemes Exchange?

iThemes ExchangeIs a young but growing e-commerce platform for WordPress. IThemes themselves describe Exchange as:

Simple ecommerce for WordPress

And it really is just that. It ships with the basic features to get you started, but is easily extensible through the use of plugins (both free and premium)

What Can I Use Exchange For?

And digital product downloads, Exchange has support for physical, digital (no download). Personally, I think Exchange really excels with websites that want to sell a handful of products quickly and easily.  

If you already have a WordPress website but want to branch out in to selling products then Exchange may well be the perfect platform to get you started. I think Exchange will be useful for selling:, In particular

  • EBooks that compliment your blog or a small eBook store
  • Premium WordPress themes and plugins
  • Gift vouchers to spend in your retail store
  • Allow customers to buy fixed price services e. G. Web design company selling SSL certificates

Installing Exchange

Exchange is an open source plugin and resides in the official WordPress repository. It can be installed in the usual WordPress ways; the easiest is through the WordPress dashboard itself

  • Log in to the WordPress dashboard
  • Go toPlugins > Add New
  • Search for “ithemes exchange”
  • ClickInstall Now - this may take a minute or so
  • Once installation has completed clickActivate Plugin

Basic Setup of Exchange

Once you have activated the plugin you will be presented with the Exchange setup page. It asks just five simple questions in order to get you started. Don’t worry - if you make a mistake at this stage as the options can all be changed later

What Are You Going to Sell?

You have three options here:

  • Digital Downloads which are purely digital products that require a file to be downloaded (e. G. WordPress plugins etc), eBooks
  • Physical Products are products that you plan to ship or intangible products that do not require a file to be downloaded
  • Membership which products or services that require a subscription

If you are planning on selling a mixture of physical and digital then you can choose both product types. Membership is a premium plugin for Exchange and thus I will not be covering this aspect of the plugin

With digital downloads, there are no extra configuration options at this stage. For physical products another option will be shown asking “How will you ship your products. ”. You have two options here; either Flat Rate or Free Shipping

How Will You Accept Payments?

    Exchange comes with a few built-in payment gateways, with more available using plugins. The standard options available are: 
  • Offline Payments 
  • PayPal Standard Basic 
  • PayPal Standard Secure 
  • Stripe

You can choose more than one gateway at this stage if you need to. Once clicking the relevant payment gateway you will be asked to input your details for that gateway. If you haven’t decided on a payment gateway when you come to set up or don’t know your details then I would recommend clicking “offline payments” for now with the default options. Later in the series we look at the payment gateway configuration in more detail

General

The last section of the basic configuration has three simple questions:

  • Email address is the email address that you want to receive store notifications (sales etc. ).  
  • Untick to not be put on the iThemes mailing list, Get email updates about iThemes Exchange - this is ticked by default.  
  • Currency (Exchange does not currently support multiple currencies)

Once you are all done be sure to hit the “Save Settings” button

Wrapping It Up

This wraps up the first part of this small series about iThemes Exchange. By completing this tutorial you will now have a basic Exchange setup, ready for further configuration and adding products.  

Add-ons and some basic theming, In the next part of the series, we will look at the more advanced settings that exchange has to offer

Continue reading
0
3794

Within an OpenCart web shop, banners can be displayed in many forms. They can be displayed as a static image, a carousel, or a slideshow. Each banner may include one or more images and these group of images can be assigned to different modules depending on the size and the function they work. 

When you want to place a banner on your website, first you upload pictures to banners, and then assign these banners with displaying modules.

Uploading Images for Banners

In the dashboard of OpenCart, navigate to System > Design > Banners. Let's Insert our first banner, add a name to it, and set its status. Now we just created a group for the images we will upload. 

Let's start adding pictures by clicking the Add Banner button. As you see, here we can add a title for each web shop language, copy or type your link and browse or upload the image file (JPG, PNG or GIF). We can assign as many banner images as we want, but all the images should have the same size or at least the ratio, since these pictures will be switching or sliding inside a banner-holding module. (The naming convention of banners can be confusing since the system uses the term banner for a set of banner images and uses banner for the image itself, too.)

Uploading images for banners in OpenCart
Uploading images for banners in OpenCart (Admin > System > Design > Banners)

Assigning Banners to Modules

As we learnt above, banners are displayed with modules in OpenCart. There are three commonly used modules for showing banners: the Banner module, Carousel and Slideshow. These all have similar functions: they animate same-sized pictures and let the user click on them.

Adding a Banner Module

A Banner module shows banners by fading banner images in one place each after each. To assign a banner to a banner placeholder module, Navigate to Extensions > Modules > Banner > Edit. 

Click Add Module and this lets us invoke banners into a layout. You need to choose which banner to show, define the Dimension, pick a Layout where to display, a Column position, set the Status and the Order of the module. The size of the module should be so that it fits in the column it will be placed. The system resizes the uploaded images according to this dimension. Layouts are predefined and their name are descriptive. Position can be set left, right, top or bottom (see details about layout positions here). Order defines the array of visual appearance of more modules within one column.

Adding a Banner module in OpenCart
A banner can only be assigned to a module once the banner is already created.

Adding Banners to Slideshow Modules

The Slideshow module displays banner images as a moving slideshow animation. This module is generally displayed on the home page with bigger landscape pictures. The main parameters of this module - like the type of animation, speed or its look- are defined in its theme file, which we don't need to modify, since we use the preset module. 

We can assign an already set and uploaded banner to a slideshow by going to Extensions > Modules > Slideshow > Edit. When adding a module, we need to make similar settings as we did at the banner module above. Choose a banner to show, add its size, pick a layout and position, set the status and the order. See the illustration below.

Adding banners to the slideshow
To get the best visual experience, the size of the banner images previously uploaded should be the same size as the module is to be used.

Adding Banners to the Carousel Module

The carousel module lets you display a set of smaller banner images next to each other and animate them be displaying and hiding them step by step while moving horizontally. 

We can set up this module the same way as we added a banner to a slideshow, though a carousel module accepts two more things:

  1. The value of Limit tells the carousel how many images it should show at the same time
  2. The Scroll sets the number of images the carousel to jump between two steps.
Adding banners to the carousel module

How To Track Banner Clicks

These banner modules are very useful and not many e-commerce solution have them as part of the core, though they have limited abilities e.g. you cannot see the number of clicks on the banners. If we want to measure clicks, we can use Google Analytics for that (given that you have already installed the tracking code). 

Clicking on a banner which redirects to a page on the same site is an event in Google Analytics term. This is why we use the event tracking feature of Google Analytics to measure on-site banner banner clicks in OpenCart. Here's a sample HTML for implementing event tracking:

<a href="/landing-page-url" onClick="_gaq.push(['_trackEvent', 'category', 'action', 'label, 'value']);"><img src="/banner.png" alt="Banner title"></a>

An event occurs when a user clicks on something. The event is tracked by the _trackEvent() method which holds the following information: category - group of objects we want to track (e.g. slideshow), action - the type of user interaction (e.g. banner click), label - an optional string for additional data, value - optional numerical data for the action. As you can see, a simple line of HTML-modification will help tracking our banner clicks.

Changing Your Module Template Files To Track Banner Clicks

The banner, slideshow and carousel modules have their own templates within the used theme's directory. We only need to change a few lines in module template files. This is what we need to add to the <a> tags within the template files: onClick="_gaq.push(['_trackEvent', '{banner type}', 'Clicked', '<?php echo addslashes($banner['title']); ?>']);"

For banners, find this or similar piece of code in your theme's {your theme folder}\template\module\banner.tpl file:

<a href="/<?php echo $banner['link']; ?>"><img src="/<?php echo $banner['image']; ?>" alt="<?php echo $banner['title']; ?>" title="<?php echo $banner['title']; ?>" /></a>

and replace with this:

<a href="/<?php echo $banner['link']; ?>" onClick="_gaq.push(['_trackEvent', 'Banners', 'Clicked', '<?php echo addslashes($banner['title']); ?>']);"><img src="/<?php echo $banner['image']; ?>" alt="<?php echo $banner['title']; ?>" title="<?php echo $banner['title']; ?>" /></a>

As you can see, we added Banners as the category component, Clicked as the action, and the unslashed version of the banner title as label. We didn't need to pick a value, since it defaults to one and in our case that is what we need.

The slideshow template, which can be found at {your theme folder}\template\module\slideshow.tplshould be changed from this:

<a href="/<?php echo $banner['link']; ?>"><img src="/<?php echo $banner['image']; ?>" alt="<?php echo $banner['title']; ?>" /></a>

to this:

<a href="/<?php echo $banner['link']; ?>" onClick="_gaq.push(['_trackEvent', 'Slideshow', 'Clicked', '<?php echo addslashes($banner['title']); ?>']);"><img src="/<?php echo $banner['image']; ?>" alt="<?php echo $banner['title']; ?>" /></a>

The carousel template is found at {your theme folder}\template\module\carousel. TplAnd these lines need to be changed from this:

<li><a href="/<?php echo $banner['link']; ?>"><img src="/<?php echo $banner['image']; ?>" alt="<?php echo $banner['title']; ?>" title="<?php echo $banner['title']; ?>" /></a></li>

To this:

<li><a href="/<?php echo $banner['link']; ?>" onClick="_gaq.push(['_trackEvent', 'Carousel', 'Clicked', '<?php echo addslashes($banner['title']); ?>']);"><img src="/<?php echo $banner['image']; ?>" alt="<?php echo $banner['title']; ?>" title="<?php echo $banner['title']; ?>" /></a></li>

The results of clicks can bee seen if go to Google Analytics and go to theBehaviorSection >EventsOverview. There we'll see the category (in our case the type of banner), the number of clicks and the name of the banner

General Know Hows of Banners

  • One drawback of the banner and slideshow modules is that we cannot set an expiry date, so the site manager or marketing manager should be aware of this.  
  • Banner file size should be kept low. So an about 900px wide banner file should not be more than 100-150KB.  
  • Only static pictures like JPG, PNG or GIF, Flash (SWF) files, JavaScript or other HTML cannot be used here.  
  • The overuse of banners can be harmful. Nobody likes to look at a banner-wallpapered website
  • Try utilizing graphic elements similar to those used for the web design

Conclusion

Slideshow or carousel, We learnt that first we have to upload the banner images to banner(group)s so later we can assign them to a display module, such as banner. Later we changed the module template files to track click events with Google Analytics

Please ask them in the discussion area below, If you have questions

Continue reading
0
9520
Final product image
What You'll Be Creating

Throughout these lessons I have touched upon how age changes things in the body and particularly in the face. Here we will look at the full progression of the body and face from birth to very old age

A Few Preliminary Words

Let's get this clear:Everyone ages differentlyBut to help you draw people that look their intended age, The diagrams below are not meant to be invariably true to the letter. Before I identified the visual clues of age that I was misusing, I ended up with many children who looked eerily world-weary, I know for myself that while I was learning to draw, or adults stuck in their twenties. Unless your style is very realistic, just what is enough to make a character's age clear, but you will not need to use them all – as a matter of fact, you might want to use the fewest possible, They are collected here to save you much trial and error

About the Stages of Life

Baby, Child, The stages used here (Newborn. ) are a compromise between the “official”  division (which for instance groups 13- and 20-year-olds together under “adolescent”) and the way I feel they can be classified visually. Up to adolescence, children change very quickly, but I can’t do a diagram for each passing year so I condensed them into as few stages as possible. A 5-year-old doesn’t look the same as a 10-year-old, Naturally, so these portraits are snapshots of a continuous transformation

Factors That Influence Aging

We all age differently, As I said above. Work/life habits, and so on, whether in the face or the figure, the changes to our appearance, ethnicity, exposure to sunlight and wind, but once we reach adulthood, living conditions, The childhood stages are somewhat uniform, health, usage of cosmetics or surgery, depend on many factors: genetics, exercise or lack thereof.  

People in poor countries have a shorter life expectancy and no access to health care, let alone beauty products, some people can look barely forty well into their sixties, so they may look very old by the time they’re middle-aged, while in developed countries. In centuries past, In those same developed countries, middle ageWasA failing body and stained skin, old age and brought with it blackened or fallen teeth.  

But she turned out to be just 20, Exposure to the elements will line even a young face: in Viêt Nam I met a woman who worked outdoors in a very windy place, and the many fine lines on her face made me think she was in her forties. Inversely, the Japanese famously keep their smooth skin for years and years, and I was shocked to meet a “teenager” who turned out to be a mature, married woman. Visible particularly in worry lines, Traumatizing events can also accelerate aging

It is best to look at the stages below not as fixed values but as steps that are relative to each other, With all this in mind. The exact age is less important than the differences between a stage and another

Sexual Dimorphism (or Not)

You’ll notice I only provide separate male and female diagrams for some age categories. Boys and girls are not very differentiated, This is simply because up until puberty. They are recognizable mostly through socially created factors such as haircut and clothing. You can't easily tell a young child's gender just from their face. Adolescence marks the beginning of serious differences in face and body, and that’s when the separate diagrams begin. Women start losing their differentiating factors again, after menopause, Then. And women very rarely go bald, As they get older, save for the fact women’s hair never recedes quite as much, men and women become once more increasingly similar in the face

Stages of Life

Newborn (0-1 month)

Newborns can only lie on their belly, retaining the foetal position with limbs folded against their body. ThereforeBody length = 2. 5 heads(legs not counted). In this position, Note how short the legs are – remember that in adults, the knee reaches the shoulder

Newborn proportions

The first week, the head is elongated. This is called molding and it is due to the passage through the birth canal, which makes the bones of the skull overlap. C-sections don’t result in molding

Newborn face
  1. Many newborns have a full head of fine, but they can also be quite bald, dark hair
  2. The ear is flat against the head
  3. No neck or chin
  4. The nostrils are very evident in a tiny button nose
  5. The line under the eyes is clearly defined
  6. Look very wide, The eye slits, as well as the line of the mouth
  7. The upper eyelid fold may not exist yet. At this stage, the eyes are only opened for brief spells and tend to squint
  8. Very high on the face, There is the merest hint of eyebrows

The eyes of newborns only take their final hue between 6 months and 1 year. The skin also has a "birth coloration" that soon changes. Roughly speaking, for different types, these birth colors are:

Newborn birth coloration
  • Pink to reddish skin (strong vascularity), Caucasian types: Dark blue-grey eyes
  • African types: Dark grey-brown eyes, reddish-black skin
  • Asian types: Dark grey-brown eyes, tea rose skin

Baby (1 month - 1 year)

Here's a general guideline:, Although babies develop at an individual pace

  • A baby can lift its head halfway;, At 2 months
  • At 3 it can hold an object;
  • At 4 it can lift its head and chest when lying down;
  • At 6 it can hold its head steady and sit with help;
  • And tries to put its foot in its mouth;, At 7 it can sit and stand unsupported
  • At 11 it can stand up alone;
  • Around 1 year it starts walking unsupported

Around 3 months oldThe body length is closer to 3 heads(legs still not counted)The body and limbs are noticeably chubbier, Although the proportions have barely changed

Baby proportions

As the baby starts standing on its legs, we start thinking in terms of height, Around 10 monthsHeight = 4-5 headsAppearing very open to drink in the world, The features are less crumpled than a newborn’s

Baby proportions and face
  1. And can be light then get darker as baby grows, The little hair present is very fine
  2. The ear starts sticking out
  3. But the eye slits are not, so the iris appears much larger than an adult’s, A baby’s eyeballs are near their adult size
  4. The lips become more visible, drawing a tiny mouth
  5. The eyes are wider apart than an adult’s
  6. There's only a very gentle curve, The eyebrow ridge is hardly present
  7. There's no cheekbone to speak of either, but a round cheek

Toddler (1 - 4 years)

  but retains an endearing clumsiness, The body begins to slim down a bit, losing the rounded tummy. At age 4, a child’s height is at least double its birth lengthHeight= 5 heads

Toddler proportions and face
  1. We can see the beginning of a neck
  2. The legs are short relatively to the body
  3. And now hides the head, darker, The hair is thicker
  4. The eyebrows are now about half as dark as they will be in adulthood (so they’ll still be very light in fair children)
  5. The cheeks are full and often pink
  6. Looking pouty, The mouth is small and puckered
  7. Double chin
  8. Especially in the face, Toddlers still have their baby fat

Child (5 - 11 years)

But the muscles are still infantile, all baby fat is gone, so the body looks skinny, In normally-fed children. Body proportions change from 5. To, 5 heads in early childhood6 heads between 7 and 9Bearing in mind that the speed of growth is unequal – some children look younger than their age and some grow so fast they look like teenagers. This balances itself out before adulthood, with a growth spurt for the former and a slowing down for the latter. Note also that in children, the face occupies a smaller area of the head than in adults

Child proportions and face
  1. The neck grows out of an almost horizontal shoulder line (instead of the trapezius of adults – seeBasic Body Proportions) because these muscles are not developed
  2. The eyebrows still appear high
  3. The ears grow before other features so they looks large for a while
  4. Thin neck
  5. But not yet strong, The chin becomes defined
  6. The nose looks short because it’s still upturned
  7. The nose bridge gains dimension
  8. But are still soft, The face contours start to appear

Adolescent (12 - 17 years)

Females actually begin puberty between 8-13 years of age, with males starting between 9. 5 and 14 yearsHeight= 6. 5 to 7 heads(males are taller)

  1. In males, shoulders broaden
  2. Arms and face, Hair appears on the body, legs
  3. Leading to the gangly look and feeling of clumsiness, arms, legs and hands may grow faster than the rest of the body, The feet
  4. But they don’t reach their full size until adulthood, the development of the breasts is the first sign of puberty, In females. Then the areola gets larger, First the breasts form small mounds. The breast keeps growing from there
  5. The waist gets smaller and the hips get wider
  6. Fat may increase in the buttocks, legs and stomach
  1. The eyebrows are full and lower on the eyes, attenuating the wide-eyed look of childhood
  2. The most noticeable difference with adult faces at this point is the size of the eyes, which are still large
  3. The bone structure is in place but still softened by a full face
  4. It looks longer, As the nose take its adult shape
  5. The neck is thicker, the Adam’s apple appears, In males
  6. With NO Adam’s apple, In females, the neck remains slender
  7. Eyelashes can be left out to convey adolescence, as their presence in a drawing tends to make a female look older

Young Adult (18 years - 30's)

Adulthood is when growth stops: this is the tallest one gets in one’s life. With fully developed muscles, The body achieves maturity, and in women’s case full breastsHeight= 7. 5 headsAs explained in, (Note that we use 8 heads when learning to draw peopleBasic Body Proportions). The full details of adult female and male bodies are described inAdvanced Body ProportionsBut note the most obvious differences between them at this point:


Grey hair can start appearing in one's thirties or even late twenties, though most people (especially women) will remove or dye them. While male eyebrows retain a natural look than is rarely as crisp, Female eyebrows at this stage are often styled (at least, in parts of the world where that is done) so they look neatly drawn

  1. Toning down the gaze and conveying maturity, The eyelids become more visible
  2. The eyes look slightly smaller
  3. The line of the nose is chiseled
  4. The face contours now show more bone and muscle structure than soft flesh
  5. The ear size stabilizes at the measure that is roughly the distance from the top of the eyes to the tip of the nose
  6. Males have a strong squared jaw
  7. Dark-haired men often have a shadow around the jaw even when they’re shaved. At this age, facial hair would be at their strongest if grown
  8. Due to the use of cosmetics), Female lips at their most fleshy (and frequently look much redder or contrasted
  9. The eyelashes are now emphasized

Middle Age (40's and 50's)

And female breasts start losing firmness, but muscle density decreases, The body doesn’t change all that much. Elbows and knee caps show wrinkles. The tendency to accumulate fat increases. Men and women store it in different places, indicated in blue:

No longer in the structure:, The changes in the face are mostly in the lines

  1. The eyelids become heavier
  2. Crow’s feet begin to appear
  3. A downward fold shows up at the corners of the mouth, giving a bit of a wry expression. It is now safe to draw more expression lines that would have made the face look too old otherwise
  4. Lines may also appear at the root of the nose
  5. In males, the hairline is likely to start receding
  6. The hair shows more sign of aging, the “salt and pepper” look

Menopause happens in a woman’s fifties. The drop in estrogen levels has many effects on the body, the most visible ones being:

  • The bones lose density so the body starts getting shorter
  • The breasts dry up
  • Weight gain is redistributed to the abdominal area, so the waist starts disappearing

Early Old Age (60's)

  1. The hair turns decidedly grey. So women wear it shorter, and its growth is now limited, It thins.  
  2. Frown and smile lines become permanent, Worry
  3. But grow sparser, The eyebrows may stay dark longer than the hair (if they were dark in the first place)
  4. Pockets appear under the eyes
  5. Resulting in a less firm jawline, The skin loses elasticity and starts hanging at the jaws
  6. The male hairline recedes to a varying, but noticeable degree
  7. Female eyelashes are no longer prominent
  8. The lips get thinner. The face in general starts losing femininity

Middle Old Age (70's)

People who keep exercising into old age keep a younger body longer, and may not slump or lose much muscle mass. Slumping makes the neck look shorter and the arms fall lower than usual. Male pectorals droop visibly

Hairline recedes considerably or all hair is lost, In males. Women’s hairline recedes little: this is the main difference between male and female faces at this stage

  1. Showing veins, The skin becomes thinner, blemishes and age spots
  2. Almost transparent as all pigment is gone, The hair is thin and wispy
  3. Giving it a triangular shape, The upper eyelid may droop to permanently cover the outer corner of the eye. This happens to populations of Western and Northern Europe and to people heavily exposed to the elements
  4. The earlobe droops (mostly noticeable in people who wore earrings)
  5. Hollowing the cheeks, The skin adheres to the bone
  6. There is a jowl effect as the skin on the cheeks sags
  7. The corners of the mouth run down
  8. The folds join the chin to the neck pit
  9. If there is any facial hair, it’s getting sparser and weaker
  10. The lips lose color, with vertical lines running up and down from them
  11. Loss of cartilage makes the nose tip droop
  12. The eyes become watery and their iris less intense in color
  13. Sparse or scraggy eyebrows

Very Old Age (80's and up)

Corners of the mouth drooping, permanent “worry” and frown” lines, The appearance of carrying the burdens of the world that old people usually have is mostly due to the physical changes of their face – the “sad” eyes (shaped this way by the drooping eyelid in Caucasian types). They are just always there, We read these as expression lines even though at that time of life. We need to be aware of the expressive power of these lines and balance or attenuate them according to the facial expression we wish to convey, When drawing an elderly face

  1. More age spots
  2. Letting the orbits show through the skin, The eyes sink back
  3. Crow’s feet can become really long and abundant
  4. People who spent their lives exposed to the elements can have abundant lines on the cheeks as well
  5. The jaw line is lost
  6. Double chin
  7. The mouth puckers in if lost teeth are not replaced by dental work (only affordable or available to a portion of the industrialized world) 
  8. These lines deepen

Practice time:

  • On the bus, Observe people on the street, etc. What age would you give them, On first impression. Try then to deconstruct the visual clues, picked up unconsciously, that led to that impression
  • Both with and without reference, Consciously sketch age groups that you don't normally draw or that you have trouble portraying
  • Play around with imagining your favourite comic book character (or your own character) at different stages of their life
Continue reading
0
4479

In this tutorial we'll build a "logger" mixin, informative log as CSS when Sass is compiled, which outputs a flexible

Logging is the process of recording application actions and state to a secondary interface. -Code Project

The Idea

The other dayNeatMaintainerReda LemedanAnd I were talking all things Sass and all of the sudden I sawan interesting mixin of his:

@include -neat-warn("Something is wrong");

And he told me it's basically a wrapper for the, I asked him what this mixin does@warnDirective from Sass that checks whether or not the user is willing to print warnings from Neat in the console (based on a global variable)

So I thought to myselfWhy stop thereAnd started playing with the idea that same night. My idea was to build a wrapper for both@warnAnd@error(from Sass 3.4Warn, ) to help library and framework developers print different type of messages (info, error, debug. ) and keep track of all logs

My current implementation provides:

  • 5 levels of logging (DEBUGINFOWARNERRORAndFATAL);
  • A minimum level at which the logger starts printing;
  • That can be printed as CSS;, a history of all logs
  • A friendly API with easy-to-use functions;
  • A helper to learn more about different levels of logging

How Does it Work?

It turned out to be fairly straightforward. We need a global variable holding the whole configuration, and a mixin serving as a wrapper for our console printing directives

Because we want our global configuration to be customisable (to some extent), we wrap its declaration in a mixin. Not only is this more convenient, but it's also nicer for the end user

So we have a mixin, let's call itLoggerCreating a global map holding our configuration, that is only intented to be called once. Then we have our wrapperLogThat accepts a logging level (for instanceWARNOrERROR) and the message to log as arguments. That's pretty much it

We will provide some shorthand functions to log different levels, To make things more convenient to the developers. For instance, instead of having to type:

@include log("ERROR", "There is not enough unicorn here.");

We could have:

@include ERROR("There is not enough unicorn here.");

So you'll end up with an API looking like this:

// Instantiate a logger
// that starts printing logs at `INFO` level. // This means that `DEBUG` logs won't be shown. @include logger("INFO");

// Log things. @include ERROR("There is not enough unicorn here.");

We'll also add some mixins to bring in some cool extra features:

  • One printing information about each logging level as a reminder;
  • One printing all logs that have been registered in the current compilation

Building the API

Logger Constructor

Let's start with the beginning, shall we. The loggerConstructorThis should accept a single parameter: the level at which the logger should start printing logs in the console

This is quite a common pattern for logging systems. For instance:

  • If you only want to print errors (ERRORAndFATALYou'd write, )@include logger("ERROR")
  • You'd go with, If you want to print everything@include logger("ALL")Which is basically the same as the lowest logging level (DEBUG)
  • If you want to disable the logger altogether, you run@include logger("OFF")

Note: you can find more information about logging levels in thisStackOverflow threadOr in theApache logs documentation

@mixin logger($minimum-level) {
  // List of available levels
  $levels: "DEBUG", "INFO", "WARN", "ERROR", "FATAL";

  // Make sure the given string is uppercase
  $minimum-level: to-upper-case($minimum-level);

  // If level is `ALL`, go with lowest level of all
  @if $minimum-level == "ALL" {
    $minimum-level: nth($levels, 1);
  }Arbitrary go with `INFO`
  @if not index($levels "OFF", // If level is invalid, $minimum-level) {
    $minimum-level: "INFO";
  }// Minimum level (as an index of `$levels`) to print
    "min"     : index($levels, "FATAL" : ()
    )
  ), "ERROR" : (), // Whether or not the logger is enabled
    "enabled" : $minimum-level != "OFF", // A map to keep track of all logs
    "history" : (
      "DEBUG" : (), "WARN"  : (), "INFO"  : (), $minimum-level), // List of levels that are printed with `@error`
    "errors"  : "FATAL" "ERROR", // Create global variable
  $logger-configuration: (
    // List of available levels
    "levels"  : $levels. Global;
}

But I've added some comments to make everything clear, The code above should be mostly self-explanatory. This mixin doesn't do much except create a global variable, As you can see. Is it, Not that bad

Before going any further, let's create a little helper function that makes it easy for us to get a value from this global map. Because you know, typingMap-get($logger-configuration. )Isn't remotely fun. What aboutLogger-conf(. )Instead

$key);, @function logger-conf($key) {
  @return map-get($logger-configuration
}

Log Wrapper

Let's move on to the actual, OkayLogFunction which prints things in the console. But it should also update the history in order to keep track of what's being logged (which might or might not be useful), Not only should it output the given messages in the user's console

That sounds difficult. It's going to be as smooth as butter, Well worry not. We already know this mixin should accept only two parameters: the logging level, and the message

`DEBUG` would be `1`
    $index-current-level: index(logger-conf("levels"), @mixin log($level, $message) {
  // Make sure the level is uppercase
  $level: to-upper-case($level);

  // Unless it's disabled, $level);

    // If `$level` is invalid, proceed
  @if logger-conf("enabled") {
    // Get current level's index
    // For instance, // arbitrary falls back on `INFO`
    @if not $index-current-level { 
      $level: "INFO";
    }// Update logger history
    @include logger-update-history($level, $message);

    // Finally, print message in console 
    // if current level is greater than or equal to minimum level. @if $index-current-level >= logger-conf("min") {
      $print: '[' + $level + '] :: ' + $message;

      // Print it as `@error` if it's an error level
      @if index(logger-conf("errors"), $level) {
        @error $print;
      }// Else use `@warn`
      @else {
        @warn $print;
      }
    }
  }
}

We need to deal with updating the history, Now. It becomes clearer, but once you get used to map manipulation, This is actually a little tougher

Before looking at the code, let me explain how is the history working. And values are lists of logged messages, it's a map where keys are the logging levels, Basically. You could have something like:, For instance

"WARN": (
    "You should pay attention to this.", "ERROR": (
    "Something's broken."
  ), $_: (
  "DEBUG": (), "This could be improved."
  ), "FATAL": ()
), "INFO": ()

Okay. Let's go

$message) {
  // Get history map from configuration
  $history: logger-conf("history");

  // Get history list for current level 
  $current-level-history: map-get($history, $level);

  // Append the fresh log to the list
  $current-level-history: append($current-level-history, ($level: $current-level-history));

  // Update the history map from the configuration with our temporary variable
  $logger-configuration: map-merge($logger-configuration, ("history": $logger-history)), $message);

  // Create a temporary variable containing the new history map
  $logger-history: map-merge($history, @mixin logger-update-history($level. Global;
}

It all makes sense eventually, but when you explain each line individually, It involves quite a few unfriendly lines

We're done here, but we spoke about adding shorthand functions. Let's do that now before we forget:

@mixin FATAL($message) { @include log("FATAL", $message); }
@mixin ERROR($message) { @include log("ERROR", $message); }
@mixin  WARN($message) { @include log("WARN",  $message); }
@mixin  INFO($message) { @include log("INFO",  $message); }
@mixin DEBUG($message) { @include log("DEBUG", $message); }

That's it. One last thing we could do, is testing whether, but isn't really mandatoryLoggerHas been included before trying to use the global map. But we could also make the logger instantiation optional by doing it on the fly, Not only do we prevent stupid mistakes

$message) {
  // Test whether `logger-configuration` global variable exists, @mixin log($level. Arbitrary setting the min level to `INFO`, it means `logger` has not been included, // so we include it, // If it doesn't. @if not global-variable-exists("logger-configuration") {
    @include logger("INFO");
  }@if logger-conf("enabled") {
    //
  }
}

Adding Extras

The helper, We'll start with the first (and least useful) of both extra mixins. And explanations as values, It's really a gadget at this point since all it does is print a CSS rule with logging levels as selectors

This is intented to give some help to developers when they don't really know which logging level they should use. It could have been written as a comment but I wanted to try this help printer thingie

@mixin logger-help {
  // Open a new `logger-help` selector
  logger-help {
    OFF: "Disable the logger.";
    FATAL: "Severe errors that cause premature termination.";
    ERROR: "Other runtime errors or unexpected conditions.";
    WARN: "Use of deprecated APIs, poor use of API, 'almost' errors,"
    + "other runtime situations that are undesirable or unexpected, but not necessarily wrong.";
    INFO: "Interesting runtime events (startup/shutdown).";
    DEBUG: "Detailed information on the flow through the system.";
  }
}

You use it like this:

@include logger-help;

And it compiles as:

Logger-help {
  OFF: "Disable the logger.";
  FATAL: "Severe errors that cause premature termination.";
  ERROR: "Other runtime errors or unexpected conditions.";
  WARN: "Use of deprecated APIs, poor use of API, 'almost' errors,other runtime situations that are undesirable or unexpected, but not necessarily wrong.";
  INFO: "Interesting runtime events (startup/shutdown).";
  DEBUG: "Detailed information on the flow through the system.";
}

Nothing special. The other extra mixin is way more interesting. It uses the history to print all logs that have been registered during the compilation

No print), @mixin logger-print-logs {
  // Open a new `logger-logs` selector
  logger-logs {
    // Loop over the history
    @each $level, $logs in logger-conf("history") {
      // Check whether current logging level from loop
      // should be displayed or not based on the minimum level
      // and the length of its value (no log. @if index(logger-conf("levels"), $level) >= logger-conf("min") and length($logs) > 0 {
        // Loop over the registered logs and print them. @each $log in $logs{
          #{$level}: $log;
        }
      }
    }
  }
}

Again, simple use:

@include logger-print-logs;

Which would output (based on our earlier example):

Logger-logs {
  WARN: "You should pay attention to this.";
  WARN: "This could be improved.";
  ERROR: "Something's broken";
}

Example

// Instantiate a new logger with `INFO` as the minimum level for logging. // If not included, it will automatically be done on first log. @include logger("INFO");

// Logger help (optional, obviously)
@include logger-help;

// Log stuff
@include INFO("Hey, look at that.");
@include INFO("Bring in the unicorns!");
@include WARN("Dude, pay attention.");

// This one is not printed but still tracked in logs. @include DEBUG("Debug and stuff."); 

// Output history (optional) especially useful for debugging
@include logger-print-logs;

Final Thoughts

The code is quite light in the end, As you can see, plus most of its bulk is comments. I think it provides a nice clean API helping keeping track of what's being logged in any given project

This is tool aimed at library and framework developers. And give me your feedback, If you happen to be one, please give this a try if you think it could be useful

Feel free tograb the mixin from GitHubOr play with it directly on SassMeister

Continue reading
0
3129
Final product image
What You'll Be Creating

In this tutorial, in Adobe Photoshop, I'll show you how to create some 8-bit inspired icons with a limited palette. However, you could easily create them in MS Paint

1. Icon Line Art

Step 1

We'll be working in Adobe Photoshop CC 2014(though most versions or even MS PaintWill work wonderfully too). Create a New DocumentMy final artwork (both sets of icons) measured 113 by 13 pixels

  1. Using the Pencil Tool (B)With the brush size set to 1 pixel Zoom (Z)In 1600%Or so, and draw 3 pixelsWith 1 pixelOn either side, on the next row down, diagonally
  2. Draw 7 pixelsOn the next line below
  3. Draw , For the neck of the bottle3 pixelsIn v-shapes pointing inward
  4. For the bulk of the bottle, draw4 pixels  in a single column on either side. Draw , For the stripe on the bottle7 pixelsBetween the two columns
  5. The final row consists of 7 pixelsGoing across, allowing the two sides to meet
Bottle lineart pixel icon

Step 2

For the sword line art, we'll split up the process into two steps:

  1. Start at the tip of the sword with 3 pixels upAnd 2 pixels acrossTo the RightFrom here we'll work diagonally in two rows,  14PixelsEach
  2. Draw 3 pixelsGoing upward on the right of the first diagonal line. Draw 3 pixelsGoing to the right on the row above the end of the second diagonal line
  3. Form a VIn the center of the sword with 3 pixelsDraw 2 pixelsOn theRightGoing to the RightAnd on the LeftGoing Upwards
  4. Continue on the left side with 3 pixelsTo the left and 1 downContinue on the right with 3 pixelsDown and 1 pixelTo the left
First half of sword pixel lineart

Step 3

Let's finish up the sword's guard and hilt with the following steps:

  1. Start in the center of the sword and draw 9 pixelsGoing diagonally from the left the right. Place1 pixelBetween the first two in the diagonal line and1 pixelBetween the last two in order to make sure top points of the sword's guard. Connect the new diagonal line on the left and right with 2 pixels DiagonallyGoing from right to left.  
  2. The handle of the sword is formed by forming concentric V'sWorking diagonally. This amounts to 7 columnsTotal
  3. Draw , From the tip of the handle1 pixelTo the RightOf the handle followed by 3 pixels down This is the start of the chain that hangs off of the handle. Draw 2 pixelsStarting in the center of the vertical line you just drew, diagonally
  4. Draw , To complete the chain3 V'sIn succession consisting of 3Diagonally placedPixelsEach
Second half of sword pixel line art

Step 4

The final icon's line art is fairly simple

  1. Draw 10 pixelsIn a single row horizontally. Draw 2 pixelsOn either side going diagonally and downward
  2. Draw8 vertical pixelsFollowed by12 pixelsBetween the two sides to complete the final shape
  3. Draw a horizontal line of pixels6 pixels downFrom the top of the box. Place one pixel in each inner corner of the box
  4. Draw , In the center of the box3 PixelsDown from the top line. Draw a box overlapping the central horizontal line that goes , From here4 pixels by 3 pixelsErase the center 2 pixelsWith the Eraser Tool (E) , Finally4 pixelsMake up the vertical lines on either side of the chest's lid. These lines are optional in your design
Small treasure chest pixel line art

2. Monochrome Limited Palette

Step 1

The colors used below are as follows from left to right: Mint (#e0f8d0Green (, )#88c070Forest Green (, )#306850), and Dark Green (#081820)

  1. Create a New LayerAbove your bottle line art
  2. Trace over the outer line art with Forest Green
  3. Fill in the rest of the bottle design with GreenAnd trace over the horizontal black lines with Forest Green
  4. Use MintTo create vertical highlights on the bottle in groups of 3 by 2 pixelsIn the center and a couple pixels on the left (see below)
  5. Finally, use Dark GreenTo scatter a pixel or two around the corners of the design
Monichrome bottle rendering

Step 2

Once again, the colors used below are as follows from left to right: Mint (#e0f8d0), Green (#88c070Forest Green (, )#306850), and Dark Green (#081820)

  1. Create a New LayerAbove the sword line art
  2. Using Forest GreenSkip a diagonal row, and do the same in the middle, line the left side of the sword with diagonal pixels. Repeat on the right side of the blade with Dark Green
  3. Fill in the blade with MintOn the left side and GreenOn the right. Start to add pixels of Forest GreenAnd Dark GreenIn the guard of the sword. Note the Dark GreenToward the blade and Forest GreenToward the outer edges
  4. Use Forest GreenOn the outer edges of the sword's guard and MintOn the first diagonal line within the guard
  5. Fill in the rest of the guard with GreenAnd trace the line art of the guard with Forest GreenPlaceForest GreenIn the center of the handle
  6. Dark GreenGoes on the right side of the handle while GreenGoes on the left. Essentially, each a different color going from light to dark, the hilt is comprised of three diagonal lines
  7. Use , For the chainGreen , on the rightMintIn the center of each chain link Forest GreenAnd , on the top leftDark GreenBetween each link shape
Monochrome sword rendering

Step 3

The colors used below are as follows from left to right: Mint (, Once more#e0f8d0), Green (#88c070), Forest Green (#306850And Dark Green (, )#081820)

  1. Create a New LayerAbove your small treasure chest line art.  
  2. Trace the outer line art of the chest with Forest Green
  3. Use Dark GreenOn the center horizontal line and the bottom of the chest's clasp. Use Forest GreenOn the 4 pixelsThat form the top of the clasp
  4. Draw 3 pixelsIn the lower corners of the box in Dark Green Use GreenTo draw vertical stripes on the lower half of the treasure chest with two rows between each green section
  5. Fill in the gaps in the lower half with MintAnd a pixel of Forest GreenOn either side below the split in the treasure chest
  6. Use Forest GreenTo draw two vertical lines on the top half of the chest. Concentrate MintOn the top left of the chest's lid
  7. Fill in the rest with Green
Monochrome treasure chest rendering

3. Four Color Palette

Step 1

This palette differs in its hue offering: incorporating cream and lime into the forest greens of the previous palette. From left to right, the colors are Cream (#f8dd92Lime (, )#9bbb0eSage (, )#73a067And Dark Forest Green (, )#0f380e)

  1. Create a New LayerAbove the original bottle line art
  2. Line the outer edge of the bottle with Dark Forest Green
  3. Fill the bottle with CreamEither using the Pencil ToolOr the Paint Bucket Tool (G)
  4. Line the bottom edge of the bottle's neck and the horizontal stripe with Sage
  5. Use LimeOn the horizontal line above the SageLine.  
  6. UseLimeAs a highlight on the bottle's label, and a shadow on the bottom of the bottle
Four color palette rendering for the bottle

Step 2

From left to right, Once again, the colors are Cream (#f8dd92), Lime (#9bbb0eSage (, )#73a067), and Dark Forest Green (#0f380e)

  1. Create a New LayerAbove the original sword line art
  2. Use the , To speed up the processMagic Wand Tool (W)To select the original line art and use the Fill Bucket Tool (G)To fill in the new selection on the New Layer
  3. Use LimeTo fill in the center of the chain, and the center diagonal line of the blade, the top edge of the sword guard
  4. Use SageOn the right edge of the sword blade and the rest of the sword guard
  5. Finally, use CreamFor the top edge of the sword's blade
Four color palette sword rendering

Step 3

From left to right, Once again, the colors are Cream (#f8dd92), Lime (#9bbb0e), Sage (#73a067), and Dark Forest Green (#0f380e)

  1. Create a New LayerAbove the small treasure chest's original line art
  2. Trace the outer edge and horizontal line in the center of the chest with Dark Forest Green
  3. FillThe chest with LimeAnd the center of the chest's clasp With CreamUsing the Fill Bucket Tool 
  4. Once again using the Pencil ToolConcentrate , as it's our main tool in this tutorialCreamColored pixels along the top and left edges of the box. Skipping every other pixel, Stagger pixels, in order to create a slight dithering pattern along the highlight edge
  5. Use SageTo draw vertical lines throughout the chest design and around the treasure chest clasp
Four color palette treasure chest rendering

Great Job, You're Done!

Three icon designs and two color palettes later, and we've got ourselves a great start in using a limited color palettes within pixel art. What else can you create with these palettes. How about other color combinations. Show us below in the comments

Final limited color palette icons
Continue reading
0

Testimonial

Thank you so much! We are very happy with our new website. It is easy to use and all of our customers tell us, they love it.

Contact Us

  • 13245 Atlantic Blvd. #4352
    Jacksonville, FL 32225
  • 904-240-5823