Friday, 31 May 2019

Implementing Private Variables In JavaScript

JavaScript (or ECMAScript) is the programming language that powers the web. Created in May 1995 by Brendan Eich, it’s found its place as a widely-used and versatile technology. Despite its success, it’s been met with its fair share of criticism, especially for idiosyncrasies. Things like objects being casted to string form when used as indices, 1 == "1" returning true, or the notoriously confusing this keyword. A particularly interesting quirk though, is the existence of various techniques for variable privacy.

In its current state, there is no "direct” way to create a private variable in JavaScript. In other languages, you can use the private keyword or double-underscores and everything works, but variable privacy in JavaScript carries characteristics that make it seem more akin to an emergent trait of the language rather than an intended functionality. Let’s introduce some background to our problem.

The "var” keyword

Before 2015, there was essentially one way to create a variable, and that was the var keyword. var is function-scoped, meaning that variables instantiated with the keyword would only be accessible to code within the function. When outside of a function, or "global” essentially, the variable will be accessible to anything executed after the definition of the variable. If you try to access the variable in the same scope before its definition, you will get undefined rather than an error. This is due to the way the var keyword "hoists."

// Define "a" in global scope
var a = 123;

// Define "b" in function scope
(function() {
  console.log(b); //=> Returns "undefined" instead of an error due to hoisting.
  var b = 456;
})();

console.log(a); // => 123
console.log(b); // Throws "ReferenceError" exception, because "b" cannot be accessed from outside the function scope.

The birth of ES6 variables

In 2015, ES6/ES2015 was made official, and with it came two new variable keywords: let and const. Both were block-scoped, meaning that variables created with the keywords would be accessible from anything within the same pair of braces. Same as with var, but the let and const variables could not be accessed outside of block scope with loops, functions, if statements, braces, etc.

const a = 123;

// Block scope example #1
if (true) {
  const b = 345;
}

// Block scope example #2
{
  const c = 678;
}

console.log(a); // 123
console.log(b); // Throws "ReferenceError" because "b" cannot be accessed from outside the block scope.
console.log(c); // Throws "ReferenceError" because "b" cannot be accessed from outside the block scope.

Since code outside of the scope cannot access the variables, we get an emergent trait of privacy. We’re going to cover some techniques for implementing it in different ways.

Using functions

Since functions in JavaScript also are blocks, all variable keywords work with them. In addition, we can implement a very useful design pattern called the "module.”

The Module Design Pattern

Google relies on the Oxford Dictionary to define a "module":

Any of a number of distinct but interrelated units from which a program may be built up or into which a complex activity may be analyzed.

—"Module" Definition 1.2

The module design pattern is very useful in JavaScript because it combines public and private components and it allows us to break a program into smaller components, only exposing what another part of the program should be able to access through a process called "encapsulation.” Through this method, we expose only what needs to be used and can hide the rest of the implementation that doesn’t need to be seen. We can take advantage of function scope to implement this.

const CarModule = () => {
  let milesDriven = 0;
  let speed = 0;

  const accelerate = (amount) => {
    speed += amount;
    milesDriven += speed;
  }

  const getMilesDriven = () => milesDriven;

  // Using the "return" keyword, you can control what gets
  // exposed and what gets hidden. In this case, we expose
  // only the accelerate() and getMilesDriven() function.
  return {
    accelerate,
    getMilesDriven
  }
};

const testCarModule = CarModule();
testCarModule.accelerate(5);
testCarModule.accelerate(4);
console.log(testCarModule.getMilesDriven());

With this, we can get the number of miles driven, as well as the amount of acceleration, but since the user doesn’t need access to the speed in this case, we can hide it by only exposing the accelerate() and getMilesDriven() method. Essentially, speed is a private variable, as it is only accessible to code inside of the same block scope. The benefit to private variables begins to become clear in this situation. When you remove the ability to access a variable, function, or any other internal component, you reduce the surface area for errors resulting from someone else mistakenly using something that wasn’t meant to be.

The alternative way

In this second example, you’ll notice the addition of the this keyword. There’s a difference between the ES6 arrow function ( => ) and the traditional function(){}. With the function keyword, you can use this, which will be bound to the function itself, whereas arrow functions don’t allow any kind of use of the this keyword. Both are equally-valid ways to create the module. The core idea is to expose parts that should be accessed and leave other parts that should not be interacted with, hence both public and private data.

function CarModule() {
  let milesDriven = 0;
  let speed = 0;

  // In this case, we instead use the "this" keyword,
  // which refers to CarModule
  this.accelerate = (amount) => {
    speed += amount;
    milesDriven += speed;
  }

  this.getMilesDriven = () => milesDriven;
}

const testCarModule = new CarModule();
testCarModule.accelerate(5);
testCarModule.accelerate(4);
console.log(testCarModule.getMilesDriven());

Enter ES6 Classes

Classes were another addition that came with ES6. Classes are essentially syntactic sugar — in other words, still a function, but potentially "sweetening” it into a form that’s easier to express. With classes, variable privacy is (as of now) close to impossible without making some major changes to the code.

Let’s take a look at an example class.

class CarModule {
  /*
    milesDriven = 0;
    speed = 0;
  */
  constructor() {
    this.milesDriven = 0;
    this.speed = 0;
  }
  accelerate(amount) {
    this.speed += amount;
    this.milesDriven += this.speed;
  }
  getMilesDriven() {
    return this.milesDriven;
  }
}

const testCarModule = new CarModule();
testCarModule.accelerate(5);
testCarModule.accelerate(4);
console.log(testCarModule.getMilesDriven());

One of the first things that stands out is that the milesDriven and speed variable are inside of a constructor() function. Note that you can also define the variables outside of the constructor (as shown in the code comment), but they are functionally the same regardless. The problem is that these variables will be public and accessible to elements outside of the class.

Let’s look at some ways to work around that.

Using an underscore

In cases where privacy is to prevent collaborators from making some catastrophic mistake, prefixing variables with an underscore (_), despite still being "visible” to the outside, can be sufficient to signal to a developer, "Don’t touch this variable.” So, for example, we now have the following:

// This is the new constructor for the class. Note that it could
// also be expressed as the following outside of constructor().
/*
  _milesDriven = 0;
  _speed = 0;
*/
constructor() {
  this._milesDriven = 0;
  this._speed = 0;
}

While this does work for its specific use case, it’s still safe to say that it’s less than ideal on many levels. You can still access the variable but you also have to modify the variable name on top of that.

Putting everything inside the constructor

Technically, there is a method for variable privacy in a class that you can use right now, and that’s placing all variables and methods inside the constructor() function. Let’s take a look.

class CarModule {
  constructor() {
    let milesDriven = 0;
    let speed = 0;

    this.accelerate = (amount) => {
      speed += amount;
      milesDriven += speed;
    }

    this.getMilesDriven = () => milesDriven;
  }
}

const testCarModule = new CarModule();
testCarModule.accelerate(5);
testCarModule.accelerate(4);
console.log(testCarModule.getMilesDriven());
console.log(testCarModule.speed); // undefined -- We have true variable privacy now.

This method accomplishes true variable privacy in the sense that there is no way to directly access any variables that aren’t intentionally exposed. The problem is that we now have, well, code that doesn’t look all that great compared to what we had before, in addition to the fact that it defeats the benefits of the syntactic sugar we had with classes. At this point, we might as well be using the function() method.

Using WeakMap

There’s another, more creative way to go about making a private variable, and that’s using WeakMap(). Although it may sound similar to Map, the two are very different. While maps can take any type of value as a key, a WeakMap only take objects and deletes the values in the WeakMap when the object key is garbage collected. In addition, a WeakMap cannot be iterated through, meaning that you must have access to the reference to an object key in order to access a value. This makes it rather useful for creating private variables, since the variables are effectively invisible.

class CarModule {
  constructor() {
    this.data = new WeakMap();
    this.data.set(this, {
      milesDriven: 0,
      speed: 0
    });
  }

  accelerate(amount) {
    // In this version, we instead create a WeakMap and
    // use the "this" keyword as a key, which is not likely
    // to be used accidentally as a key to the WeakMap.
    const data = this.data.get(this);
    const speed = data.speed + amount;
    const milesDriven = data.milesDriven + data.speed;
    this.data.set({ speed, milesDriven });
  }

  this.getMilesDriven = () => this.data.get(this).milesDriven;
}

const testCarModule = new CarModule();
testCarModule.accelerate(5);
testCarModule.accelerate(4);
console.log(testCarModule.getMilesDriven());
console.log(testCarModule.data); //=> WeakMap { [items unknown] } -- This data cannot be accessed easily from the outside!

This solution is good at preventing an accidental usage of the data, but it isn’t truly private, since it can still be accessed from outside the scope by substituting this with CarModule. In addition, it adds a fair amount of complexity to the mix and, therefore, isn’t the most elegant solution.

Using symbols to prevent collisions

If the intent is to prevent name collisions, there is a useful solution using Symbol. These are essentially instances that can behave as unique values that will never be equal to anything else, except its own unique instance. Here’s an example of it in action:

class CarModule {
  constructor() {
    this.speedKey = Symbol("speedKey");
    this.milesDrivenKey = Symbol("milesDrivenKey");
    this[this.speedKey] = 0;
    this[this.milesDrivenKey] = 0;
  }

  accelerate(amount) {
    // It's virtually impossible for this data to be
    // accidentally accessed. By no means is it private,
    // but it's well out of the way of anyone who would
    // be implementing this module.
    this[this.speedKey] += amount;
    this[this.milesDrivenKey] += this[this.speedKey];
  }

  getMilesDriven() {
    return this[this.milesDrivenKey];
  }
}

const testCarModule = new CarModule();
testCarModule.accelerate(5);
testCarModule.accelerate(4);
console.log(testCarModule.getMilesDriven());
console.log(testCarModule.speed); // => undefined -- we would need to access the internal keys to access the variable.

Like the underscore solution, this method more or less relies on naming conventions to prevent confusion.

TC39 private class field proposal

Recently, a new proposal was introduced that would introduce private variables to classes. It’s rather simple: put a # before the name of a variable, and it becomes private. No extra structural changes needed.

class CarModule {
  #speed = 0
  #milesDriven = 0
  
  accelerate(amount) {
    // It's virtually impossible for this data to be
    // accidentally accessed. By no means is it private,
    // but it's well out of the way of anyone who would
    // be implementing this module.
    this.#speed += amount;
    this.#milesDriven += speed;
  }

  getMilesDriven() {
    return this.#milesDriven;
  }
}

const testCarModule = new CarModule();
testCarModule.accelerate(5);
testCarModule.accelerate(4);
console.log(testCarModule.getMilesDriven());
console.log(testCarModule.speed); //=> undefined -- we would need to access the internal keys to access the variable.

The private class field proposal is not standard and cannot be done without using Babel as of this writing, so you’ll have to wait a bit for it to be usable on major browsers, Node, etc.

Conclusion

That sums up the various ways you can implement private variables in JavaScript. There isn’t a single "correct” way to do it. These will work for different needs, existing codebases, and other constraints. While each has advantages and disadvantages, ultimately, all methods are equally valid as long as they effectively solve your problem.

Thanks for reading! I hope this provides some insight into how scope and variable privacy can be applied to improve your JavaScript code. This is a powerful technique and can support so many different methods and make your code more usable and bug-free. Try out some new examples for yourself and get a better feel.

The post Implementing Private Variables In JavaScript appeared first on CSS-Tricks.



from CSS-Tricks http://bit.ly/2MnVr49
via IFTTT

Weekly Platform News: Favicon Guidelines, Accessibility Testing, Web Almanac

Reducing motion with the picture element

Here’s a bonafide CSS/HTML trick from Brad Frost and Dave Rupert where they use the <picture> element to switch out a GIF file with an image if the user has reduced motion enabled. This is how Brad goes about implementing that:

<picture>
  <!-- This image will be loaded if the media query is true  -->
  <source srcset="no-motion.jpg" media="(prefers-reduced-motion: reduce)"></source>

  <!--  Otherwise, load this gif -->
  <img srcset="animated.gif alt="brick wall"/>
</picture>

How nifty is this? It makes me wonder if there are other ways this image-switching technique can be used besides accessibility and responsive images...

Also it’s worth noting that Eric Bailey wrote about the reduced motion media query a while back where he digs into its history and various approaches to use it.

Direct Link to ArticlePermalink

The post Reducing motion with the picture element appeared first on CSS-Tricks.



from CSS-Tricks http://bit.ly/2XaVxwL
via IFTTT

Wednesday, 29 May 2019

A Quick Look at the First Public Working Draft for Color Adjust Module 1

The difference between keyboard and screen reader navigation

There are a few differences between keyboards and screen readers and LĂ©onie Watson highlights of them:

When using the tab key, keyboard focus and screen reader focus are synchronised with each other. The rest of the time, screen reader users have an enormous range of commands at their disposal for reading and navigating content independently of keyboard focus. The commands vary between screen readers, but they all have one thing in common: they’re tied to different HTML elements.

This is also a good reminder that screen readers behave differently from one another. It’s worth doing some research to see how our sites work in all these environments. One thing is clear from this post though: writing semantic and concise HTML is the best way to improve accessibility for both users with keyboards and screen readers. For example, Scott O'Hara has this recent post on best practices using the tabindex attribute to ensure accessible navigation using the keyboard.

Direct Link to ArticlePermalink

The post The difference between keyboard and screen reader navigation appeared first on CSS-Tricks.



from CSS-Tricks http://bit.ly/2M8kc4b
via IFTTT

Creating Interactive Maps in WordPress with MapSVG

Wednesday, 22 May 2019

Rural Local SEO: A Marketing Package Strong on Education

The Browser Can Remember Edited Content

Getting Started with React Testing Library

I can guess what you are thinking: another React testing library? So many have already been covered here on CSS-Tricks (heck, I’ve already posted one covering Jest and Enzyme) so aren’t there already enough options to go around?

But react-testing-library is not just another testing library. It’s a testing library, yes, but one that’s built with one fundamental principle that separates it from the rest.

The more your tests resemble the way your software is used, the more confidence they can give you.

It tries to address tests for how a user will use your application. In fact, it’s done in such a way that tests won’t break even when you refactor components. And I know that’s something we’ve all run into at some point in our React journey.

We’re going to spend some time writing tests together using react-testing-library for a light to-do application I built. You can clone the repo locally:

git clone https://github.com/kinsomicrote/todoapp-test.git

And, if you do that, install the required packages next:

## yarn
yarn add --dev react-testing-library jest-dom

## npm
npm install --save-dev react-testing-library jest-dom

In case you’re wondering why Jest is in there, we’re using it for assertion. Create a folder called __test__ inside the src directory and create a new file called App.test.js.

Taking snapshots

Snapshot tests keep a record of tests that have been performed on a tested component as a way to visually see what’s changes between changes.

When we first run this test, we take the first snapshot of how the component looks. As such, the first test is bound to pass because, well, there’s no other snapshot to compare it to that would indicate something failed. It only fails when we make a new change to the component by adding a new element, class, component, or text. Adding something that was not there when the snapshot was either created or last updated.

The snapshot test will be the first test we will be writing here. Let’s open the App.test.js file and make it look like this:

import React from 'react';
import { render, cleanup } from "react-testing-library";
import "jest-dom/extend-expect";
import App from './App';

afterEach(cleanup);

it("matches snapshot", () => {
  const { asFragment } = render(<App />);
  expect(asFragment()).toMatchSnapshot();
});

This imports the necessary packages we are using to write and run the tests. render is used to display the component we want to test. We make use of cleanup to clear things out after each test runs — as you can see with the afterEach(cleanup) line.

Using asFragment, we get a DocumentFragment of the rendered component. Then we expect it to match the snapshot that had been created.

Let’s run the test to see what happens:

## yarn
yarn test

## npm
npm test

As we now know, a snapshot of the component gets created in a new folder called __snapshots__ inside the __tests__ directory if this is our first test. We actually get a file called App.test.js.snap in there that will look like this:

// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`matches snapshot 1`] = `
<DocumentFragment>
  <div
    class="container"
  >
    <div
      class="row"
    >
      <div
        class="col-md-6"
      >
        <h2>
          Add Todo
        </h2>
      </div>
    </div>
    <form>
      <div
        class="row"
      >
        <div
          class="col-md-6"
        >
          <input
            class="form-control"
            data-testid="todo-input"
            placeholder="Enter a task"
            type="text"
            value=""
          />
        </div>
      </div>
      <div
        class="row"
      >
        <div
          class="col-md-6"
        >
          <button
            class="btn btn-primary"
            data-testid="add-task"
            type="submit"
          >
            Add Task
          </button>
        </div>
      </div>
    </form>
    <div
      class="row todo-list"
    >
      <div
        class="col-md-6"
      >
        <h3>
          Lists
        </h3>
        <ul
          data-testid="todos-ul"
        >
          <li>
            <div>
              Buy Milk
              <button
                class="btn btn-danger"
              >
                X
              </button>
            </div>
          </li>
          <li>
            <div>
              Write tutorial
              <button
                class="btn btn-danger"
              >
                X
              </button>
            </div>
          </li>
        </ul>
      </div>
    </div>
  </div>
</DocumentFragment>
`;

Now, let’s Test DOM elements and events

Our app includes two to-do items that display by default the first time the app runs. We want to make sure that they do, in fact, show up by default on the first app run so, to test this, we have to target the unordered list (<ul>) and check the length. We expect the length to be equal to two — the number of items.

it('it displays default todo items', () => {
  const { getByTestId } = render(<App />);
  const todoList = getByTestId('todos-ul');
  expect(todoList.children.length).toBe(2);  
});

We’re making use of getByTestId in that snippet to extract the test IDs from the App component. We then set todoList to target the todos-ul element. That’s what should return as two.

Using what we’ve learned so far, see if you can write a test to assert that a user can enter values in the input field. Here are the things you’ll want to do:

  • Get the input field
  • Set a value for the input field
  • Trigger a change event
  • Assert that the input field has its value as the one you set for it in Step 2

Don’t peek at my answer below! Take as much time as you need.

Still going? Great! I’ll go grab some coffee and be right back.

Mmm, coffee. ☕️

Oh, you’re done! You rock. Let’s compare answers. Mine looks like this:

it('allows input', () => {
  const {getByTestId } = render(<App />)
  let item = 'Learn React'
  const todoInputElement = getByTestId('todo-input');
  todoInputElement.value = item;
  fireEvent.change(todoInputElement);
  expect(todoInputElement.value).toBe('Learn React')
});

Using getByTestId, I am able to extract the test IDs in the application. Then I create a variable which is set to the string Learn React, and make it the value of the input field. Next, I obtain the input field using its test ID and fire the change event after setting the value of the input field. With that done, I assert that the value of the input field is indeed Learn React.

Does that check out with your answer? Leave a comment if you have another way of going about it!

Next, let’s test that we can add a new to-do item. We’ll need to get the input field, the button for adding new items and the unordered list because those are all of the elements needed to create an new item.

We set a value for the input field and then trigger a button click to add the task. We’re able to do this by obtaining the button using getByText — by triggering a click event on the DOM element with the text Add Task, we should be able to add a new to-do item.

Let’s assert that the number of children (list items) in unordered list element is equal to three. This assumes that the default tasks are still in tact.

it('adds a new todo item', () => {
  const { getByText, getByTestId } = render(<App />);
  const todoInputElement = getByTestId('todo-input');
  const todoList = getByTestId('todos-ul');
  todoInputElement.value = 'Learn React';
  fireEvent.change(todoInputElement);
  fireEvent.click(getByText('Add Task'))
  expect(todoList.children.length).toBe(3); 
});

Pretty nice, right?

This is just one way to test in React

You can try react-testing-library in your next React application. The documentation in the repo is super thorough and — like most tools — the best place to start. Kent C. Dodds built it and has a full course on testing over at Frontend Masters (subscription required) that also covers the ins and outs of react-testing-library.

That said, this is just one testing resource for React. There are others, of course, but hopefully this is one you’re interested in trying out now that you’ve seen a bit of it but use what’s best for your project, of course.

The post Getting Started with React Testing Library appeared first on CSS-Tricks.



from CSS-Tricks http://bit.ly/2we6Mst
via IFTTT

Podcasts in SERPs: Is Audio SEO The Next Frontier?

Monday, 20 May 2019

The “Inside” Problem

So, you're working on a design. You need a full-width container element because the design has a background-color that goes from edge-to-edge horizontally. But the content inside doesn’t necessarily need to be edge-to-edge. You want to:

  1. Limit the width (for large screens)
  2. Pad the edges
  3. Center the content

It's "the inside problem" in web layout. It's not hard, it's just that there are lots of considerations.

The classic solution is an outer and inner container.

The parent element is naturally as wide as it's own parent, and let's assume that's the <body> element, or the entire width of the browser window. That takes the background-color and pads the left and right sides. The inside element is what limits the width inside and centers.

<footer>
  <div class="inside">
    Content
  </div>
</footer>
footer {
  --contentWidth: 400px;
  background: lightcoral;
  padding: 2rem 1rem;
}

.inside {
  max-width: var(--contentWidth);
  margin: 0 auto;
}

This is what my brain reaches for first. Doesn't use anything fancy and feels perfectly understandable. That "inside" element isn't wonderfully desirable, only because it feels like busywork to remember to add it to the markup each time this pattern is used, but it does the trick with few other downsides.

See the Pen
Classic "inside" element
by Chris Coyier (@chriscoyier)
on CodePen.

What if you only can use a single element?

These type of limitations aren't my favorite, because I feel like a healthy project allows designers and developers to have whatever kind of control over the final HTML, CSS, and JavaScript output they need to do the best possible job. But, alas, sometimes you’re in a weird position as a contractor or have legacy CMS issues or whatever.

If you only have a single element to work with, padding sorrrrrta kinnnnda works. The trick is to use calc() and subtract half of the content’s maximum width from 100%.

<footer>
  Content
</footer>
footer {
  --contentWidth: 600px;
  
  background: lightcoral;
  padding: 2rem calc((100% - var(--contentWidth)) / 2);
}

See the Pen
VOYxOa
by Chris Coyier (@chriscoyier)
on CodePen.

The problem here is that it doesn't prevent edge-touching, which might make this entirely unacceptable. Maybe you could select elements inside (paragraphs and whatnot...) and add padding to those (with a universal selector, like footer > *). It's tempting to put padding way up on the <body> or something to prevent edge-touching, but that doesn't work because we want that edge-to-edge background color.

What if you're already inside a container you can't control and need to break out of it?

Well, you can always do the ol' full-width utility thing. This will work in a centered container of any width:

.full-width {
  width: 100vw;
  margin-left: 50%;
  transform: translateX(-50%);
}

But that leaves the content inside at full width as well. So, you'd need to turn to an inside element again.

See the Pen
Full width element with inside element
by Chris Coyier (@chriscoyier)
on CodePen.

Also, as soon as you have a vertical scrollbar, that 100vw value will trigger an obnoxious horizontal scrollbar. Some sites can pull off something like this to get rid of that scroll:

body { overflow-x: hidden; }

That’s pretty nice. If you can't do that, though, you might need to set an explicit width on the scrollbar, then subtract that from 100vw.

body {
  scrollbar-width: 20px; /* future standards way */
}

body::-webkit-scrollbar { /* long-standing webkit way */
  width: 20px;
}

.full-width {
  width: calc(100vw - 20px);
}

Even that kinda sucks as it means the full-width container isn't quite full width when there is no vertical scrolling. I'd love to see CSS step it up here and help, probably with improved viewport units handling.

There are a variety of other ways of handling this full-width container thing, like Yanking to the edges with margins and such. However, they all ultimately need viewport units and suffer from the same scrollbar-related fate as a result.

If you can definitely hide the overflow-x on the parent, then extreme negative-margin and positive-padding can do the trick.

This is kinda cool in that it uses nothing modern at all. All very old school CSS properties.

See the Pen
Full Width Bars Using Negative Margins
by Chris Coyier (@chriscoyier)
on CodePen.

Can CSS Grid or Flexbox help here?

Meh. Not really.

I mean, sure, you could set up a three-column grid and place the content in the center column, while using the outside columns as padding. I don't think that's a particularly compelling use of grid and it adds complication for no benefit — that is, unless you're already using and taking advantage of grid at this scope.

Fake the edges instead.

There is no law that the background-color needs to come from one single continuous element. You could always "fake" the left and right sides by kicking out a huge box-shadow or placing a pseudo element wherever needed.

We cover various techniques around that here.

The post The “Inside” Problem appeared first on CSS-Tricks.



from CSS-Tricks http://bit.ly/2YC63gT
via IFTTT

Creating a Diversity Scholarship Program for Your Conference

4 Key Lessons Content Marketers Can Take From Data Journalists

Thursday, 16 May 2019

Iterating a React Design with Styled Components

Evergreen Googlebot

I've heard people say that the #1 most exciting and important thing that came out of Google I/O this year was the evergreen Googlebot:

Today, we are happy to announce that Googlebot now runs the latest Chromium rendering engine (74 at the time of this post) when rendering pages for Search. Moving forward, Googlebot will regularly update its rendering engine to ensure support for latest web platform features.

Before this, I guess I never even thought about it.

I guess part of it is that some people did already know that the old version didn't support some newfangled JavaScript stuff, and thus literally packaged their app with old JavaScript to be more SEO-friendly.

A bunch of people were apparently shipping older code simply for the sake of Googlebot, and now they don't have to. Sure, I'll call that a win.

Don't read this news as "don't worry about your JavaScript-rendered pages and SEO" though, because Google Webmasters is still telling us that pages with content that requires JavaScript to render are put into a special slower queue for both initial crawling and for updates. Not necessarily a penalty, but certainly a delay. I'm sure that's enough to make server-side rendering a priority for sites where SEO is the whole ballgame.

Direct Link to ArticlePermalink

The post Evergreen Googlebot appeared first on CSS-Tricks.



from CSS-Tricks http://bit.ly/2H6wp3t
via IFTTT

Using Jetpack to Accelerate WordPress Development

We’re Officially a Google Partner

We’re very pleased to announce that TRCREATIVE has recently been awarded Google Partner status. This unlocks a range of benefits that we’re excited to share with our clients who trust us to manage their online advertising campaigns. As far as we know, we’re the only creative agency in our local area to have this credential. As an official Google Partner, we have:

  • Demonstrated Google Ads skills and expertise
  • Met Google ad spend requirements
  • Delivered company/agency and client revenue growth
  • Sustained and grown our client base

Mike Lawson, co-founder of TCREATIVE, says, “We’re proud to achieve Google Partner status. This professional accreditation demonstrates our product knowledge and expertise in paid search, which confirms we offer the latest and best digital marketing services to existing and future clients.”

Google Partner status is made official with a badge that we use on our website and marketing materials, online and offline. It’s an instantly recognisable sign that confirms we’ve met performance requirements and possess the required skill set to research and set up well-structured and highly effective Google Ads campaigns.

How does Google Partner Status benefit our clients? At a glance, it shows that we’ve passed exams and we’re qualified to do a professional job when it comes to growing their business. In more detail, here are other benefits outlined:

Run cost-effective campaigns

Google Ads certification reassures our clients that their advertising budget is in safe hands. We have a certified affiliated person within our team to manage Google Ads and make most of all the options available, which can otherwise be overwhelming, unproductive and expensive if you’re not familiar with all the features and settings.

In the loop with the latest updates

We have direct access to Google’s beta features, product updates and new applications. This allows us to test and use new features in order to run the most up-to-date campaign for our clients, keeping them ahead of the competition.

Maintaining high standards

We have to continue to perform well and maintain Google’s standards in order to keep our Google Partner status. Our clients know that we meet account management best practices, which means they’ll get the most out of Google Ads.

Share expert knowledge

We have direct access to a Google representative who can advise on any account issues, suggest improvements and help resolve any problems super-quick so our clients don’t lose out. We can also share advice with other partners within the Google community.

Access to training and support

We’re invited to attend Google events and have access to the latest training and support, which is always reflected in the efficient management of our clients’ accounts.

Actively running campaigns

The Partner badge shows we’ve met the 90-day ad-spend requirement across our managed accounts and therefore are actively managing a number of client accounts.

Ultimately, Google Partner status brings peace of mind to our clients. It is official proof that we really know what we’re doing in the competitive and often complex world of Google Ads and latest PPC practices. It’s about providing a premium service that compliments your SEO. Above all, it’s about making sure our clients grow their business in the most productive and cost-effective way.



from TRCREATIVE http://bit.ly/2w0FpCb
via IFTTT

Wednesday, 15 May 2019

A Deep Dive into Native Lazy-Loading for Images and Frames

A Better Approach for Using Purgecss with Tailwind

Greg Kohn looks at how to use Purgecss — a tool that helps remove unused styles — and Tailwind — a utility-based CSS framework — and why we might want to pair these tools together:

Tailwind, by intention, is aiming to equip you with an arsenal of utility classes by generating more than you need. There are some best practices which will help keep this overall build size down, like limiting your colors and breakpoints or turning off the modules by default before adding them as necessary. Still, you’ll inevitably generate classes that go unused. And honestly, approaching your configuration with an unrelenting miserly attitude will slow you down and make development less fun. By leaning on Purgecss, there’s no worry that the CSS your users download will only include classes that are ultimately needed.

I’ve never used Tailwind or Purgecss, but I reckon the latter could be particularly useful if you have a giant old codebase and you don’t have the resources to refactor things just yet. I guess my only concern with introducing a tool like that is it could encourage folks to not refactor large and problematic areas in their styles – taking the safest route with this tool instead.

For more info about Tailwind, though, Ben Tinsley wrote a great post a while back about how to get started and Nick Basile showed us how to style a form with Tailwind.

Direct Link to ArticlePermalink

The post A Better Approach for Using Purgecss with Tailwind appeared first on CSS-Tricks.



from CSS-Tricks http://bit.ly/309RD9e
via IFTTT

TRCREATIVE is proud to celebrate 10 years in business

Time flies when you’re busy working on creative design, web design and build and digital marketing. One minute, baby steps as the business gets off the ground and then, before you know it, double figures. We’re delighted to hit this special milestone. Before we get the office party started, let’s look back at how and where we came about and also how far we’ve come.

TRCREATIVE founders Lynsey Edwards and Mike Lawson met and bonded over fonts and layouts when working for other agencies. Both shared a passion to set up a design studio, therefore it made perfect sense to form a creative partnership and start their own business.

Established in 2009, TRCREATIVE was born in a barn in Brereton, Cheshire. It was an old barn with no heating and no bean-to-cup coffee machine but it was a great creative space. It was soon a hub of activity and innovative design, starting with leaflets, logos and websites.

Richard Rankin, the founder of Team Rewards, a firm specialising in employee benefits, is also part of TRCREATIVE’s success story. “Richard owned the barn and put a roof over our heads 10 years ago,” says Lynsey. “His business experience and mentoring have also been invaluable.”

Indeed, the “TR” in TRCREATIVE, is a nod to Team Rewards and Richard is still very much involved; the two businesses work closely together today. There’s also been a major office upgrade – home is now a characterful building in the heart of the Cheshire countryside.

The location might have changed but the passion to create, develop and produce exceptional work for clients is as focused as it ever was, if not more. Our clients include TV celebrities Clare Balding and Charlotte Hawkins; Pets at Home; Clive Christian; Westbridge Furniture; Cheshire West & Chester Council and NHS; and a number of new brands, too.

Over the 10 years, here are 10 things we’ve learned and celebrated along the way:

  1. Learn and grow: we started out designing logos and websites. Now our services include branding, latest website design and development and a specialised digital marketing team.
  2. Embrace change: the digital world never sleeps. We’re constantly adapting to change to get best results in social media advertising, Google Ads, PPC, SEO and conversion rate optimization.
  3. Nurture team spirit: a business that pulls together, stays together. Creatives and developers within the team share ideas and inspire each other. We even take it in turns to make the tea.
  4. Keep it real: we’re a friendly team of people who communicate directly with clients. There’s no middle-man or creative hierarchy. Our streamlined operation produces better-targeted work.
  5. Make it memorable: whether it is branding, creative design or advertising campaigns, whatever we do, we make sure it is highly effective, beautiful and memorable.
  6. Never stop learning: we continue to explore, question and learn. Achieving Google Partner status or attending seminars, we do whatever it takes in order to offer the best services.
  7. Bring on the challenge: we get excited about exploring new ways to keep our clients happy, including developing unique solutions and building websites to exact requirements.
  8. Build relationships: we take pride in creating a close working relationship with our clients. So much so, we retain 93% of our clients, year on year.
  9. Love what you do: Passion keeps us fresh and motivated. We’re obsessed about creating, building and problem-solving. This is evident in our design, storytelling and communication.
  10. Look to the future: we are growing our digital marking department. We’ve also launched our own premium template websites to help smaller businesses have a better presence online.

From a big dream and an old barn to a thriving team in a vibrant design studio, we’ve come a long way. Technology and contemporary culture have a big impact on our industry, so we’re always thinking “what next?” But first, the office party. It is time to celebrate 10 years of TRCREATIVE. Did someone say cake?

 



from TRCREATIVE http://bit.ly/2WaT60c
via IFTTT

Use the Power of Social Media Advertising to Build a Stronger Business

It’s hard to attract someone’s attention if they’re not looking in your direction. They might turn around eventually, maybe, if you’re lucky, or they might not. Social media advertising works in much the same way. If customers don’t actually see your ad, all that cost and effort will be for nothing.

We’ve noticed a trend among our clients. More and more are reaching out to us for help with their digital marketing. Business posts and pages are simply not getting seen by their audience. Interaction can be as low as 2%. It could be that the post is too general or, most likely, it’s dropping in front of the wrong people at the wrong time.

The good news is that the team at TRCREATIVE can turn this around with our experience in creating well-structured and targeted social media advertising campaigns. And luck has nothing to do with it.

There are 2.32 billion monthly active Facebook users worldwide. Admittedly, that seems like an overwhelming crowd of people but it’s also a lucrative crowd. With that number of users, you’ll most definitely find an audience who wants to connect and engage with your business or organisation.

We cut through the crowd

Fortunately, we know how to cut through the two-billion-something chatter and have a direct conversation with those who are interested in what you have to say or sell.

 

Our latest social media advertising campaigns were a sell-out success for one of our clients, owners of a hotel, restaurant and wedding venue. They asked us for our help and we tailored the ads to suit their events. The first one was a Mother’s Day lunch. We set up and promoted this event on Facebook as well as creating offline media (posters) to display around the premises. The result was a 30% increase in bookings in comparison to the previous year making it a sold-out event.

Hot on the heels of this success we managed the hotel’s second event, which was a Spring Night Party. It was sold out during the course of a three-week digital marketing campaign.

How did we do this? We target the right audience based on gender, age and location and we send them in the direction of your business. We can create a call-to-action ad that allows your audience to make a booking or make a purchase, or drive them to your website. Here’s what else we can do:

  • We use the advanced targeting tools to reach a more specific audience
  • We choose the advertising objectives that work within your budget
  • We can show your ads across social media, not just Facebook, to reach a wider audience
  • We pick the creative to suit your brand
  • We know the latest advertising features available to keep you ahead of the competition

Facebook algorithm changes mean it is more important than ever to get your digital marketing right. In light of this, we make sure your advertising is structured properly and laser-targeted. We make sure you get your money’s worth and more. The power of social media advertising can make your business go from strength to strength, starting from today. Get in touch and we’ll show you how.



from TRCREATIVE http://bit.ly/2LKdl0G
via IFTTT

How to explore a SERP feature strategy with STAT

Tuesday, 14 May 2019

Integrating Third-Party Animation Libraries to a Project

Google Fonts is Adding font-display

Google announced at I/O that their font service will now support the font-display property which resolves a number of web performance issues. If you're hearing cries of joy, that's probably Chris as he punches the air in celebration. He's wanted this feature for some time and suggests that all @font-face blocks ought to consider using the property.

Zach Leatherman has the lowdown:

This is big news—it means developers now have more control over Google Fonts web font loading behavior. We can enforce instant rendering of fallback text (when using font-display: swap) rather than relying on the browser default behavior of invisible text for up to 3 seconds while the web font request is in-flight.

It’s also a bit of trailblazing, too. To my knowledge, this is the first web font host that’s shipping support for this very important font-display feature.

Yes, a big deal indeed! You may recall that font-display instructs the browser how (and kinda when) to load fonts. That makes it a possible weapon to fight fight FOUT and FOIT issues. Chris has mentioned how he likes the optional value for that exact reason.

@font-face {
  font-family: "Open Sans Regular";
  src: url("...");
  font-display: optional;
}

Oh and this is a good time to remind everyone of Monica Dinculescu’s font-display demo where she explores all the various font-display values and how they work in practice. It’s super nifty and worth checking out.

Direct Link to ArticlePermalink

The post Google Fonts is Adding font-display appeared first on CSS-Tricks.



from CSS-Tricks http://bit.ly/2VXsaAQ
via IFTTT

The New Moz Local Is on Its Way!

Posted by MiriamEllis

Exciting secrets can be so hard to keep. Finally, all of us at Moz have the green light to share with all of you a first glimpse of something we’ve been working on for months behind the scenes. Big inhale, big exhale...

Announcing: the new and improved Moz Local, to be rolled out beginning June 12!

Why is Moz updating the Moz Local platform?

Local search has evolved from caterpillar to butterfly in the seven years since we launched Moz Local. I think we’ve spent the time well, intensively studying both Google’s trajectory and the feedback of enterprise, marketing agency, and SMB customers.

Your generosity in telling us what you need as marketers has inspired us to action. Over the coming months, you’ll be seeing what Moz has learned reflected in a series of rollouts. Stage by stage, you’ll see that we’re planning to give our software the wings it needs to help you fully navigate the dynamic local search landscape and, in turn, grow your business.

We hope you’ll keep gathering together with us to watch Moz Local take full flight — changes will only become more robust as we move forward.

What can I expect from this upgrade?

Beginning June 12th, Moz Local customers will experience a fresh look and feel in the Moz Local interface, plus these added capabilities:

  • New distribution partners to ensure your data is shared on the platforms that matter most in the evolving local search ecosystem
  • Listing status and real-time updates to know the precise status of your location data
  • Automated detection and permanent duplicate closure, taking the manual work out of the process and saving you significant time
  • Integrations with Google and Facebook to gain deeper insights, reporting, and management for your location’s profiles
  • An even better data clean-up process to ensure valid data is formatted properly for distribution
  • A new activity feed to alert you to any changes to your location’s listings
  • A suggestion engine to provide recommendations to increase accuracy, completeness, and consistency of your location data

Additional features available include:

  • Managing reviews of your locations to keep your finger on the pulse of what customers are saying
  • Social posting to engage with consumers and alert them to news, offers, and other updates
  • Store locator and landing pages to share location data easily with both customers and search engines (available for Moz Local customers with 100 or more locations)

Remember, this is just the beginning. There's more to come in 2019, and you can expect ongoing communications from us as further new feature sets emerge!

When is it happening?

We'll be rolling out all the new changes beginning on June 12th. As with some large changes, this update will take a few days to complete, so some people will see the changes immediately while for others it may take up to a week. By June 21st, everyone should be able to explore the new Moz Local experience!

Don't worry — we'll have several more communications between now and then to help you prepare. Keep an eye out for our webinar and training materials to help ensure a smooth transition to the new Moz Local.

Are any metrics/scores changing?

Some of our reporting metrics will look different in the new Moz Local. We'll be sharing more information on these metrics and how to use them soon, but for now, here’s a quick overview of changes you can expect:

  • Profile Completeness: Listing Score will be replaced by the improved Profile Completeness metric. This new feature will give you a better measurement of how complete your data is, what’s missing from it, and clear prompts to fill in any lacking information.
  • Improved listing status reporting: Partner Accuracy Score will be replaced by improved reporting on listing status with all of our partners, including continuous information about the data they’ve received from us. You’ll be able to access an overview of your distribution network, so that you can see which sites your business is listed on. Plus, you’ll be able to go straight to the live listing with a single click.
  • Visibility Index: Though they have similar names, Visibility Score is being replaced by something slightly different with the new and improved Visibility Index, which notates how the data you’ve provided us about a location matches or mismatches your information on your live listings.
  • New ways to measure and act on listing reach: Reach Score will be leaving us in favor of even more relevant measurement via the Visibility Index and Profile Completeness metrics. The new Moz Local will include more actionable information to ensure your listings are accurate and complete.

Other FAQs

You'll likely have questions if you’re a current Moz Local customer or are considering becoming one. Please check out our resource center for further details, and feel free to leave us a question down in the comments — we'll be on point to respond to any wonderings or concerns you might have!

Head to the FAQs

Where is Moz heading with this?

As a veteran local SEO, I’m finding the developments taking place with our software particularly exciting because, like you, I see how local search and local search marketing have matured over the past decade.

I’ve closely watched the best minds in our industry moving toward a holistic vision of how authenticity, customer engagement, data, analysis, and other factors underpin local business success. And we’ve all witnessed Google’s increasingly sophisticated presentation of local business information evolve and grow. It’s been quite a ride!

At every level of local commerce, owners and marketers deserve tools that bring order out of what can seem like chaos. We believe you deserve software that yields strategy. As our CEO, Sarah Bird, recently said of Moz,

“We are big believers in the power of local SEO.”

So the secret is finally out, and you can see where Moz is heading with the local side of our product lineup. It’s our serious plan to devote everything we’ve got into putting the power of local SEO into your hands.


Sign up for The Moz Top 10, a semimonthly mailer updating you on the top ten hottest pieces of SEO news, tips, and rad links uncovered by the Moz team. Think of it as your exclusive digest of stuff you don't have time to hunt down but want to read!



from The Moz Blog http://bit.ly/2Jmt5oy
via IFTTT

How Often Does Google Update Its Algorithm?

Monday, 13 May 2019

Change Color of SVG on Hover

There are a lot of different ways to use SVG. Depending on which way, the tactic for recoloring that SVG in different states or conditions — :hover, :active, :focus, class name change, etc. — is different.

Let's look at the ways.

Inline SVG

Inline SVG is my favorite way to use SVG anyway, in part because of how easy it is to access and style the SVG.

See the Pen
bJXNyy
by Chris Coyier (@chriscoyier)
on CodePen.

If you're used to working with icon fonts, one thing you might enjoy about them is how easy it is to change the color. You're largely limited to a single color with icon fonts in a way that SVG isn't, but still, it is appealingly easy to change that single color with color. Using inline SVG allows you to set the fill, which cascades to all the elements within the SVG, or you can fill each element separately if needed.

SVG Symbol / Use

There is such thing as an SVG sprite, which is a group of SVGs turned into <symbol> elements such that any given icon can be referenced easily with a <use> element.

See the Pen
Use SVG Hovers
by Chris Coyier (@chriscoyier)
on CodePen.

You can still set the fill color from outside CSS rather easily this way, but there are caveats.

  • The internal SVG elements (like the <path>) can have no fill themselves. This allows the fill set from the parent SVG to cascade into the Shadow DOM created by <use>. As soon as you have something like <path fill="blue" ... /> in the <symbol>, you've lost outside CSS control.
  • Likewise, the fill of individual elements cannot be controlled within the SVG like you could with inline SVG. This means you're pretty firmly in single-color territory. That covers most use cases anyway, but still, a limitation nonetheless.

SVG background images

SVG can be set as a background image just like PNG, JPG, or whatever other graphics format. At this point, you've sort of given up on being able to change the fill. One possibility, which I'd argue isn't a particularly good one, is to have two versions of every icon, in the respective colors, and swap between them:

See the Pen
Background SVG Hovers
by Chris Coyier (@chriscoyier)
on CodePen.

I don't blame you if you'd rather not swap sources, so another possibility is to get gnarly with filters.

See the Pen
Background SVG Hovers with Filters
by Chris Coyier (@chriscoyier)
on CodePen.

Trying to finagle the right filters to get the color right is tricky stuff. Fortunately, Barrett Sonntag made a tool to calculate the filters for you! Turning black to red ends up a whacky combination like this: invert(27%) sepia(51%) saturate(2878%) hue-rotate(346deg) brightness(104%) contrast(97%);.

SVG also has object, which is kinda neat in that it had a built-in fallback back in the day — although browser support is so good these days, I honestly have never used it. But if you're using it, you would probably have to use this filter technique to swap color on hover.

See the Pen
Background SVG Object Hovers
by Chris Coyier (@chriscoyier)
on CodePen.

Use a mask instead of a background image

This way, the SVG is still in charge of essentially drawing the shape, but the color comes from the background-color (or image! or gradient!) behind it rather than the SVG itself.

See the Pen
Background SVG Hovers with Mask
by Chris Coyier (@chriscoyier)
on CodePen.

SVG background images as data URLs

This doesn't change that much from above, but it does open up one interesting possibility: Using a variable for the internal fills. Here that is with Sass keeping the URLs as variables:

See the Pen
Background SVG Hovers with Data URL variables
by Chris Coyier (@chriscoyier)
on CodePen.

You can also do this with native CSS custom properties!

The post Change Color of SVG on Hover appeared first on CSS-Tricks.



from CSS-Tricks http://bit.ly/30ihc8o
via IFTTT

SVG Properties and CSS

SEO & Progressive Web Apps: Looking to the Future

Thursday, 9 May 2019

CSS-Tricks Chronicle XXXV

An SEO’s Guide to Writing Structured Data (JSON-LD)

The Thinking Behind Simplifying Event Handlers

A responsive grid layout with no media queries

The Impact of Team Collaboration and Communication on Projects

TRCREATIVE is proud to celebrate 10 years in business

Time flies when you’re busy working on creative design, web design and build and digital marketing. One minute, baby steps as the business gets off the ground and then, before you know it, double figures. We’re delighted to hit this special milestone. Before we get the office party started, let’s look back at how and where we came about and also how far we’ve come.

TRCREATIVE founders Lynsey Edwards and Mike Lawson met and bonded over fonts and layouts when working for other agencies. Both shared a passion to set up a design studio, therefore it made perfect sense to form a creative partnership and start their own business.

Established in 2009, TRCREATIVE was born in a barn in Brereton, Cheshire. It was an old barn with no heating and no bean-to-cup coffee machine but it was a great creative space. It was soon a hub of activity and innovative design, starting with leaflets, logos and websites.

Richard Rankin, the founder of Team Rewards, a firm specialising in employee benefits, is also part of TRCREATIVE’s success story. “Richard owned the barn and put a roof over our heads 10 years ago,” says Lynsey. “His business experience and mentoring have also been invaluable.”

Indeed, the “TR” in TRCREATIVE, is a nod to Team Rewards and Richard is still very much involved; the two businesses work closely together today. There’s also been a major office upgrade – home is now a characterful building in the heart of the Cheshire countryside.

The location might have changed but the passion to create, develop and produce exceptional work for clients is as focused as it ever was, if not more. Our clients include TV celebrities Clare Balding and Charlotte Hawkins; Pets at Home; Clive Christian; Westbridge Furniture; Cheshire West & Chester Council and NHS; and a number of new brands, too.

Over the 10 years, here are 10 things we’ve learned and celebrated along the way:

  1. Learn and grow: we started out designing logos and websites. Now our services include branding, latest website design and development and a specialised digital marketing team.
  2. Embrace change: the digital world never sleeps. We’re constantly adapting to change to get best results in social media advertising, Google Ads, PPC, SEO and conversion rate optimization.
  3. Nurture team spirit: a business that pulls together, stays together. Creatives and developers within the team share ideas and inspire each other. We even take it in turns to make the tea.
  4. Keep it real: we’re a friendly team of people who communicate directly with clients. There’s no middle-man or creative hierarchy. Our streamlined operation produces better-targeted work.
  5. Make it memorable: whether it is branding, creative design or advertising campaigns, whatever we do, we make sure it is highly effective, beautiful and memorable.
  6. Never stop learning: we continue to explore, question and learn. Achieving Google Partner status or attending seminars, we do whatever it takes in order to offer the best services.
  7. Bring on the challenge: we get excited about exploring new ways to keep our clients happy, including developing unique solutions and building websites to exact requirements.
  8. Build relationships: we take pride in creating a close working relationship with our clients. So much so, we retain 93% of our clients, year on year.
  9. Love what you do: Passion keeps us fresh and motivated. We’re obsessed about creating, building and problem-solving. This is evident in our design, storytelling and communication.
  10. Look to the future: we are growing our digital marking department. We’ve also launched our own premium template websites to help smaller businesses have a better presence online.

From a big dream and an old barn to a thriving team in a vibrant design studio, we’ve come a long way. Technology and contemporary culture have a big impact on our industry, so we’re always thinking “what next?” But first, the office party. It is time to celebrate 10 years of TRCREATIVE. Did someone say cake?

 



from TRCREATIVE http://bit.ly/2vOIXaE
via IFTTT

Wednesday, 8 May 2019

MozCon 2019: Acceptance. Education. Donuts

Posted by PJ_Howland

We’re digital marketers; we make our living in a constantly changing (and consistently misunderstood) industry. It’s easy to feel like even those who are closest to us don’t really get what we do. Take me, for example, I once mentioned algorithms to my grandmother, and ever since then, she’s been absolutely (and adamantly) sure that I work with clocks. Did she think I said analog?

But despite the dynamic nature of marketing, Moz has always been a solid rock at the center of the storm. It’s been here since the beginning, a place where all the marketing nerds and SEO geeks could hang our hats and feel understood.

And MozCon feels like the culmination of that culture of acceptance.

MozCon: Helping you build your best self

As I’ve chatted with the good folks at Moz about this year’s MozCon, it’s clear to me that they pay attention to data. Why do I say that? Because they’re doubling down on making this year their most actionable year ever. As a past attendee, I can say that hearing that MozCon’s biggest focus is a dedication to actionable tactics gets me excited.

The creative media surrounding MozCon have an under-the-sea theme going on. These nautical nods are setting us all up for the deep dive into digital marketing we’re sure to see this year. Since there’s a good chance that most of us marketers never made it to prom (just me? Okay then...), it’s kind of fun to get a second chance to experience oceanic decor in a congregate environment (What, you’ve never dreamed about being Marty McFly at his parent’s Enchantment Under the Sea dance? Was I the only one?)

The point is that the upcoming MozCon is poised to do what it does so well: Offer a delightful mix of predictability and variety, presented in a way that’s designed to improve us without reforming us. New players will share the stage with established thought leaders and strategists. Innovation will go hand in hand with cherished tradition.

After looking at the initial agenda, here are a few of the front runner speakers and sessions I’m excited for in particular.

Casie Gillette — Thanks for the Memories: Creating Content People Remember

Digital marketers like data, right?

[Cue nodding heads and incoherent mumblings]

While I certainly love data, I also struggle with data. Sometimes I rely on the data so much that I become hesitant to take risks. And if there’s one thing our industry as a whole can improve on, it’s taking more risk.

Casie is taking to the stage with a mission to teach us how to make content memorable. With the promise that MozCon 2019 will be more tactical and strategic than ever before, I am earnestly giddy (feel free to picture that emotion however the mood takes you) to hear about what I can do to take a step back from the data, and instead put it on the line for something my audience will never forget.

Shannon McGuirk: How to Supercharge Link Building with a Digital PR Newsroom

Link-building, anyone? Yeah, it’s still a thing. After all, if you link-build it, they will come. Shannon promises to teach us how to set up a “digital PR room.” AKA, a link-earning machine! It sounds like she’s pulling back the entire curtain and will be showing us some concrete link-building tactics. I know how many hours go into earning a single link, so I am eagerly awaiting a process that scales.

Ross Simmonds — Keyword's Aren't Enough: How to Uncover Content Ideas Worth Chasing

Like many SEOs, I’m a firm believer in the power of valuable content. So when I hear about a session titled, “Keyword's Aren't Enough: How to Uncover Content Ideas Worth Chasing,” it’s eye-catching. Maybe more than eye-catching, it’s paradigm challenging. I love keywords, LOVE’em! Content marketing without keywords makes me a little uneasy. Let’s just say keywords are at the center of most of my strategy for content marketing decisions. I’m glad I have time to prepare my mind for what mad brilliance Ross will be sharing this year at MozCon.

Heather Physioc — Mastering Branded Search

Before I even jump into Heather’s digital game, let’s start with her taste in music. Her walk-on music was strong last year — real strong.

This year Heather is going to be chatting us up on branded search. At one glance I’m like, “Okay, color me intrigued…” Branded search seems so surface-level, but knowing Heather, it will be an engaging presentation replete with answers to (what I thought were) unanswerable questions about branded search. Heather has a background in working with enterprise brands, so for me, the opportunity to learn how to leverage big brand names for unique perspectives on what many may think is a pretty straightforward subject, is one I don’t dare pass up. Very excited for what’s sure to be a wild ride.

Britney Muller — Topic TBD, but looking forward to it nonetheless 

I’ve never left a conference with more notes from a single session that I have from Britney’s MozCon address in 2017. I recall her sharing her trepidation about being the lead SEO for Moz. A quick project Britney took on was gutting some old and thin pages on Moz.com — about 70,000 community pages if my notes from the event are correct. But shortly, Moz.com saw a modest organic traffic bump. Britney is fearless as an SEO, and there’s something beyond the sheer value of case studies here. As SEOs, we too should be fearless in our work. I’m looking forward to Britney sharing data, insights, and her gutsy spirit with all of us.

Moz with Benefits...

Speakers and sessions are cool and all, but can I just say that all the little extras MozCon has to offer are amazing.

Networking is something that every conference touts. And sure we all like networking, cause that’s what we have to say right? What’s the phrase? “If you’re not networking, you’re not working”? At MozCon, networking is not a chore; it’s easy and enjoyable. Even productive. From an agency perspective, it’s a cool place outside the office to connect with clients too.

And how have I gotten this far and not mentioned the food at MozCon? The meals are excellent, but can I say a word about the snacks? Moz does not skimp when it comes to eats. Sure, I talked about some cool speakers and topics above, but you know what’s actually stolen my heart at MozCon? Top Pot donuts. I may be that guy that leaves a session 5 minutes early just to get a head start on these donuts. Does that mean I might miss out on valuable insights or strategies? Absolutely it does, and I don’t care. My goal has always been to get a couple of donuts down the hatch before I run into someone I know. That way, when they see me with a donut in each hand, they think that’s all I’ve had.

“Just two donuts this time, PJ?”

“Yeah, haha, just two…” Suckers.

Donuts aside, Moz cares immensely about their community and has done everything possible to make this the best year yet. So come as you are, and leave as you were… only better. The Moz culture of acceptance and education stands to deliver a MozCon experience that will keep you going throughout the year.

I can’t wait to take a deep dive into the sea of SEO with all of my fellow marketing geeks. And if you want to chat, I’ll be the guy hovering around the donut table.

Well, what did I miss?

For all the long-time MozCon attendees out there, what are you excited for?

Which speakers and sessions are you looking forward to most?

Do you have any favorite moments from years past?

Where are you grabbing dinner in the city?


Sign up for The Moz Top 10, a semimonthly mailer updating you on the top ten hottest pieces of SEO news, tips, and rad links uncovered by the Moz team. Think of it as your exclusive digest of stuff you don't have time to hunt down but want to read!



from The Moz Blog http://bit.ly/2vOL91y
via IFTTT

A Few Functional Uses for Intersection Observer to Know When an Element is in View

Getting To Know The MutationObserver API

MutationObserver watches the DOM, specifically the places you tell it to, like:

document.querySelector('#watch-this');

...and it can tell you (trigger a callback) when stuff happens — like when a child is added, removed, changed, or a number of other things.

I used it just the other day to watch the <head> of a Pen and detected newly-injected processed Sass code, so you could use CodePen to see Sass and CSS side by side:

See the Pen
Sassmeister clone
by Chris Coyier (@chriscoyier)
on CodePen.

Direct Link to ArticlePermalink

The post Getting To Know The MutationObserver API appeared first on CSS-Tricks.



from CSS-Tricks http://bit.ly/2voTcCe
via IFTTT

Tuesday, 7 May 2019

I Want To Rank Beyond My Location: A Guide to How This Works

Why, How, and When to Use Semantic HTML and ARIA

The Place of UX

Every time "UX" comes out of my mouth or is typed by my fingers, I think, "did I just use that term correctly?" It feels like such a big and loaded term these days, that perhaps the way I use it only contributes to the confusion. Ryan Singer frames that problem well:

Debates continue to rage about the role of UX designers, user research, and how far knowledge about the user should permeate the organization. On one extreme, UX is seen as a specialized pocket of knowledge that informs the definition of projects and sets requirements. On the other, UX is something for which the entire organization should somehow feel responsible.

It can feel so big, like UX is literally the only thing that matters in an entire project. It can also feel so small, like 2px of extra padding on a specific dropdown will make the options easier to tap.

Direct Link to ArticlePermalink

The post The Place of UX appeared first on CSS-Tricks.



from CSS-Tricks http://bit.ly/2Zy8yC8
via IFTTT

Can You Reverse A 301 Redirect?

Monday, 6 May 2019

Creating Quality Content in 2019 (For Search Engines and People)

A CSS Golfing Exercise

A Conspiracy to Kill IE6

Chris Zacharias published a few notes about why the team at YouTube added a banner that asked users to switch from IE6 to a more modern browser back in 2009:

The bittersweet consequence of YouTube’s incredible growth is that so many stories will be lost underneath all of the layers of new paint. This is why I wanted to tell the story of how, ten years ago, a small team of web developers conspired to kill IE6 from inside YouTube and got away with it.

I do not recall the exact triggering event that led to our web development team laying out plans to kill IE6 over lunch in the YouTube cafeteria. Perhaps it was the time I pushed out a CSS stylesheet that included an attribute selector on a semi-supported HTML element. Any reasonable web developer would expect this to be ignored by browsers not up to the task. This was not the case with older flavors of IE. Under very specific conditions, an attribute selector on an unsupported HTML element in IE would create an internal recursion that would at best, cause the browser to crash and at worst, trigger a blue screen of death.

There are a lot of interesting things to consider here. IE6 was notoriously difficult for developers to work with and would cause teams to spend a great deal of time fixing game-breaking bugs for what often represented a mere slither of their overall site traffic. However, it’s important to note that as soon as you make a call like this, where do you stop? It suddenly becomes easier to make a Chrome-only website, to ignore basic accessibility principles, to ignore semantic markup, and to make a website optimized for yourself. That leads us to more sticky topics, such as browser diversity and proprietary resources that seem at odds with an open, inclusive web.

I’m reminded here of Jeremy Keith’s book, Resilient Web Design, where he writes:

If a website is built using progressive enhancement then it’s okay if a particular feature isn’t supported or fails to load: Ajax, geolocation, whatever. As long as the core functionality is still available, web designers don’t need to bend over backwards trying to crowbar support for newer features into older browsers.

And Jeremy quotes Mat Marquis, who happened to work on the responsive redesign of The Boston Globe, where he argued that:

Lots of cool features on the Boston Globe don’t work when JS breaks; “reading the news” is not one of them.

Maybe there’s a middle ground here; maybe there’s not. But I find Mat and Jeremy’s approach to be more inspiring and kinder to the overall health of the web.

Direct Link to ArticlePermalink

The post A Conspiracy to Kill IE6 appeared first on CSS-Tricks.



from CSS-Tricks http://bit.ly/2ZNhiV4
via IFTTT

Friday, 3 May 2019

Making the Move from jQuery to Vue

As someone who has used jQuery for many. years and has recently become a Vue convert, I thought it would be an interesting topic to discuss the migration process of working with one to the other.

Before I begin though, I want to ensure one thing is crystal clear. I am not, in any way whatsoever, telling anyone to stop using jQuery. That's been pretty fashionable lately, and heck, I wrote up something similar myself a few year ago ("How I'm (Not) Using jQuery"). If you get things done with jQuery and your end users are successfully using your site, then more power to you. Keep using what works for you.

This guide is more for people who may be coming from years of jQuery experience and want to see how things can be done with Vue. With that in mind, I'm going to focus on what I consider "core" jQuery use cases. I won't cover every single possible feature but instead take a "I often did [X] with jQuery" approach that may be more relatable to people considering learning Vue. (As an aside, also note that how I write my examples are simply one way of performing a task. Both jQuery and Vue give provide multiple ways to accomplish the same goal and that's a great thing!)

With that in mind, let's consider some high level things we might turn to jQuery for:

  • Finding something in the DOM (with the idea of doing something with it later)
  • Changing something in the DOM (e.g. the text of a paragraph or the class of a button)
  • Reading and setting form values
  • Form validation (which is really just a combination of the items above)
  • Ajax calls and handling the results
  • Event handling (e.g. on button click, do something)
  • Measuring or changing the styles of an element

There's more to jQuery, of course, but these uses (at least in my opinion), cover the most common use cases. Also note there's a lot of cross pollination in the list above. So, should we start with a simple one-to-one comparison of each? Nope, not so fast. Let's begin by covering the major difference in Vue applications.

Defining where Vue "works"

When we drop jQuery onto a page, we are basically adding a Swiss Army knife to JavaScript code to handle common web development tasks. We can do any of the uses case we’re going to cover in whatever order we see fit. For example, a client may ask for form validation today, then in a month or so, ask to do an Ajax-based search form in the header of the site.

Vue has one significant difference in that respect. When starting a with Vue project, we start by defining an "area" in the DOM we want it to focus on. So, let’s consider a simple prototype web page:

<body>

  <header>
    Fancy header stuff here
  </header>

  <div id="sidebar">
    Some sidebar doohicky here
  </div>

  <main>
    <p>
      Main site content here, super important stuff...
    </p>
    <div id="loginForm">
      A login form of course
    </div>
  </main>

</body>

In a typical jQuery application, we may write code to work with the header, sidebar, and login form or something. No big whoop:

$(document).ready(function() {

  $('header') // something...

  $('#sidebar') // something...

  $('#loginForm') // something... 

});

In a Vue application, we first specify what are we're working with. Imagine our client first asked to add validation to the loginForm element. Our Vue code would specify that:

new Vue({
  el: '#loginForm',
  // Code here...
});

This means that we’d typically end up adding a second Vue application if the client later decides to have us add something to the sidebar:

new Vue({
  el:'#loginForm',
  // Code here...
});

new Vue({
  el:'#sideBar',
  // Code here...
});

Is that a bad thing? Absolutely not. Right away, we get the benefit of encapsulation. If we accidentally use a variable with a generic name (we've all done that), we don't have to worry about conflicts with other parts of your code. Later on when the client adds yet another request, having our unique, logical sets of Vue code separated out like this gives us some great peace of mind that things won't step on each other.

So, yes, a good thing. But it absolutely caused me to stop a bit when I first began using Vue. Now, onto our use cases.

Finding Stuff in the DOM

Another aspect you'll find interesting, or scary, is how to "find stuff in the DOM." That's a bit vague, but let's consider a firm example. We have a button, and when it’s clicked, we something to happen. Here's an abbreviated example of how this could look:

<button id="myButton">Click Me!</button>
<!-- More stuff... -->
<script>
$(document).ready(function() {

  $('#myButton').click(function() {
    alert(1);
  });

});
</script>

Now let's compare that to how it can be done with Vue:

<div id="app">
  <button v-on:click="doSomething">Click Me!</button>
</div>

<script>
const app = new Vue({
  el:'#app',
  methods: {
    doSomething: function() {
      alert(1);
    }
  }
});
</script>

The Vue application is a bit more verbose, but note how the markup has a direct connection between the action ("click") and the function that will be called. Vue's code doesn't have a tie back to the DOM (outside of the el portion where we define where it needs to work). This was easily one of the things that sold me on Vue the most — it feels easier to tell what is going on. Also, I didn't need to worry so much about the ID value and selectors. If I change the class or ID of the button, I don't need to go back into my code and worry about updating selectors.

Let's consider another example: finding and changing text in the DOM. Imagine that button, on click, now changes the text of another part of the DOM.

<button id="myButton">Click Me!</button>
<span id="result"></span>

<!-- More stuff... -->

<script>
$(document).ready(function() {

  $('#myButton').click(function() {
    $('#result').text('You clicked me, thanks!');
  });

});
</script>

I've added a new span and now, when the button is clicked, we use another selector to find it and use a jQuery utility method to change the text inside it. Now consider the Vue version:

<div id="app">
  <button v-on:click="doSomething">Click Me!</button>
  <!-- On click, change text in this span -->
  <span></span>
</div>

<script>
const app = new Vue({
  el: '#app',
  data: {
    resultText: ''
  },
  methods: {
    doSomething: function() {
      this.resultText = 'You clicked me, thanks!';
    }
  }
});
</script>

In this example, we're using Vue's template language (the highlighted line) to specify that we want to render a variable inside the span, which is resultText in this case. Now, when the button is clicked, we change that value and the span's inner text will change automatically.

As an aside, Vue supports a shorthand for the v-on attribute, so the button in the example could have been written with @click="doSomething" instead.

Reading and writing form variables

Working with forms is probably one of the most common — and useful — things that we can do with JavaScript. Even before JavaScript, most of my early "web development" was writing Perl script to handle form submissions. As the primary way of accepting user input, forms have always been critical to the web and that's probably going to stay the same for quite some time. Let's consider a simple jQuery example of reading a few form fields and setting another:

<form>
  <input type="number" id="first"> + 
  <input type="number" id="second"> =
  <input type="number" id="sum"> 
  <button id="sumButton">Sum</button>
</form>

<script>
$(document).ready(function() {
  let $first = $('#first');
  let $second = $('#second');
  let $sum = $('#sum');
  let $button = $('#sumButton');
  
  $button.on('click', function(e) {
    e.preventDefault();
    let total = parseInt($first.val(),10) + parseInt($second.val(),10);
    $sum.val(total);
  });
});
</script>

This code demonstrates how jQuery can both read and write via the val() method. We end up getting four items from the DOM (all three form fields and the button) and use simple math to generate a result. Now consider the Vue version:

<form id="myForm">
  <input type="number" v-model.number="first"> + 
  <input type="number" v-model.number="second"> =
  <input type="number" v-model="sum"> 
  <button @click.prevent="doSum">Sum</button>
</form>

<script>
new Vue({
  el: '#myForm',
  data: {
    first: 0,
    second: 0,
    sum: 0
  },
  methods: {
    doSum: function() {
      this.sum = this.first + this.second;
    }
  }
})
</script>

This introduces some interesting Vue shortcuts. First, v-model is how Vue creates two way data binding between values in the DOM and in JavaScript. The data block variables will automatically sync up with the form fields. Change the data, and the form updates. Change the form, and the data updates. The .number is a flag to Vue to treat the inherit string values of form fields as numbers. If we leave this off and do addition as we are, we'll see string additions and not arithmetic. I've been working with JavaScript for nearly a century and still screw this up.

Another neat "trick" is @click.prevent. First, @click defines a click handler for the button, then the .prevent portion blocks the browser’s default behavior of submitting the form (the equivalent of event.preventDefault()).

The final bit is the addition of the doSum method that's bound to that button. Note that it simply works with the data variables (which Vue makes available in the this scope).

While this is mostly my personal feeling here, I really love the lack of query selectors in the script when writing in Vue and how the HTML is much more clear about what it's doing.

Finally, we could even get rid of the button completely:

<form id="myForm">
  <input type="number" v-model.number="first"> + 
  <input type="number" v-model.number="second"> =
  <input type="number" v-model="sum"> 
</form>

<script>
new Vue({
  el: '#myForm',
  data: {
    first: 0,
    second: 0
  },
  computed: {
    sum: function() {
      return this.first + this.second;
    }
  }
})
</script>

One of the cooler features of Vue is computed properties. They are virtual values that recognize when their derived values are updated. In the code above, as soon as any of the two form fields change, the sum will update. This works outside of form fields too. We could render the sum like so:

The total is .

Working with Ajax

It’s commendable how easy jQuery has made it to use Ajax. In fact, I can say I've done Ajax "the vanilla" way probably a grand total of one time. (If you're curious, you can take a look at the spec for XMLHttpRequest and probably be happy you avoided it yourself.) jQuery's simple $.get(...) method worked in a large number of cases and when it’s needed for something more complex, $.ajax() made it easy as well. Another thing jQuery did well is the way it handles JSONP requests. While mostly unnecessary now with CORS, JSONP was a way to handle making requests to APIs on different domains.

So, what does Vue do for you to make Ajax easier? Nothing!

OK, that sounds scary but it really isn't. There are many options out there for working with HTTP requests, and Vue.js took a more agnostic route of letting us, the developers, decide how we want to handle it. So yes, that does mean a bit more work, but we've got some great options.

The first one to consider is Axios, this is a Promise-based library that is very popular among the Vue community. Here's a simple example of it in action (taken from their README file):

axios.get('/user?ID=12345')
  .then(function (response) {
    // handle success
    console.log(response);
  })
  .catch(function (error) {
    // handle error
    console.log(error);
  })
  .then(function () {
    // always executed
  });

Axios supports POST requests, of course, and lets us specify headers among many other options.

While Axios is very popular among Vue developers, it isn't something that really clicked with me. (At least not yet.) Instead, I've been much more a fan of Fetch. Fetch is not an external library but is a web standard way of performing HTTP requests. Fetch has very good support at roughly 90% of browsers, though that means it isn't completely safe to use, but we can always use a polyfill we need to.

While it's totally out of the scope of what we're discussing here, Kingsley Silas has written an excellent guide on using both Axios and Fetch with React.

Like Axios, Fetch is Promise-based and has a friendly API:

fetch('http://example.com/movies.json')
  .then(function(response) {
    return response.json();
  })
  .then(function(myJson) {
    console.log(JSON.stringify(myJson));
  });

Both Axios and Fetch cover all types of HTTP requests, so either will fit an any number of needs. Let's look at a simple comparison. Here's a simple jQuery demo that makes use of the Star Wars API.

<h1>Star Wars Films</h1>
<ul id="films">
</ul>

<script>
$(document).ready(function() {
  $.get('https://swapi.co/api/films', function(res) {
    let list = '';
    res.results.forEach(function(r) {
      list += `<li>${r.title}</li>`;
    });
    $('#films').html(list);
  });
});
</script>

In the sample above, I use $.get to hit the API and return a list of films. Then I generate a list of titles as li tag elements with that data and insert it all into a ul block.

Now, let's consider an example of this using Vue:

<div id="app">
  <h1>Star Wars Films</h1>
  <ul>
    <li v-for="film in films"></li>
  </ul>  
</div>

<script>
const app = new Vue({
  el: '#app',
  data: {
    films: []
  }, 
  created() { 
    fetch('https://swapi.co/api/films')
    .then(res => res.json())
    .then(res => {
      this.films = res.results;  
    });
  }
})
</script>

Probably the best part of this is the use of the v-for template. Notice how Vue isn't concerned with the layout (well, at least the JavaScript). The data is fetched from the API. It’s assigned a variable. The layout handles displaying it. I've always hated having HTML in my JavaScript and, while solutions exist for that with jQuery, having it baked into Vue makes it a natural fit.

A full (if somewhat trivial) example

To bring it home a bit, let's consider a more real world example. Our client has asked us to build a fancy Ajax-enabled front-end search interface to a product API. The feature list includes:

  • Support filtering by name and product category
  • Form validation such that we must supply a search term or a category
  • While the API is being hit, show a message to the user and disable the submit button
  • When done, handle reporting that no products were shown or list the matches

Let's begin with the jQuery version. First, the HTML:

<form>
  <p>
    <label for="search">Search</label>
    <input type="search" id="search">
  </p>
  <p>
    <label for="category">Category</label>
    <select id="category">
      <option></option>
      <option>Food</option>
      <option>Games</option>
    </select>
  </p> 
  <button id="searchBtn">Search</button>
</form>

<div id="status"></div>
<div id="results"></div>

There's a form with our two filters and two divs. One's used as a temporary status when searching or reporting errors and one is used to render results. Now, check out the code.

const productAPI = 'https://wt-c2bde7d7dfc8623f121b0eb5a7102930-0.sandbox.auth0-extend.com/productSearch';

$(document).ready(() => {
  let $search = $('#search');
  let $category = $('#category');
  let $searchBtn = $('#searchBtn');
  let $status = $('#status');
  let $results = $('#results');
  
  $searchBtn.on('click', e => {
    e.preventDefault();
    
    // First clear previous stuff
    $status.html('');
    $results.html('');

    // OK, now validate form
    let term = $search.val();
    let category = $category.val();
    if(term === '' && category === '') {
      $status.html('You must enter a term or select a category.');
      return false;
    }

    $searchBtn.attr('disabled','disabled');
    $status.html('Searching - please stand by...');
    
    $.post(productAPI, { name:term, category:category }, body => {
      $searchBtn.removeAttr('disabled');
      $status.html('');

      if(body.results.length === 0) {
        $results.html('<p>Sorry, no results!</p>');
        return;
      }
      
      let result = '<ul>';
      body.results.forEach(r => {
        result += `<li>${r.name}</li>`
      });
      result += '</ul>';
      $results.html(result);
    });
    
  });
});

The code begins by creating a set of variables for each of the DOM items we want to work with — the form fields, button, and divs. The core of the logic is within the click handler for the button. We do validation, and if everything is OK, do a POST request against the API. When it returns, we either render the results or show a message if nothing was matched.

You can work with a complete version of this demo using the CodePen below.

See the Pen
jQuery Full
by Raymond Camden (@cfjedimaster)
on CodePen.

Now let's consider the Vue version. Again, let's start with the layout:

<div id="app">
  <form>
    <p>
      <label for="search">Search</label>
      <input type="search" v-model="search">
    </p>
    <p>
      <label for="category">Category</label>
      <select v-model="category">
        <option></option>
        <option>Food</option>
        <option>Games</option>
      </select>
    </p>
    <button @click.prevent="searchProducts" :disabled="searchBtnDisabled">Search</button>
  </form>

    <div v-html="status"></div>
    <ul v-if="results">
      <li v-for="result in results"></li>
    </ul>
</div>

From the top, the changes include:

  • Wrapping the layout in a div that can be used to let Vue know where to work.
  • Using v-model for the form fields to make it easy to work with the data.
  • Using @click.prevent to handle doing the main search operation.
  • Using :disabled to bind whether or not the button is disabled to a value in the Vue application (we'll see that in action in a moment).
  • The status value is a bit different than earlier examples. While jQuery has a specific method to set text in a DOM item and another for HTML, Vue requires using v-html when assigning HTML to a value that's going to be rendered. If we tried to do with HTML, the tags would be escaped.
  • Finally, using v-if to conditionally render a list of results along with v-for to handle the iteration.

Now let's look at the code.

const productAPI = 'https://wt-c2bde7d7dfc8623f121b0eb5a7102930-0.sandbox.auth0-extend.com/productSearch';

const app = new Vue({
  el: '#app',
  data: {
    search: '',
    category: '',
    status: '',
    results: null,
    searchBtnDisabled: false
  },
  methods: {
    searchProducts:function() {
      this.results = null;
      this.status = '';
      
      if(this.search === '' && this.category === '') {
        this.status = 'You must enter a term or select a category.';
        return;
      }

      this.searchBtnDisabled = true;
      this.status = 'Searching - please stand by...';
      
      fetch(productAPI, {
        method: 'POST',
        headers: {
          'Content-Type':'application/json'
        },
        body: JSON.stringify({name:this.search,category:this.category})
      }).then(res => res.json())
      .then(res => {
        this.status = '';
        this.searchBtnDisabled = false;
        this.results = res.results;
        if(this.results.length === 0) this.status = '<p>Sorry, no results!</p>';
      });
      
    }
  }
});

The first block worth calling out is the set of data fields. Some map to form fields and others to results, status messages, and the like. The searchProducts method handles much of the same stuff as the jQuery version but, in general, there's much less code directly tied to the DOM. For example, even though we know the results are listed in an unordered list, the code itself doesn't worry about that. It simply assigns the value and the markup handles rendering it. Overall, the JavaScript code is much more concerned about logic in comparison to the jQuery code which "feels" like a much nicer separation of concerns.

As before, I've got a CodePen for you to try this out yourself:

See the Pen
Vue Full
by Raymond Camden (@cfjedimaster)
on CodePen.

Death to jQuery! Long Live Vue!

OK, that's a bit over the top. As I said in the beginning, I absolutely think that you shouldn't change a thing if like working with jQuery and it's working for you.

I can say, however, that Vue feels like a great "next step" for people who are used to working with jQuery. Vue supports complex applications and has a great command line tool for scaffolding and building projects. But for simpler tasks, Vue works as a great "modern jQuery" replacement that has become my tool of choice for development!

For another perspective on using Vue in place of jQuery, check out Sarah Drasner's "Replacing jQuery With Vue.js: No Build Step Necessary" because it includes a handful of other super helpful examples.

The post Making the Move from jQuery to Vue appeared first on CSS-Tricks.



from CSS-Tricks http://bit.ly/2PIyiYd
via IFTTT

Passkeys: What the Heck and Why?

These things called  passkeys  sure are making the rounds these days. They were a main attraction at  W3C TPAC 2022 , gained support in  Saf...