Pug102 - Mixins

While the include statements that we learnt about previously are useful, mixins allow a finer level of control. Specifically they make it easy to use the same layout for small chunks of code but change the values that might be displayed in them.
  1. Standard Mixin

    Defining a mixin lets you easily use a block of code repeatedly. The most basic form of a mixin does not have any parameters.

    mixin flower
      ul
        li one petal
        li two petal
        li three petal
    Having defined the above we can now use it with the below command.
    +flower
    • one petal
    • two petal
    • three petal
    It is also possible to give mixins arguments. Note when assigning things make sure that the '=' is touching the element which you are assigning objects to.
    mixin link(title, content)
      li
        .title= title
        .content= content
    Having defined the above we can now use it with the below command.
    ul
      +link('The Lord of the Rings', 'There was once a little hobbit in a hole')
      +link('The Lion King', 'Lions, lots of lions')
      +link('The Dark Knight Rises', 'I was born in the darkness')
    • The Lord of the Rings
      There was once a little hobbit in a hole
    • The Lion King
      Lions, lots of lions
    • The Dark Knight Rises
      I was born in the darkness
  2. Mixin Blocks

    Passing in large quantities of text or code is best done using blocks. If and else statements can be used to determine what to do if there is no block given.

    mixin link(title)
      li
        .title= title
        if block
          block
        else
          p No content given :(
    Having defined the above we can now use it with the below command.
    ul
      +link('The Lord of the Rings')
        p There was once a little hobbit on a roll
      +link('The Dark Knight Rises')
      +link('The Lion King')
    • The Lord of the Rings

      There was once a little hobbit on a roll

    • The Dark Knight Rises

      No content given :(

    • The Lion King

      No content given :(

  3. Mixin Attributes

    You can also use attributes passed to the mixin. As attributes are automatically escaped (this is a security measure) you will need to assign it with !=.

    mixin link(href, name)
      a(class!=attributes.class href=href)= name
    Having defined the above we can now use it with the below command.
    +link('/foo', 'foo')(class='btn')

    Attributes are best used to assign things that may be optional. For example if only certain instances of the mixin will have a class, it is easier to set the class using attributes rather than a variable that may not be defined. It also gives more clarity what the intended use of the variable is.

  4. Rest arguments

    In case there is an unknown number of arguments, the '...' syntax can be used.

    mixin list(name, ...items)
      ul
        div= name
        each item in items
          li= item
    Having defined the above we can now use it with the below command.
    +list('I love being a list <3', 'bee', 'ant', 'grasshopper', 'ladybird', 'christmas beetle')
    br
    +list('I don\'t like being a list :(', 'feeling', 'empty')
      I love being a list <3
    • bee
    • ant
    • grasshopper
    • ladybird
    • christmas beetle

      I don't like being a list :(
    • feeling
    • empty
  5. Exercises

    1. Recreate this site. First complete it without using mixins and then redo it with mixins. You can recreate the styling as well or just focus on the content. The ak-color.styl file provied in the prototyping template will be useful if you decide to recreate the style. You should only need to create three mixins and two of those should accept variables.
      .tag
        background-color: cyan
        display: inline-block
        width: 100px
        height: 30px
        line-height: 30px
        text-align: center
      link(href='style.styl' rel='stylesheet')
      
      ul
        li Octupuses have three hearts
        li Ostriches eyes are bigger than their brains
        li There are approximately 6,900 distinct languages in existence today
      ul
        li dan is 3
        li freddy is 4
        li sasha is 3.333
        li maria is 4
      .tag #cat
      .tag #dog
      ul
        li Octupuses have three hearts
        li Ostriches eyes are bigger than their brains
        li There are approximately 6,900 distinct languages in existence today
      .tag #mouse
      .tag #horse
      .tag #elephant
      ul
        li Octupuses have three hearts
        li Ostriches eyes are bigger than their brains
        li There are approximately 6,900 distinct languages in existence today
      link(href='style.styl' rel='stylesheet')
      
      mixin list
        ul
          li Octupuses have three hearts
          li Ostriches eyes are bigger than their brains
          li There are approximately 6,900 distinct languages in existence today
      
      mixin student(name, age)
        .student=name + " is " + age
      
      mixin hashtags(...tags)
        each tag in tags
          .tag= tag
      
      +list
      .students
        +student('dan', 3)
        +student('freddy', 4)
        +student('sasha', 3.333)
        +student('maria', 4)
      +hashtags("#cat", "#dog")
      +list
      +hashtags("#mouse", "#horse", "#elephant")
      +list

    2. Catlassian is back! This time we want more variation in the users though. Use this zip as a starting point. Create a mixin that will allow us to input the user's name, the location of their image, their age and a short bio. For the image location you can use the images already in the zip, or be more creative ;). Have a look at reader.pug if you're stuck on the html for the user card. Fill up the reader page so that it looks something like this:
      link(href='style.styl' rel='stylesheet')
      
      mixin user(name, img, age, bio)
        .user
          .name= name
          img(src=img)
          .age= age + " years old"
          .bio= bio
      
      h1 Catlassian Magazine
      h3 January, 2017
      
      #content
        #article
          p.
            Did you know that eighty percent of Atlassian employees love cats? That's why this quarter we're firing one fifth of the Atlassian work force. We predict once 100% of employees love cats, morale will skyrocket. That's stunning, as is our favorite kitten Greg.
          img(src='greg.jpg' width='100%' style='max-width: 750px')
          p.
            What a cutie. I bet he's just a ball of love and energy. Not that I would actually know. Greg's a stock image cat, I don't even know if his name is Greg. My entire life is a lie.
      
        #ourReaders
          h3 Our Readers
          +user("Frank Ocean", "frank.jpg", "29", "Christopher Francis \"Frank\" Ocean, is an American singer, songwriter, and rapper. Known for his idiosyncratic musical style, Ocean first embarked on a career as a ghostwriter, and in 2010 he became a member of hip hop collective Odd Future.")
          +user("Taylor Swift", "taylor.jpg", "27", "Taylor Alison Swift is an American singer-songwriter. One of the most popular contemporary female recording artists, she is known for narrative songs about her personal life, which has received much media attention.")
          +user("Jason Mraz", "jason.jpg", "39", "Jason Thomas Mraz is an American singer-songwriter who first came to prominence in the San Diego coffee shop scene in 2000. In 2002, he released his debut studio album, Waiting for My Rocket to Come, which contained the hit single \"The Remedy\". ")
          +user("Beyoncé", "beyonce.jpg", "35", "Beyoncé Giselle Knowles-Carter is an American singer, songwriter and actress. Born and raised in Houston, Texas, she performed in various singing and dancing competitions as a child.")
          +user("Shakira", "shakira.jpg", "40", "Shakira Isabel Mebarak Ripoll is a Colombian singer, songwriter, dancer, and record producer. Born and raised in Barranquilla, she began performing in school.")
          +user("Sting", "sting.jpg", "65", "Gordon Matthew Thomas Sumner, CBE, better known by his stage name Sting, is an English musician, singer, songwriter, and actor.")

    3. Create a mixin. It should contain a div element styled by the attributes set when calling the mixin. It should also have an optional block element. If no block is added make it clear to the user. If the following call is made:
      +container(style="background-color: lightblue; width: 100px; height: 100px")
      +container(style="border: 2px solid pink; width: 200px; height: 200px")
        p sock, sock, sock, sock, sock, stocking, sock, sock
      The end result should look something like the below:
      mixin container
        .container(style!=attributes.style)
          if block
            block
          else
            | no sock, no stocking, no sock sock sock :(
      
      +container(style="background-color: lightblue; width: 100px; height: 100px")
      +container(style="border: 2px solid pink; width: 200px; height: 200px")
        p sock, sock, sock, sock, sock, stocking, sock, sock