Example 1 - Crazy Mike's

Rob Attorri - 14 Feb 2017

(Eve is a new programming language, and this is our development blog. If you’re new to Eve, start here)

What is this?

This small app is pretty straightforward, consisting of a simple webpage with four subpages. The purpose is to demonstrate some basic webpage structure, show how a navigation bar could be implemented, how it changes the view between the different subpages, and how to inject page contents into the page view as you navigate from one subpage to another.

You can play with this example in your browser here.

Page Layout

Containers

I want this app to have three containers: a hero image, a nav bar above the page container, and page contents which are going to change depending on the active section. I draw the basic page structure here and worry about details like drawing the individual tabs for the subpages later. The hero image and the nav bar also have their classes set here because their style never changes. The individual pages may require different styles, so their classes are bound later.

commit @browser
  [#div class:"app-wrapper" children:
    [#div class:"hero-image"]
    [#div class:"nav-bar" #nav-bar]
    [#div #page-contents]]

Subpages

Crazy Mike sells a modest selection of repossessed electronics. I can set all the pages the site is going to have right here, and because I separated this from the page containers above, if I want to add another page and have it appear as a tab on the navigation bar, I can simply add it to this list.

Each page has a name, which is displayed as a label on the navigation button; and an order, which indicates its position in the nav bar.

commit
  [#page name: "Home" order: 1]
  [#page name: "Televisions" order: 3]
  [#page name: "Computers" order: 2]
  [#page name: "Stereos" order: 4]

Initial Landing Site

The #app record is where I’ve decided to keep track of which page is being viewed. I’ve also set page to homepage to begin with so that new customers will land there when they visit the site.

commit
  [#app page:"Home"]

The Navigation Bar

Drawing the Nav Bar

While the hero image was easy, the nav bar gets its own section because it needs a little more love than a background. It needs to make a button for each page of the website, which were committed in the Subpages section, so I take all the #page records and add a child #div to the #nav-bar for each of them.

search @session @browser
  page = [#page]
  nav-bar = [#nav-bar]

bind @browser
  nav-bar.children += [#div sort: page.order, class:"nav-btn", page text: page.name]

We start on the home page, but when you click a button on the nav bar, we want to navigate to that page. This listens for a click on any nav button, whose record has a page attached to it, then sets the page attribute of the #app record to match the page attribute of the button that was clicked.

search @browser @session @event
  click = [#click element:[#div page class:"nav-btn"]]
  view = [#app]

commit
  view.page := page.name

Highlighting the Active Page

Purely as a style issue, I want to change the background color of the nav bar button of whichever page we’re on. You could also use this block to bind a new class to nav-btn and use CSS to set the new background color, but this is a little more terse without obfuscating the goal.

search @session @browser
  [#app page]
  nav-btn = [#div page class:"nav-btn"]

bind @browser
  nav-btn.style += [background:"#606060"]

Subpages

Home Page

When the app specifies that we should be looking at the home page, the contents of this block are injected into the #page-contents record that was bound to the browser at the start of the Page Layout section.

search @session @browser
  [#app page: "Home"]
  view = [#page-contents]

bind @browser
  view <- [class: "main-page" children:
    [#h1 text: "Welcome to Crazy Mike's!"]
      [#p text: "Located on the scenic Pulaski Highway in East Baltimore, Crazy Mike's has the region's best selection of used electronics, and our prices are INSANE!"]
    [#p text: "Hours: Tue-Sat 2pm-4am"]
    [#p text: "Contact: (410) 768-7000, Ask for Mike"]]

Computers

Much like the home page, when the app specifies that we want to navigate to the Computers tab, we want to inject this page into #page-contents.

search @session @browser
  [#app page: "Computers"]
  view = [#page-contents]

bind @browser
  view <- [class: "main-page" children:
    [#p text: "Need to compute things? We can help."]
    [#div class:("computer", "pic")]
    [#p text: "One of our many fine products, this War Operations Plan Response supercomputer was repossessed from the US Dept. of Defense in 1984. Comes with classic games such as chess, checkers, backgammon, poker, tic-tac-toe, and Global Thermonuclear War, though it has been known not to play. Open box, comes as-is. Strict no return policy."]]

Televisions

Once more, when we navigate to the Televisions tab, it gets injected into #page-contents.

search @session @browser
  [#app page: "Televisions"]
  view = [#page-contents]

bind @browser
  view <- [class:"main-page" children:
    [#p text: "This is where the TVs live - get you one!"]
    [#div class: "tv pic"]
    [#p text: "Forget the internet, this baby is the real series of tubes. Perfect for your LaserDisc collection."]  ]

Stereos

When we navigate to the Stereos tab, it gets injected into #page-contents.

search @session @browser
  [#app page: "Stereos"]
  view = [#page-contents]

bind @browser
  view <- [class: "main-page" children:
    [#p text: "The hottest audio equipment in town!"]
    [#div class: "radio pic"]
    [#p text: "New stock arriving daily, priced to move."]
  ]

Styles

A little CSS to clean things up and make the page more readable.

.app-wrapper {
  display: flex;
  flex-direction: column;
  position: absolute;
  align-self: center;
  width: 432px;
  height: 768px;
  overflow-y: auto;
  background: #fff;
}

.hero-image {
  height: 300px;
  background-image: url(http://i.imgur.com/L8suaDZ.jpg);
  background-size: cover;
}

.nav-bar {
  display: flex;
  flex-direction: row;
  width: 100%;
  height: 50px;
  align-items: center;
}

.nav-btn {
  flex: 1;
  text-align: center;
  background: #404040;
  line-height: 50px;
  color: #fff;
  user-select: none;
  cursor: pointer;
}

.main-page {
  display: flex;
  flex-direction: column;
  align-items: center;
  padding-top: 20px;
  background: ;
}

.main-page h1 {
  margin: 10px 0px;
  font-size: 26px;
}

.main-page p {
  margin: 5px 25px;
  font-size: 16px;
  text-align: center;
}

.pic {
  margin: 20px 0px;
}

.computer {
  height: 150px;
  width: 320px;
  background: url(http://i.imgur.com/2EbQYGA.jpg) center no-repeat;
  background-size: cover;
}

.tv {
  height: 250px;
  width: 320px;
  background: url(http://i.imgur.com/0kD08WU.jpg) center no-repeat;
  background-size: cover;
}

.radio {
  height: 250px;
  width: 320px;
  background: url(http://i.imgur.com/rs1NW31.jpg) center no-repeat;
  background-size: cover;
}