ReactJS in PHP: Writing Compilers Is Easy and Fun!

I used to use an extension called XHP. It enables HTML-in-PHP syntax for generating front-end markup. I reached for it recently, and was surprised to find that it was no longer officially supported for modern PHP versions.

So, I decided to implement a user-land version of it, using a basic state-machine compiler. It seemed like it would be a fun project to do with you!

The code for this tutorial can be found on Github.

Abstract image of blocks coming together

Creating Compilers

Many developers avoid writing their own compilers or interpreters, thinking that the topic is too complex or difficult to explore properly. I used to feel like that too. Compilers can be difficult to make well, and the topic can be incredibly complex and difficult. But, that doesn’t mean you can’t make a compiler.

Making a compiler is like making a sandwich. Anyone can get the ingredients and put it together. You can make a sandwich. You can also go to chef school and learn how to make the best damn sandwich the world has ever seen. You can study the art of sandwich making for years, and people can talk about your sandwiches in other lands. You’re not going to let the breadth and complexity of sandwich-making prevent you from making your first sandwich, are you?

Compilers (and interpreters) begin with humble string manipulation and temporary variables. When they’re sufficiently popular (or sufficiently slow) then the experts can step in; to replace the string manipulation and temporary variables with unicorn tears and cynicism.

At a fundamental level, compilers take a string of code and run it through a couple of steps:

  1. The code is split into tokens – meaningful characters and sub-strings – which the compiler will use to derive meaning. The statement if (isEmergency) alert("there is an emergency") could be considered to contain tokens like if, isEmergency, alert, and "there is an emergency"; and these all mean something to the compiler.

    The first step is to split the entire source code up into these meaningful bits, so that the compiler can start to organize them in a logical hierarchy, so it knows what to do with the code.

  2. The tokens are arranged into the logical hierarchy (sometimes called an Abstract Syntax Tree) which represents what needs to be done in the program. The previous statement could be understood as “Work out if the condition (isEmergency) evaluates to true. If it does, run the function (alert) with the parameter ("there is an emergency")”.

Using this hierarchy, the code can be immediately executed (in the case of an interpreter or virtual machine) or translated into other languages (in the case of languages like CoffeeScript and TypeScript, which are both compile-to-Javascript languages).

In our case, we want to maintain most of the PHP syntax, but we also want to add our own little bit of syntax on top. We could create a whole new interpreter…or we could preprocess the new syntax, compiling it to syntactically valid PHP code.

I’ve written about preprocessing PHP before, and it’s my favorite approach to adding new syntax. In this case, we need to write a more complex script; so we’re going to deviate from how we’ve previously added new syntax.

Generating Tokens

Let’s create a function to split code into tokens. It begins like this:

function tokens($code) {
    $tokens = [];

    $length = strlen($code);
    $cursor = 0;

    while ($cursor < $length) {
        if ($code[$cursor] === "{") {
            print "ATTRIBUTE STARTED ({$cursor})" . PHP_EOL;
        }

        if ($code[$cursor] === "}") {
            print "ATTRIBUTE ENDED ({$cursor})" . PHP_EOL;
        }

        if ($code[$cursor] === "<") {
            print "ELEMENT STARTED ({$cursor})" . PHP_EOL;
        }

        if ($code[$cursor] === ">") {
            print "ELEMENT ENDED ({$cursor})" . PHP_EOL;
        }

        $cursor++;
    }
}

$code = '
    <?php

    $classNames = "foo bar";
    $message = "hello world";

    $thing = (
        <div
            className={() => { return "outer-div"; }}
            nested={<span className={"nested-span"}>with text</span>}
        >
            a bit of text before
            <span>
                {$message} with a bit of extra text
            </span>
            a bit of text after
        </div>
    );
';

tokens($code);

// ELEMENT STARTED (5)
// ELEMENT STARTED (95)
// ATTRIBUTE STARTED (122)
// ELEMENT ENDED (127)
// ATTRIBUTE STARTED (129)
// ATTRIBUTE ENDED (151)
// ATTRIBUTE ENDED (152)
// ATTRIBUTE STARTED (173)
// ELEMENT STARTED (174)
// ATTRIBUTE STARTED (190)
// ATTRIBUTE ENDED (204)
// ELEMENT ENDED (205)
// ELEMENT STARTED (215)
// ELEMENT ENDED (221)
// ATTRIBUTE ENDED (222)
// ELEMENT ENDED (232)
// ELEMENT STARTED (279)
// ELEMENT ENDED (284)
// ATTRIBUTE STARTED (302)
// ATTRIBUTE ENDED (311)
// ELEMENT STARTED (350)
// ELEMENT ENDED (356)
// ELEMENT STARTED (398)
// ELEMENT ENDED (403)

This is from tokens-1.php

We’re off to a good start. By stepping through the code, we can check to see what each character is (and identify the ones that matter to us). We’re seeing, for instance, that the first element opens when we encounter a < character, at index 5. The first element closes at index 210.

Unfortunately, that first opening is being incorrectly matched to <?php. That’s not an element in our new syntax, so we have to stop the code from picking it out:

preg_match("#^</?[a-zA-Z]#", substr($code, $cursor, 3), $matchesStart);

if (count($matchesStart)) {
    print "ELEMENT STARTED ({$cursor})" . PHP_EOL;
}

// ...

// ELEMENT STARTED (95)
// ATTRIBUTE STARTED (122)
// ELEMENT ENDED (127)
// ATTRIBUTE STARTED (129)
// ATTRIBUTE ENDED (151)
// ATTRIBUTE ENDED (152)
// ATTRIBUTE STARTED (173)
// ELEMENT STARTED (174)
// ...

This is from tokens-2.php

Instead of checking only the current character, our new code checks three characters: if they match the pattern <div or </div, but not <?php or $num1 < $num2.

There’s another problem: our example uses arrow function syntax, so => is being matched as an element closing sequence. Let’s refine how we match element closing sequences:

preg_match("#^=>#", substr($code, $cursor - 1, 2), $matchesEqualBefore);
preg_match("#^>=#", substr($code, $cursor, 2), $matchesEqualAfter);

if ($code[$cursor] === ">" && !$matchesEqualBefore && !$matchesEqualAfter) {
    print "ELEMENT ENDED ({$cursor})" . PHP_EOL;
}

// ...

// ELEMENT STARTED (95)
// ATTRIBUTE STARTED (122)
// ATTRIBUTE STARTED (129)
// ATTRIBUTE ENDED (151)
// ATTRIBUTE ENDED (152)
// ATTRIBUTE STARTED (173)
// ELEMENT STARTED (174)
// ...

This is from tokens-3.php

As with JSX, it would be good for attributes to allow dynamic values (even if those values are nested JSX elements). There are a few ways we could do this, but the one I prefer is to treat all attributes as text, and tokenize them recursively. To do this, we need to have a kind of state machine which tracks how many levels deep we are in an element and attribute. If we’re inside an element tag, we should trap the top level {…} as a string attribute value, and ignore subsequent braces. Similarly, if we’re inside an attribute, we should ignore nested element opening and closing sequences:

function tokens($code) {
    $tokens = [];

    $length = strlen($code);
    $cursor = 0;

    $elementLevel = 0;
    $elementStarted = null;
    $elementEnded = null;

    $attributes = [];
    $attributeLevel = 0;
    $attributeStarted = null;
    $attributeEnded = null;

    while ($cursor < $length) {
        $extract = trim(substr($code, $cursor, 5)) . "...";

        if ($code[$cursor] === "{" && $elementStarted !== null) {
            if ($attributeLevel === 0) {
                print "ATTRIBUTE STARTED ({$cursor}, {$extract})" . PHP_EOL;
                $attributeStarted = $cursor;
            }

            $attributeLevel++;
        }

        if ($code[$cursor] === "}" && $elementStarted !== null) {
            $attributeLevel--;

            if ($attributeLevel === 0) {
                print "ATTRIBUTE ENDED ({$cursor})" . PHP_EOL;
                $attributeEnded = $cursor;
            }
        }

        preg_match("#^</?[a-zA-Z]#", substr($code, $cursor, 3), $matchesStart);

        if (count($matchesStart) && $attributeLevel < 1) {
            print "ELEMENT STARTED ({$cursor}, {$extract})" . PHP_EOL;

            $elementLevel++;
            $elementStarted = $cursor;
        }

        preg_match("#^=>#", substr($code, $cursor - 1, 2), $matchesEqualBefore);
        preg_match("#^>=#", substr($code, $cursor, 2), $matchesEqualAfter);

        if (
            $code[$cursor] === ">"
            && !$matchesEqualBefore && !$matchesEqualAfter
            && $attributeLevel < 1
        ) {
            print "ELEMENT ENDED ({$cursor})" . PHP_EOL;

            $elementLevel--;
            $elementEnded = $cursor;
        }

        if ($elementStarted && $elementEnded) {
            // TODO

            $elementStarted = null;
            $elementEnded = null;
        }

        $cursor++;
    }
}

// ...

// ELEMENT STARTED (95, <div...)
// ATTRIBUTE STARTED (122, {() =...)
// ATTRIBUTE ENDED (152)
// ATTRIBUTE STARTED (173, {<spa...)
// ATTRIBUTE ENDED (222)
// ELEMENT ENDED (232)
// ELEMENT STARTED (279, <span...)
// ELEMENT ENDED (284)
// ELEMENT STARTED (350, </spa...)
// ELEMENT ENDED (356)
// ELEMENT STARTED (398, </div...)
// ELEMENT ENDED (403)

This is from tokens-4.php

We’ve added new $attributeLevel, $attributeStarted, and $attributeEnded variables; to track how deep we are in the nesting of attributes, and where the top-level starts and ends. Specifically, if we’re at the top level when an attribute’s value starts or ends, we capture the current cursor position. Later, we’ll use this to extract the string attribute value and replace it with a placeholder.

We’re also starting to capture $elementStarted and $elementEnded (with $elementLevel fulfilling a similar role to $attributeLevel) so that we can capture a full element opening or closing tag. In this case, $elementEnded doesn’t refer to the closing tag but rather the closing sequence of characters of the opening tag. Closing tags are treated as entirely separate tokens…

After extracting a small substring after the current cursor position, we can see elements and attributes starting and ending exactly where we expect. The nested control structures and elements are captured as strings, leaving only the top-level elements, non-attribute nested elements, and attribute values.

Let’s package these tokens up, associating attributes with the tags in which they are defined:

function tokens($code) {
    $tokens = [];

    $length = strlen($code);
    $cursor = 0;

    $elementLevel = 0;
    $elementStarted = null;
    $elementEnded = null;

    $attributes = [];
    $attributeLevel = 0;
    $attributeStarted = null;
    $attributeEnded = null;

    $carry = 0;

    while ($cursor < $length) {
        if ($code[$cursor] === "{" && $elementStarted !== null) {
            if ($attributeLevel === 0) {
                $attributeStarted = $cursor;
            }

            $attributeLevel++;
        }

        if ($code[$cursor] === "}" && $elementStarted !== null) {
            $attributeLevel--;

            if ($attributeLevel === 0) {
                $attributeEnded = $cursor;
            }
        }

        if ($attributeStarted && $attributeEnded) {
            $position = (string) count($attributes);
            $positionLength = strlen($position);

            $attribute = substr(
                $code, $attributeStarted + 1, $attributeEnded - $attributeStarted - 1
            );

            $attributes[$position] = $attribute;

            $before = substr($code, 0, $attributeStarted + 1);
            $after = substr($code, $attributeEnded);

            $code = $before . $position . $after;

            $cursor = $attributeStarted + $positionLength + 2 /* curlies */;
            $length = strlen($code);

            $attributeStarted = null;
            $attributeEnded = null;

            continue;
        }

        preg_match("#^</?[a-zA-Z]#", substr($code, $cursor, 3), $matchesStart);

        if (count($matchesStart) && $attributeLevel < 1) {
            $elementLevel++;
            $elementStarted = $cursor;
        }

        preg_match("#^=>#", substr($code, $cursor - 1, 2), $matchesEqualBefore);
        preg_match("#^>=#", substr($code, $cursor, 2), $matchesEqualAfter);

        if (
            $code[$cursor] === ">"
            && !$matchesEqualBefore && !$matchesEqualAfter
            && $attributeLevel < 1
        ) {
            $elementLevel--;
            $elementEnded = $cursor;
        }

        if ($elementStarted !== null && $elementEnded !== null) {
            $distance = $elementEnded - $elementStarted;

            $carry += $cursor;

            $before = trim(substr($code, 0, $elementStarted));
            $tag = trim(substr($code, $elementStarted, $distance + 1));
            $after = trim(substr($code, $elementEnded + 1));

            $token = ["tag" => $tag, "started" => $carry];

            if (count($attributes)) {
                $token["attributes"] = $attributes;
            }

            $tokens[] = $before;
            $tokens[] = $token;

            $attributes = [];

            $code = $after;
            $length = strlen($code);
            $cursor = 0;

            $elementStarted = null;
            $elementEnded = null;

            continue;
        }

        $cursor++;
    }

    return $tokens;
}

$code = '
    <?php

    $classNames = "foo bar";
    $message = "hello world";

    $thing = (
        <div
            className={() => { return "outer-div"; }}
            nested={<span className={"nested-span"}>with text</span>}
        >
            a bit of text before
            <span>
                {$message} with a bit of extra text
            </span>
            a bit of text after
        </div>
    );
';

tokens($code);

// Array
// (
//     [0] => <?php
//
//     $classNames = "foo bar";
//     $message = "hello world";
//
//     $thing = (
//     [1] => Array
//         (
//             [tag] => <div className={0} nested={1}>
//             [started] => 157
//             [attributes] => Array
//                 (
//                     [0] => () => { return "outer-div"; }
//                     [1] => <span className={"nested-span"}>with text</span>
//                 )
//
//         )
//
//     [2] => a bit of text before
//     [3] => Array
//         (
//             [tag] => <span>
//             [started] => 195
//         )
//
//     [4] => {$message} with a bit of extra text
//     [5] => Array
//         (
//             [tag] => </span>
//             [started] => 249
//         )
//
//     [6] => a bit of text after
//     [7] => Array
//         (
//             [tag] => </div>
//             [started] => 282
//         )
//
// )

This is from tokens-5.php

There’s a lot going on here, but it’s all just a natural progression from the previous version. We use the captured attribute start and end positions to extract the entire attribute value as one big string. We then replace each captured attribute with a numeric placeholder and reset the code string and cursor positions.

As each element closes, we associate all the attributes since the element was opened, and create a separate array token from the tag (with its placeholders), attributes and starting position. The result may be a little harder to read, but it is spot on in terms of capturing the intent of the code.

So, what do we do about those nested element attributes?

Continue reading %ReactJS in PHP: Writing Compilers Is Easy and Fun!%


Source: Sitepoint

4 Signs Your Employer Will Ruin Your Career

Employers ruining careers

“No one will hire me.”

Jim Walters was blacklisted. His former boss tried to ruin his career. When prospective employers contacted Jim, they asked for references.

So he sent them.

Inevitably, these employers decided they didn’t want to hire Jim. 12 employers made an offer. They all backed out after contacting his references.

His former boss was attempting to ruin his career.

Maybe Your Boss is Terrible

Maybe they’re a tyrant, focused on dominating you. Or maybe they’re clueless micromanagers harassing you about your work. The real question, though, is this:

Will your boss ruin your career?

It doesn’t seem like a legitimate question at first glance.

Who cares? It’s not like they can ruin my career. What are they gonna do, tell on me?

A terrible boss will ruin your career. Spend enough time with them and the damage becomes inevitable.

But how?

Aren’t there laws to protect employees?

Sort of.

Laws, for the most part, are limited to eavesdropping on private oral communication, anti-discrimination, equal opportunity, etc. But aside from that?

Employers, your boss, can pretty much do what they want, when they want.

Don’t believe me? Let’s look at a few examples.

  • Lynne Gobbell was fired because her boss didn’t like the bumper sticker on her car. When her boss saw her sticker he said, “either work for John Kerry or work for me.” She refused to remove the sticker, and was immediately fired.

  • Best Lock Company in Indiana fired employees for social drinking at their home. The reason? Their president believes drinking alcohol is a sin. They even go so far as to deny unemployment.

  • Johnson County Community College installed hidden cameras in their bathrooms and locker rooms. They stated workers had no right to privacy. What’s worse, they got away with it.

  • Glen Hillier was fired from his job at an ad agency. During the 2004 presidential race, he asked President Bush some embarrassing questions. One of his company’s customers felt offended and reported it to Hillier’s boss. One day later, Hillier was out of a job.

Lewis Maltby, in his book Can They Do That? discloses the abuse workers face in detail.

And there’s the problem.

Your employers know they can do what they want. The vast majority of employees know it too, which is why so many people work in fear.

Dysfunctional Employers Feed on Your Fear

Employers ruining careers

They use sadistic and dysfunctional behavior to extract the results they want from their employees. Then, once you’re burned out and used up, they toss you aside.

When that happens, you’re treated as damaged goods.

Future employers are suddenly nervous about hiring you. You’re blacklisted by your dysfunctional employer directly or implicitly. It’s suddenly difficult to get a new job.

That’s the thing about a ruined career.

It creeps up on you slowly, gradually. Ignore the signs, wait too long and the damage may be irreversible.

Here’s the worst part.

The vast majority of developers reject these signals automatically. “It won’t happen to me,” they tell themselves. Their rejection is based on a wide variety of reasons.

  • Most believe the solution is beneath them somehow.
  • Some are afraid they’ll dig up unpleasant things.
  • My company isn’t like that, they tell themselves.
  • Others think “working hard” or doing a “good job” is enough. (It’s not.)
  • Things are good, so why bother with that now?

As developers, we create rationalizations to avoid facing stupid or unpleasant things. But the signs of a bad employer are there, screaming for us to pay attention. You can protect and save your career … if you know how to read the signals. Here are four signals, numbered from 4 to 1 …

Signal #4: Chronic Emotional Invalidation

Invalidation is an attempt by others to control how you feel about something and how long you feel that way.

It’s accomplished by rejecting, mocking, judging or minimizing someone else’s thoughts, values or feelings. It’s a devastating part of work that most developers have come to accept as a normal, everyday part of work.

What does that look like?

  • Procrastinators are made. A fear of failure, perfectionism, or a lack of focus is all that’s needed to induce procrastination. The sad part? All three of these causes are really part of the same problem. Make a mistake and you’ll probably lose your job.

  • Silent and disengaged. Co-workers who couldn’t care less about their jobs and are eagerly looking forward to the weekend/holidays/vacation, etc. Thanks to interpersonal dynamics, the idea of doing a job at work has completely lost its appeal for them.

  • Distracted co-workers are fixated on all the wrong things. They’re not working on exciting projects, aren’t being trained to do more or simply aren’t in the environment of their choice. So these developers focus their time and attention on doing as little as they can.

  • Fearful. Your manager or boss asks for an “honest opinion” or “feedback” in a meeting. Everyone looks down. They stare at the table or their hands. Everyone in that meeting knows feedback or honest opinion is code for tell me what I want to hear. Mess it up and you’re out of a job.

An organization struggling with these dysfunctions runs into a predictable problem. A-player developers quickly leave, while B- and C-players do their best to survive.

Those who stay absorb these bad habits like a sponge, taking them wherever they go, ruining their careers in the process.

Most developers will allow their boss, their employer to hurt their careers — even after learning about these details.

Why?

They believe that feelings/emotions don’t matter. “I’m a logical thinker, I’m clear-headed. These things just don’t get to me.” Here’s why that’s a problem.

It’s a lie.

That’s because logical decision making is a myth.

Antonio Damasio, Professor at the University of Southern California, made the surprising discovery. His research focused on patients who were normal in every way, except one. They all had a damaged limbic system.

They couldn’t feel emotions at all. This led to a surprising but unusual problem.

None of Damasio’s patients could make decisions.

They were able to logically describe what they should do, but without emotion, they found it incredibly difficult to make the simplest decisions. These people couldn’t decide what to eat, when to eat it or even how they should eat.

Damasio found that emotions are absolutely vital for decision making.

It gets worse.

Negative emotions, fear, stress and anxiety, kills your performance. Whether we like it or not, these emotions are slowly chipping away at our ability to perform, giving dysfunctional employers the ammunition they need to hurt our careers.

Signal #3: Codependency and the Drama Triangle

It’s a silent epidemic, codependency in the workplace. It’s something that makes developers (and employees), in general, miserable. But, what is it?

Here’s a simple definition.

When I work on your desires, goals, fears and frustrations more than you do. It’s a behavioral problem that masks itself in lots of different ways.

  • The micromanaging boss
  • Abandoning your work routine to bail out a co-worker
  • Allowing someone else to take the credit for your work
  • Feeling compelled — almost forced — to help an irresponsible co-worker solve the problem they created
  • Offering unasked for advice
  • Controlling others with guilt, helplessness, threats, shame, advice-giving, manipulation, domination, etc.
  • Pretending a problem isn’t happening or isn’t as bad as it really is.

This isn’t a comprehensive list. It’s meant to show the types of behaviors present in a dysfunctional workplace.

Why does this matter?

The Drama Triangle is a social model of unhealthy human interaction. In an unhealthy environment, developers and employers play a dysfunctional role where everyone fights for control.

Here’s how it works.

This dynamic is at play in our personal and professional relationships. Here’s an example of what that looks like.

  1. An employer decides to become a rescuer, choosing an employee they feel will help them but also finding one they feel needs a leg up.

  2. Their employee realizes they’re making less than their friends and feels victimized, cheated by the employer because they’re not being paid enough.

  3. The employee asks for a raise. Employer, feeling taken advantage of (victim state), says No, becomes a persecutor telling their employee they need to see a performance improvement first.

  4. The employee becomes enraged and swears revenge. They make the move to persecutor doing everything they can to punish their employer and their co-workers.

  5. The employee takes revenge, completes the cycle of persecution and destroys the company.

Sounds a bit extreme, doesn’t it? I mean, who’d go to the trouble of doing something malicious like this? Ask JournalSpace. JournalSpace was a blogging platform. The keyword is was, because their IT guy (the same guy who was caught stealing from the company), maliciously wiped out the main database (for which there was no backup). JournalSpace shut down immediately.

Here’s how his employer described the whole affair.

It was the guy handling the IT (and, yes, the same guy who I caught stealing from the company, and who did a slash-and-burn on some servers on his way out) who made the choice to rely on RAID as the only backup mechanism for the SQL server. He had set up automated backups for the HTTP server which contains the PHP code, but, inscrutably, had no backup system in place for the SQL data. The ironic thing here is that one of his hobbies was telling everybody how smart he was.

Notice how both employer and employee decided to persecute each other. They both had a role to play but neither wanted to accept any responsibility for their role in the situation.

That’s the destructive power of codependency and the drama triangle at work.

Continue reading %4 Signs Your Employer Will Ruin Your Career%


Source: Sitepoint

Visualize Large Date and Time-Based Datasets with AnyStock

I introduced the basics of the AnyChart product family in my previous article on SitePoint. This time I will tell you about how AnyStock is helpful in visualizing stock data as well as any large date and time-based data sets (and how to use it best).

AnyStock is part of the AnyChart JavaScript charting library that is marketed as a set of products:

  • AnyChart – common chart types,
  • AnyMap – geo maps and seat maps,
  • AnyGantt – Project Gantt, Resource, and PERT charts,
  • AnyStock – visualization of big date/time-based data sets, the features of which are the topic of this article.

Because AnyChart is essentially one big JavaScript charting library, the API is common and all charts are configured in pretty much the same way, sharing themes, settings, and ways to load data. That said, most of the things and approaches you’ll learn about in this article can be easily applied to making other charts and maps.

AnyStock stock charts are a special type of charts that can effectively visualize big amounts of date/time-based data. It has many special features such as zoom with Scroller UI, synchronized plots, data grouping, and so on. AnyStock is completely compatible with all other AnyChart charts, and besides having all basic stock features such as grouping, streaming, scrolling, etc., AnyStock stocks also have multiple technical indicators built-in and ability to customize them.

To put it in a nutshell, in this article I will:

AnyStock Quick Start

To start using AnyStock in your HTML page you need three simple things. The first one is a link to the library’s JavaScript file. The second one is a block-level HTML element; here’s a sample HTML template you may use:

<html lang="en">
  <head>
    <meta charset="utf-8" />
    <script src="https://cdn.anychart.com/js/7.14.3/anystock.min.js"></script>    
    <style>
    html, body, #container {
      width: 100%;
      height: 100%;
    }
  </style>    
    <title>AnyStock Basic Example</title>    
  </head>
  <body>
    <div id="container"></div>
    <script>
      // AnyStock code here
    </script>
  </body>
</html>

And here is a basic code to create a simple Japanese Candlestick chart, along with the volume on the second plot and scroller that shows volume as an area:

anychart.onDocumentReady(function() {
    // data
    var data = [
      ['2015-12-24', 511.53, 514.98, 505.79, 506.40, 1050016],
      ['2015-12-25', 512.53, 514.88, 505.69, 505.34, 1050015],
      ['2015-12-26', 511.83, 514.98, 505.59, 506.23, 1050016],
      ['2015-12-27', 511.22, 515.30, 505.49, 506.47, 1250016],
      ['2015-12-28', 510.35, 515.72, 505.23, 505.80, 1250015],
      ['2015-12-29', 510.53, 515.86, 505.38, 508.25, 1250018],
      ['2015-12-30', 511.43, 515.98, 505.66, 507.45, 1250017],
      ['2015-12-31', 511.50, 515.33, 505.99, 507.98, 1250017],
      ['2016-01-01', 511.32, 514.29, 505.99, 506.37, 1250016],
      ['2016-01-02', 511.70, 514.87, 506.18, 506.75, 1250016],
      ['2016-01-03', 512.30, 514.78, 505.87, 508.67, 1250018],
      ['2016-01-04', 512.50, 514.77, 505.83, 508.35, 1250018],
      ['2016-01-05', 511.53, 516.18, 505.91, 509.42, 1050019],
      ['2016-01-06', 511.13, 516.01, 506.00, 509.26, 1050019],
      ['2016-01-07', 510.93, 516.07, 506.00, 510.99, 1050110],
      ['2016-01-08', 510.88, 515.93, 505.22, 509.95, 1350019],
      ['2016-01-09', 509.12, 515.97, 505.15, 510.12, 1350110],
      ['2016-01-10', 508.53, 516.13, 505.66, 510.42, 1350110],
      ['2016-01-11', 508.90, 516.24, 505.73, 510.40, 1350110]
    ];

    // create stock chart
    chart = anychart.stock();
    chart.title("AnyStock: Basic Sample");

    // create data table and load data in it
    table = anychart.data.table();
    table.addData(data); 

    // map data - name fields
    mapping = table.mapAs({open: 1, high: 2, low: 3, close: 4, value: 5});

    // create series to show stock changes
    chart.plot(0).candlestick(mapping).name("Stock name");
    // create second plot and show trading volume there as a line
    chart.plot(1).column(mapping).name("Volume");
    // create series to show trading volume
    chart.scroller().area(mapping);

    // set HTML container and draw chart into it
    chart.container('container').draw();     
});

Data mapping

In the previous article about AnyChart, I demonstrated multiple ways to load data into the library, but an important and astonishing feature called data mapping has been left out.

What is data mapping? Let’s delve into it a little bit, as we have already made good use of this feature in the basic AnyStock sample and will continue to use it in every sample in this article.

As this Wikipedia article on data mapping tells us:

In computing and data management, data mapping is the process of creating data element mappings between two distinct data models. Data mapping is used as the first step for a wide variety of data integration tasks including data transformation or data mediation between a data source and a destination.

One of the ways to translate this definition into layman’s terms: “Data mapping is a rule that tells what is what in the data and prepares some data to be used somewhere else.”

I know it may sound crude and an oversimplification, but it still might be helpful.

Now, let’s look how the data mapping happens in the example above. First, we have an array with numbers and dates that we load into the table:

// data
var data = [
  ['2015-12-24', 511.53, 514.98, 505.79, 506.40, 1050016],
  ['2015-12-25', 512.53, 514.88, 505.69, 505.34, 1050015],
  ['2015-12-26', 511.83, 514.98, 505.59, 506.23, 1050016],
  ['2015-12-27', 511.22, 515.30, 505.49, 506.47, 1250016],
  ['2015-12-28', 510.35, 515.72, 505.23, 505.80, 1250015],
  ['2015-12-29', 510.53, 515.86, 505.38, 508.25, 1250018],
  ['2015-12-30', 511.43, 515.98, 505.66, 507.45, 1250017],
  ['2015-12-31', 511.50, 515.33, 505.99, 507.98, 1250017]
];

// create data table and load data in it
table = anychart.data.table();
table.addData(data); 

There is nothing in this data that explains which columns contain prices or anything else. Open, high, low and close prices can come in any order. So how can the AnyStock library understand what’s what? By using data mappings!

In this case, we need only one:

// map data - name fields
mapping = table.mapAs({open: 1, high: 2, low: 3, close: 4, value: 5});

As we see, the mapAs() method takes an object where we decide what names a field gets and then we pass this mapping to the functions that show series:

// create series to show stock changes
chart.plot(0).candlestick(mapping).name("Stock name");
// create second plot and show trading volume there as line
chart.plot(1).column(mapping).name("Volume");
// create series to show trading volume
chart.scroller().area(mapping);

AnyStock expects a mapping with open, high, low and close fields for a candlestick series and value for area and column and this allows us to use one mapping in this case.

Continue reading %Visualize Large Date and Time-Based Datasets with AnyStock%


Source: Sitepoint

Fancy Web Animations Made Easy with GreenSock Plugins

GreenSock Animation Tutorial for Beginners: Plugins

The aim of the third part of this GreenSock tutorial series is to introduce you to some amazing GreenSock plugins.

You’ll be using:

  • The BezierPlugin to animate properties along a curved Bezier path
  • The GSAP Draggable utility to drag elements on the screen and the ThrowPropsPlugin to glide them to a smooth stop
  • The DrawSVGPlugin to draw SVG strokes dynamically
  • The MorphSVGPlugin to morph any SVG path into any other path, even if the two paths don’t have the same number of points
  • And the SplitText utility to create fun animation text effects.

By the end of this tutorial, you’ll be able to create complex types of web animations in a fraction of the time that it would normally take without using GreenSock’s plugins.

For an introduction to the basics of GreenSock, including how to work with TweenMax for sequencing and staggering simple animations, head over to part 1 of this multi-part article.

If you’re looking for a refresher on GreenSock’s powerful timeline (TimelineLite and TimelineMax), check out Part 2.

The GreenSock articles are part of the series Beyond CSS: Dynamic DOM Animation Libraries. Here’s what I covered in the past instalments:

Animation Along a Path with GreenSock’s BezierPlugin

Motion along a path consists in objects following a predefined path like a curved path or a zigzag path, etc. In the right context, it can be crucial for realistic animation.

This kind of animation is possible using SMIL (Synchronized Multimedia Integration Language), which is being deprecated.

The future of motion along a path seems to be CSS, but although the feature is supported in a few browsers (mostly Chrome and Opera), adopting it in production websites could be a risky move.

For consistent browser support and ease of implementation, GSAP’s BezierPlugin is a fantastic option.

This is a free plugin included with TweenMax. Let’s try it out!

Continue reading %Fancy Web Animations Made Easy with GreenSock Plugins%


Source: Sitepoint

15 Color Schemes From Disney Heroes and Villains

Aladdin and Stitch

The Walt Disney Company was first established in 1923, and their first full-length film, Snow White and The Seven Dwarves was released in 1937. What’s interesting about the character of Snow White, is that she’s one of the most archetypal symbols of “Good” in the Disney universe.

In the story, the Evil Queen is envious of Snow White’s beauty and purity, which is represented by her ever so pale skin, and serves her the nickname, “the fairest of them all”. Allocating a dominant color/brightness to this character helps the audience better identify to what degree of good or evil this character is. The Evil Queen, on the other hand, is made up of predominantly darker shades of black and purple, to help portray her as the villain.

But just how much does color impact the characteristics of various Disney heroes and villains? And, can a certain color scheme dictate the way in which we, the audience, interpret a character, or in the case of design, a brand?

Color Psychology

Color psychology has always been a somewhat controversial topic. When you consider that different cultures, upbringings and experiences vary from person to person, the way in which we interpret certain colors (and their many hues and shades) differs as well. It’s easy to say that “yellow makes us happy”, or “red makes us angry”, however many of these statements are in fact highly subjective. In China, red means happiness, prosperity, celebration, long-life, and so on—not angry.

Alas we turn to Disney in order to get a better idea of how color is used in the design of various heroes and villains, and how those choices influence the way in which we interpret and emotionally react to the color schemes they use.

As you can see, the Disney infographic below shows some of the most well-known Walt Disney heroes and villains on a color wheel, and categorizes their demeanor on a scale from good to bad. Generally speaking, characters that are made up of mostly yellow, green and blue were considered to be more “good”, whereas those that are primarily made up of red, black and purple were interpreted as more “evil” by the audience.

Disney heroes and villains color wheel infographic

So…what does this mean for you, as a designer? Well, if you’re looking to communicate a certain message in your web designs/brand/infographics/…, using color is one of the ways that we can do that. Let’s take a look a 15 Disney color schemes, ranging from “Innocent Princess” to “Malicious Queen”, to better understand how colors affect us.

15 Color Schemes From Good to Evil

In this section, 15 color schemes have been organised into 7 different categories, ranging from good to evil. They’ve been draw from the above color wheel and you’ll notice they tend to range from lighter schemes to darker ones.

1. The Quintessential Princess Color Schemes

These “Quintessential Princess” color schemes are perfect if you’re trying to depict that innocent/selfless vibe. If your company is a charity or social enterprise dedicated to helping humankind, then these colors are right up your alley.

Quintessential Princess Color Scheme 1

Quintessential Princess Color Scheme 2

Who inspired these color schemes?

Snow White and Belle.

Snow White and Belle

2. The Adventurer Color Schemes

“Adventurer” color schemes are ideal for brands and businesses with a focus on travel, nature, or anything outdoorsy. Can you guess what well-known Disney characters they’ve been inspired by?

Adventure Color Scheme 1

Adventure Color Scheme 2

Who inspired these color schemes?

Peter Pan and Mulan.

Peter Pan and Mulan

3. The “There’s Something Bigger Out There” Color Schemes

The “There’s Something Bigger Out There” color schemes are for those that have an innovative vision for changing the world. Is your project the next Tesla or Google? You can convey that with these stunningly ambitious color schemes.

Something Bigger Color Scheme 1

Something Bigger Color Scheme 2

Who inspired these color schemes?

Hercules and Nemo.

Hercules and Nemo

4. The Powerful Femme Color Schemes

Are you trying to send the message that your brand is confident, strong, high-end and maybe even daring? Well, these “Powerful Femme” color schemes are exactly what you need to add that sense of alluring dominance to your designs.

Continue reading %15 Color Schemes From Disney Heroes and Villains%


Source: Sitepoint

10 Ways to Keep Your Programming Skills Sharp Between Jobs

Woman balancing on tightrope over a chasm

Keeping up to date in the fast-moving world of programming and development is an ever-present issue for developers. That challenge can be even greater if you’re not currently employed, because a job tends to keep you at the coal face and aware of the newest developments in tech.

In fact, one could argue that anything tech-related moves at hyperactive speeds, meaning you have more of a responsibility — and more work involved — to stay current.

Things happen fast in this industry, which means you need to remain vigilant. It does you no good to let your skills, knowledge or experience fade away. How can you stay current? What are some things you can do to keep your skills fresh, especially if you’re not practicing or using them in a job?

Believe it or not, there are many opportunities for honing your skills or keeping things fresh, even if you’re not employed. Not all of them are boring, either, meaning you won’t be slogging through thick textbooks or online guides just to stay relevant.

1. Play Some Coding Games

In recent years, online courses and teaching applications have cropped up — one of which incorporates video games and software development or coding. If that sounds fun, it is!

While some of the games and opportunities were designed with beginners in mind, that doesn’t mean the content doesn’t eventually touch on more experienced concepts. Platforms like CodeCombat, CodeMonkey, CheckIO, CodeWars and many others allow you to play a game, all while being exposed to coding and programming references.

Never underestimate having fun and learning as a collaborative experience. You’d be surprised how much more information and ideas you retain.

2. Listen to Audio Books, Anywhere

OK, here’s the dilemma. It’s no fun reading expansive textbooks and online resources, especially when they’re filled to the brim with programming and coding references. No matter how much you like software development, or development of any kind, there’s not much to spruce up these resources. They are downright boring at times.

Unfortunately, many of those resources — including official documentation — are a must-read. They detail important elements and concepts that can be used when working with a particular language, IDE or toolset.

That’s where audio books or text-to-voice tools come into play. Instead of reading a boring book in your free time, you can listen to audio books, anywhere. Some examples include during your morning commute, in the shower, during your workout or while you’re making dinner. Any downtime is an opportunity to listen to some audio books.

3. Volunteer or Offer Discounted Work

No one likes to work for free, and that’s especially true of any creative — programmers and developers included. But if you’re unemployed and you want to keep your skills fresh, you might need to compromise in some way, especially if you’re having a tough time finding work.

You can volunteer your services for ongoing projects, or if you’re not OK with going pro bono, you can offer discounted or cheaper services. This method isn’t ideal for everyone, and that’s OK.

It’s best to get involved with movements or projects you’re passionate about, as they will provide more than just monetary rewards. If you love games, for example, you could help a friend or colleague with their game development project.

Also, try to stick with the type of work and content — like the same language — you’ll be working with in a more professional environment. This helps you work on your current skills and keep everything relevant.

4. Take an Online Coding Course or Two

Want to refresh your knowledge or become a little more experienced with a topic or language? Take one of the hundreds — or thousands — of available online coding classes. The best part is that not all of them are designed in the same way. If you’re more of a visual learner, there are plenty of platforms that offer visual demonstrations. Conversely, if you’re more of a hands-on person, there are plenty of courses that get you into the actual development and programming work you’re used to. That’s what makes online coding courses such a viable choice.

Check out platforms like Lynda, Treehouse, CodeSchool and many others. Almost all of them offer a free or trial period where you can sample the courses offered. If you don’t like the material on one platform, simply move to another.

5. Head to YouTube

YouTube offers an endless stream of entertainment and educational content, and when you’re learning development or programming, it’s no different. The same is true if you just want a refresher, or want to keep your skills relevant.

The YouTube community offers thousands of videos in pretty much any topics and genres you can think of. Not all of them are tutorial or guide-based either, so there are plenty of opportunities to brush up on your knowledge.

Continue reading %10 Ways to Keep Your Programming Skills Sharp Between Jobs%


Source: Sitepoint

Removing Friction In UX: Last-Minute Travel Planning And Activity Booking (A Case Study)




 


 

Most travellers make last-minute decisions, even though they spend significant time researching things to do before embarking on their trip. Finding a hotel and flight is relatively easy, but when it comes to tours and activities, the problem is that late or last-minute bookings are not always available.

Removing Friction In UX: Last-Minute Travel Planning And Activity Booking

And if they are available, the process of making a purchase online is often hard. The mobile experience can also be limited because many websites are slow or their booking process is long and complex.

The post Removing Friction In UX: Last-Minute Travel Planning And Activity Booking (A Case Study) appeared first on Smashing Magazine.


Source: Smashing Magazine

How to Create a Real-Time Feed Using Phoenix and React

Final product image
What You’ll Be Creating

In this tutorial, I’ll show you how we can use the power of React and Phoenix to create a feed application which will update itself in real time as we add new feeds to our database.

Introduction

Elixir is known for its stability and real-time features, and Phoenix leverages the Erlang VM ability to handle millions of connections alongside Elixir’s beautiful syntax and productive tooling. This will help us in generating the real-time updating of data through APIs which would be consumed by our React application to show the data on the user interface.

Getting Started

You should have Elixir, Erlang, and Phoenix installed. More about that can be found on the Phoenix framework’s website. Apart from that, we will be using a bare-bones React boilerplate since it’s well-maintained and properly documented.

Making the APIs Ready

In this section, we will bootstrap our Phoenix API-only application and add channels to update the APIs in real time. We will just be working with a feed (it will contain a title and a description), and once its value is changed in the database, the API will send the updated value to our front-end application.

Bootstrap the App

Let’s first bootstrap the Phoenix application.

mix phoenix.new  realtime_feed_api --no-html --no-brunch

This will create a bare-bones Phoenix application inside a folder named realtime_feed_api. The --no-html option won’t create all the static files (which is useful if you’re creating an API-only application), and the --no-brunch option won’t include Phoenix’s static bundler, Brunch. Please make sure you install the dependencies when it prompts.

Let’s go inside the folder and create our database.

cd realtime_feed_api

We will have to remove the username and password fields from our config/dev.exs file since we will be creating our database without any username or password. This is just to keep things simple for this post. For your application, make sure that you create a database first, with a username and password.

mix ecto.create

The above command will create our database. Now, we can run our Phoenix server and test if everything is fine at this point.

mix phoenix.server

The above command will fire our Phoenix server, and we can go to http://localhost:4000 to see it running. Currently, it will throw a no route found error since we haven’t created any routes yet!

Feel free to verify your changes with my commit.

Add the Feed Model

In this step, we will add our Feed model to our Phoenix app. The Feeds model will consist of a title and a description.

mix phoenix.gen.json Feed feeds title:string description:string

The above command will generate our Feed model and controller. It will also generate the specs (which we won’t be modifying in this tutorial, just to keep it short).

You need to add the /feeds route in your web/router.ex file inside the api scope:

resources "/feeds", FeedController, except: [:new, :edit]

We would also need to run the migration to create the feeds table in our database:

mix ecto.migrate

Now, if we go to http://localhost:4000/api/feeds, we will see that the API is sending us a blank response since there is no data in our feeds table.

You can check my commit for reference.

Add the Feed Channel

In this step, we will add our Feed channel to our Phoenix app. Channels provide a means for bidirectional communication from clients that integrate with the Phoenix.PubSub layer for soft real-time functionality.

mix phoenix.gen.channel feed

The above command will generate a feed_channel.ex file inside the web/channels folder. Through this file, our React application will exchange the updated data from the database using sockets.

We need to add the new channel to our web/channels/user_socket.ex file:

channel "feeds", RealtimeFeedApi.FeedChannel

Since we are not doing any authentication for this application, we can modify our web/channels/feed_channel.ex file. We will need one join method for our React application to join our feed channel, one handle_out method to push the payload through a socket connection, and one broadcast_create method which will broadcast a payload whenever a new feed is created in the database.

The three methods are defined above. In the broadcast_create method, we are using app/FeedsPage/HAS_NEW_FEEDS since we will be using that as a constant for our Redux state container, which will be responsible for letting the front-end application know that there are new feeds in the database. We will discuss that when we build our front-end application.

In the end, we will only need to call the broadcast_change method through our feed_controller.ex file whenever new data is inserted in our create method. Our create method will look something like:

The create method is responsible for inserting a new data in the database. You can check my commit for reference.

Add CORS Support for the API

We need to implement this support since, in our case, the API is served from http://localhost:4000 but our front-end application will be running on http://localhost:3000. Adding CORS support is easy. We will just need to add cors_plug to our mix.exs file:

Now, we stop our Phoenix server using Control-C and fetch the dependency using the following command:

mix deps.get

We will need to add the following line to our lib/realtime_feed_api/endpoint.ex file:

plug CORSPlug

You can check my commit. We are done with all our back-end changes. Let’s now focus on the front-end application.

Update the Front-End Data in Real Time

As mentioned earlier, we will use react-boilerplate to get started with our front-end application. We will use Redux saga which will listen to our dispatched actions, and based on that, the user interface will update the data. 

Since everything is already configured in the boilerplate, we don’t have to configure it. However, we will make use of the commands available in the boilerplate to scaffold our application. Let’s first clone the repository:

git clone https://github.com/react-boilerplate/react-boilerplate.git realtime_feed_ui

Bootstrap the App

Now, we will need to go inside the realtime_feed_ui folder and install the dependencies.

cd realtime_feed_ui && npm run setup

This initializes a new project with this boilerplate, deletes the react-boilerplate git history, installs the dependencies, and initializes a new repository.

Now, let’s delete the example app which is provided by the boilerplate, and replace it with the smallest amount of boilerplate code necessary to start writing our app:

npm run clean

We can now start our application using npm run start and see it running at http://localhost:3000/.

You can refer to my commit.

Add the Necessary Containers

In this step, we will add two new containers, FeedsPage and AddFeedPage, to our app. The FeedsPage container will show a list of feeds, and the AddFeedPage container will allow us to add a new feed to our database. We will use the react-boilerplate generators to create our containers.

npm run generate container

The above command is used to scaffold a container in our app. After you type this command, it will ask for the name of the component, which will be FeedsPage in this case, and we will use the Component option in the next step. We won’t be needing headers, but we will need actions/constants/selectors/reducer as well as sagas for our asynchronous flows. We don’t need i18n messages for our application. We will also need to follow a similar approach to create our AddFeedPage container.

Now, we have a bunch of new files to work with. This saves us a lot of time. Otherwise, we would have to create and configure all these files by ourselves. Also, the generator creates test files, which are very useful, but we won’t be writing tests as part of this tutorial.

Let’s just quickly add our containers to our routes.js file:

This will add our FeedsPage container to our /feeds route. We can verify this by visiting http://localhost:3000/feeds. Currently, it will be totally blank since we don’t have anything in our containers, but there won’t be any errors in the console of our browser.

We will do the same for our AddFeedPage container.

You can refer to my commit for all the changes.

Build the Feeds Listing Page

In this step we will build the FeedsPage which will list all our feeds. For the sake of keeping this tutorial small, we won’t be adding any styles here, but at the end of our application, I’ll make a separate commit which will add some designs to our application.

Let’s start by adding our constants in our app/containers/FeedsPage/constants.js file:

We will need these four constants:

  • The FETCH_FEEDS_REQUEST constant will be used to initialize our fetching request.
  • The FETCH_FEEDS_SUCCESS constant will be used when the fetching request is successful.
  • The FETCH_FEEDS_ERROR constant will be used when the fetching request is unsuccessful.
  • The HAS_NEW_FEEDS constant will be used when there is a new feed in our database.

Let’s add our actions in our app/containers/FeedsPage/actions.js file:

All these actions are self-explanatory. Now, we will structure the initialState of our application and add a reducer in our app/containers/FeedsPage/reducer.js file:

This will be the initialState of our application (the state before the fetching of the data starts). Since we are using ImmutableJS, we can use its List data structure to store our immutable data. Our reducer function will be something like the following:

Basically, what we are doing here is changing our state based on the constant from our actions. We can show loaders and error messages very easily in this manner. It will be much clearer when we use this in our user interface.

It’s time to create our selectors using reselect, which is a selector library for Redux. We can extract complex state values very easily using reselect. Let’s add the following selectors to our app/containers/FeedsPage/selectors.js file:

As you can see here, we are using the structure of our initialState to extract data from our state. You just need to remember the syntax of reselect.

It’s time to add our sagas using redux-saga. Here, the basic idea is that we need to create a function to fetch data and another function to watch the initial function so that whenever any specific action is dispatched, we need to call the initial function. Let’s add the function which will fetch our list of feeds from the back-end application in our app/containers/FeedsPage/sagas.js file:

Here, request is just a util function which does our API call to our back end. The whole file is available at react-boilerplate. We will make a slight change in it after we complete our sagas.js file.

We also need to create one more function to watch the getFeeds function:

As we can see here, the getFeeds function will be called when we dispatch the action which contains the FETCH_FEEDS_REQUEST constant.

Now, let’s copy the request.js file from react-boilerplate into our application inside the app/utils folder and then modify the request function:

I’ve just added a few defaults which will help us in reducing the code later on since we don’t need to pass the method and headers every time. Now, we need to create another util file inside the app/utils folder. We will call this file socketSagas.js. It will contain four functions: connectToSocketjoinChannelcreateSocketChannel, and handleUpdatedData

The connectToSocket function will be responsible for connecting to our back-end API socket. We will use the phoenix npm package. So we will have to install it:

npm install phoenix --save

This will install the phoenix npm package and save it to our package.json file. Our connectToSocket function will look something like the following:

Next, we define our joinChannel function, which will be responsible for joining a particular channel from our back end. The joinChannel function will have the following contents:

If the joining is successful, we will log ‘Joined successfully’ just for testing. If there was an error during the joining phase, we will also log that just for debugging purposes.

The createSocketChannel will be responsible for creating an event channel from a given socket.

This function will also be useful if we want to unsubscribe from a particular channel.

The handleUpdatedData will just call an action passed to it as an argument.

Now, let’s add the rest of the sagas in our app/containers/FeedsPage/sagas.js file. We will create two more functions here: connectWithFeedsSocketForNewFeeds and watchConnectWithFeedsSocketForNewFeeds

The connectWithFeedsSocketForNewFeeds function will be responsible for connecting with the back-end socket and checking for new feeds. If there are any new feeds, it will call the createSocketChannel function from the utils/socketSagas.js file, which will create an event channel for that given socket. Our connectWithFeedsSocketForNewFeeds function will contain the following:

And the watchConnectWithFeedsSocketForNewFeeds will have the following:

Now, we will tie everything with our app/containers/FeedsPage/index.js file. This file will contain all our user interface elements. Let’s start by calling the prop which will fetch the data from the back end in our componentDidMount:

This will fetch all the feeds. Now, we need to call the fetchFeedsRequest prop again whenever the hasNewFeeds prop is true (you can refer to our reducer’s initialState for the structure of our app):

After this, we just render the feeds in our render function. We will create a feedsNode function with the following contents:

And then, we can call this method in our render method:

If we now go to http://localhost:3000/feeds, we will see the following logged in our console:

Joined successfully Joined feeds

This means that our feeds API is working fine, and we have successfully connected our front end with our back-end application. Now, we just need to create a form through which we can enter a new feed.

Feel free to refer to my commit since a lot of stuff went in this commit!

Build the Form to Add a New Feed

In this step, we will be creating a form through which we can add a new feed to our database.

Let’s start by adding the constants to our app/containers/AddFeedPage/constants.js file:

The UPDATE_ATTRIBUTES constant will be used when we add some text to the input box. All the other constants will be used for saving the feed title and description to our database.

The AddFeedPage container will use four actions: updateAttributessaveFeedRequestsaveFeed, and saveFeedError. The updateAttributes function will update the attributes of our new feed. It means whenever we type something in the input box of the feed title and description, the updateAttributes function will update our Redux state. These four actions will look something like the following:

Next, let’s add our reducer functions in app/containers/AddFeedPage/reducer.js file. The initialState will look like the following:

And the reducer function will look something like:

Next, we will be configuring our app/containers/AddFeedPage/selectors.js file. It will have four selectors: titledescriptionerror, and saving. As the name suggests, these selectors will extract these states from the Redux state and make it available in our container as props.

These four functions will look like the following:

Next, let’s configure our sagas for AddFeedPage container. It will have two functions: saveFeed and watchSaveFeed. The saveFeed function will be responsible for doing the POST request to our API, and it will have the following:

The watchSaveFeed function will be similar to our previous watch functions:

Next, we just need to render the form in our container. To keep things modularized, let’s create a sub-component for the form. Create a new file form.js inside our app/containers/AddFeedPage/sub-components folder (the sub-components folder is a new folder which you will have to create). It will contain the form with one input box for the title of the feed and one textarea for the description of the feed. The render method will have the following contents:

We will create two more functions: handleChange and handleSubmit. The handleChange function is responsible for updating our Redux state whenever we add some text, and the handleSubmit function calls our API to save the data in our Redux state.

The handleChange function has the following:

And the handleSubmit function will contain the following:

Here, we are saving the data and then clearing the form values.

Now, back to our app/containers/AddFeedPage/index.js file, we will just render the form we just created.

Now, all our coding is complete. Feel free to check my commit if you have any doubts.

Finalizing

We have completed building our application. Now, we can visit http://localhost:3000/feeds/new and add new feeds which will be rendered in real time on http://localhost:3000/feeds. We don’t need to refresh the page to see the new feeds. You can also try this by opening http://localhost:3000/feeds on two tabs side by side and test it!

Conclusion

This will be just a sample application to show the real powers of combining Phoenix with React. We use real-time data in most places now, and this might just help you get a feel for developing something like that. I hope that you found this tutorial useful.


Source: Nettuts Web Development

Improve Web Typography with CSS Font Size Adjust

CSS font-size-adjust Property

The font-size-adjust property in CSS allows developers to specify the font-size based on the height of lowercase letters instead of uppercase letters. This can significantly improve the legibility of text on the web.

In this article, you will learn about the importance of the font-size-adjust property and how to use it properly in your projects.

The Importance of font-size-adjust

Most websites that you visit consist primarily of text. Since the written word is such an important part of a website, it makes sense to pay special attention to the typeface you are using to display your information. Choosing the right typeface can result in a pleasant reading experience. However, using the wrong one can make the website illegible. Once you have decided the typeface you want to use, you generally choose a proper size for it.

The font-size property sets the size of all the font-family options that you want to use on a website. However, most of the times it is generally chosen in such a way that your first font-family option looks good. The problem arises when the first choice is not available for some reason and the browser renders the text using one of the fallback fonts listed in the CSS document.

For instance, given this CSS rule:

[code language=”css”]
body {
font-family: ‘Lato’, Verdana, sans-serif;
}
[/code]

If ‘Lato’, which your browser downloads from Google Fonts, is not available, the next fallback font, in this case Verdana, will be used instead. However, it’s likely that the font-size value was chosen with ‘Lato’ in mind, rather than with Verdana.

What Is the Aspect Value of a Web Font?

The apparent size of a font as well as its legibility can vary greatly for a constant font-size value. This is especially true for scripts like Latin that distinguish between upper and lowercase letters. In such cases, the ratio of the height of lowercase letters to their uppercase counterparts is an important factor in deciding the legibility of the given font. This ratio is commonly called the aspect value of a font.

As I mentioned earlier, once you set a font-size value, it will remain constant for all the font families. However, this may affect the legibility of the fallback font if its aspect value is too different from the aspect value of the first choice font.

The role of the font-size-adjust property becomes very important in such situations, as it allows you to set the x-height of all the fonts to the same value thereby improving their legibility.

Choosing the Right Value for font-size-adjust

Now that you know the importance of using the font-size-adjust property, it is time to learn how to use it on your website.

Continue reading %Improve Web Typography with CSS Font Size Adjust%


Source: Sitepoint

How to Customize WooCommerce Product Pages

When planning a WooCommerce store, you will have to answer a lot of up-front questions that will have a serious impact on the future success of the store. The setup of the store is a serious challenge because once done, changes to the setup and design of the store are always difficult. To customize WooCommerce product pages, you’ll have to consider the options available to you, which I’ll get into in this post.

Now once the store is up, the next challenge is the clutter on the product pages. WooCommerce Single Product page has a lot of elements that do not directly help with the custom design and setup of the store. Two common culprits are product categories and star ratings. Not every store needs these two elements on the Single Product page. Similarly, other elements also need to be repositioned in order to fit into the store’s custom design.

All these challenges could be tackled very easily through WooCommerce action and filter hooks. I have created this short list of things to demostrate what you could customize in the Product Page.

Customize WooCommerce Product Pages

The first thing you might wish to do is to display products in a different template than the default. The file single-product.php, which controls the template files that display product information on the frontend, should be loaded.

A common practice when customizing the template pages of parent themes and plugins that is often recommended is to make a copy of the template in the theme. Now make all changes in the copy only. This way, if the themes and plugins are updated, your custom changes will remain unaffected.

Several plugins and themes provide an extensive collection of custom action and filter hooks that allow changes directly into theme file(s). The good thing about all this is that you do not have to go through and modify the markup of the template files. The result is a cleaner code and no messy duplication of files.

I will use single-product.php to call template files that control the information and the format of how the product’s information will be displayed on the product page. Similarly, content-single-product.php is the product template and is modified to change the information and styling of the product page.
Now open single_template and add the following code to change the template for the Single Product page:

Continue reading %How to Customize WooCommerce Product Pages%


Source: Sitepoint