Tag Archives: custom

Thumbnail

Smashing Book 6 Is Here: New Frontiers In Web Design




Smashing Book 6 Is Here: New Frontiers In Web Design

Vitaly Friedman



Imagine you were living in a perfect world. A world where everybody has fast, stable and unthrottled connections, reliable and powerful devices, exquisite screens, and capable, resilient browsers. The screens are diverse in size and pixel density, yet our interfaces adapt to varying conditions swiftly and seamlessly. What a glorious time for all of us — designers, developers, senior Webpack configurators and everybody in-between — to be alive, wouldn’t you agree?

Well, we all know that the reality is slightly more nuanced and complicated than that. That’s why we created Smashing Book 6, our shiny new book that explores uncharted territories and seeks to discover new reliable front-end and UX techniques. And now, after 10 months of work, the book is ready, and it’s shipping. Jump to table of contents and get the book right away.


Smashing Book 6: New Frontiers in Web Design

eBook

$19Get the eBook

PDF, ePUB, Kindle. Free for Smashing Members.

Hardcover

$39Get the Print (incl. eBook)

Printed, quality hardcover. Free airmail shipping worldwide.

About The Book

Finding your way through front-end and UX these days is challenging and time-consuming. But frankly, we all just don’t have time to afford betting on a wrong strategy. Smashing Book 6 sheds some light on new challenges and opportunities, but also uncovers new traps and pitfalls in this brave new front-end world of ours.

Our books aren’t concerned with short-living trends, and our new book isn’t an exception. Smashing Book 6 is focused on real challenges and real front-end solutions in the real world: from accessible apps to performance to CSS Grid Layout to advanced service workers to responsive art direction. No chit-chat or theory. Things that worked, in actual projects. Jump to table of contents.


Smashing Book 6


The Smashing Book 6, with 536 pages on real-life challenges and opportunities on the web. Photo by our dear friend Marc Thiele. (Large preview)

In the book, Laura and Marcy explore strategies for maintainable design systems and accessible single-page apps with React, Angular etc. Mike, Rachel and Lyza share insights on using CSS Custom Properties and CSS Grid in production today. Yoav and Lyza take a dive deep into performance patterns and service workers in times of Progressive Web Apps and HTTP/2.


Inner design of the Smashing Book 6.


Inner design of the Smashing Book 6. Designed by one-and-only Chiara Aliotta. Large view.

Ada, Adrian and Greg explore how to design for watches and new form factors, as well as AR/VR/XR, chatbots and conversational UIs. The last chapter will guide you through some practical strategies to break out of generic, predictable, and soulless interfaces — with dozens of examples of responsive art direction. But most importantly: it’s the book dedicated to headaches and solutions in the fragile, inconsistent, fragmented and wonderfully diverse web we find ourselves in today.

Table Of Contents

Want to peek inside? Download a free PDF sample (PDF, ca. 21 MB) with a chapter on bringing personality back to the web by yours truly. Overall, the book contains 10 chapters:

  1. Making Design Systems Work In Real-Life
    by Laura Elizabeth
  2. Accessibility In Times Of Single-Page Applications
    by Marcy Sutton
  3. Production-Ready CSS Grid Layouts
    by Rachel Andrew
  4. Strategic Guide To CSS Custom Properties
    by Mike Riethmueller
  5. Building An Advanced Service Worker
    by Lyza Gardner
  6. Loading Assets On The Web
    by Yoav Weiss
  7. Conversation Interface Design Patterns
    by Adrian Zumbrunnen
  8. Building Chatbots And Designing For Watches
    by Greg Nudelman
  9. Cross Reality And The Web (AR/VR)
    by Ada Rose Cannon
  10. Bringing Personality Back To The Web (free PDF sample, 21MB)
    by Vitaly Friedman
Laura Elizabeth
Marcy Sutton
Rachel Andrew
Mike Riethmuller
Lyza Danger Gardner
Yoav Weiss
Adrian Zumbrunnen
Greg Nudelman
Ada Rose Edwards
Vitaly Friedman
From left to right: Laura Elizabeth, Marcy Sutton, Rachel Andrew, Mike Riethmuller, Lyza D. Gardner, Yoav Weiss, Adrian Zumbrunnen, Greg Nudelman, Ada Rose Edwards, and yours truly.

  • 536 pages. Quality hardcover + eBook (PDF, ePUB, Kindle).
    Published late September 2018.
  • Written by and for designers and front-end developers.
    Designed with love from Italy by Chiara Aliotta.
  • Free airmail worldwide shipping from Germany.
    Check delivery times for your country.
  • If you are a Smashing Member, don’t forget to apply your Membership discount.
  • Good enough? Get the book right away.

Smashing Book 6: Covers of Chapter 1 and Chapter 10

eBook

$19Get the eBook

PDF, ePUB, Kindle. Free for Smashing Members.

Hardcover

$39Get the Print (incl. eBook)

Printed, quality hardcover. Free airmail shipping worldwide.

About The Designer

Chiara AliottaThe cover was designed with love from Italy by one-and-only Chiara Aliotta. She founded the design studio Until Sunday and has directed the overall artistic look and feel of different tech companies and not-for-profit organizations around the world. We’re very happy that she gave Smashing Book 6 that special, magical touch.

Behind The Scenes Of The Design Process

We asked Chiara to share some insights into the design process of the cover and the interior design and she was very kind to share some thoughts with us:

“It all started with a few exchanges of emails and a Skype meeting where Vitaly shared his idea of the book and the general content. I had a lot of freedom, which is always exciting and scary at the same time. The only bond (if we want to call it like this) was that the “S” of Smashing Magazine should be the main protagonist of the cover, reinvented and creatively presented as per all the other previous Smashing Books.




The illustration on paper. The cover sketched on paper. Also check the close-up photo. (Large preview)

I worked around few keywords that Vitaly was using to describe the book during our meetings and then developed an idea around classical novels of adventure where the main hero leaves home, encounters great hazards, risks, and then eventually returns wiser and/or richer than he/she was before.

So I thought of Smashing Book 6 as a way to propose this basic and mythic structure under a new light: through the articles of this book, the modern web designer will be experiencing true and deep adventures.

I imagined the “S” as an engine, the starting point of this experience, from where different worlds were creating and expanding. So the cover was the map of these uncharted territories that the book explores.

Every element on the cover has a particular meaning that constructs the S
Every element on the cover has a particular meaning that constructs the S. Large view.

I am a person who judges books by its cover and having read some of the chapters and knowing some of the well-established writers, I wanted to honour its content and their work by creating a gorgeous cover and chapter illustrations.

For this edition of Smashing Book, I imagined a textile cover in deep blue, where the graphic is printed using a very old technique, the hot gold foil stamping.

Together with Markus, part of the Smashing Magazine team and responsible for the publishing of all the Smashing Books, we worked closely to choose the final details of the binding and guarantee an elegant and sophisticated result, adding a touch of glam to the book.




Smashing Book 6 comes wrapped with a little bookmark. Photo by our dear friend Marc Thiele.

As a final touch, I added a paper wrap around the book that invites the readers to “unlock their adventure”, suggesting a physical action: the reader needs to tear off the paper before starting reading the book.
And for this only version, we introduced a customise Smashing Magazine bookmark, also in printed on gold paper. Few more reasons to prefer the paperback version over the digital ones!”

A huge round of applause to Chiara for her wonderful work and sharing the thoughts with us. We were remarkably happy with everything from design to content. But what did readers think? Well, I’m glad that you asked!




Sketches for chapter illustrations. (Large preview)

Feedback and Testimonials

We’ve sent the shiny new book to over 200 people to peek through and read, and we were able to gather some first insights. We’d love to hear your thoughts, too!

“Web design is getting pretty darned complicated. The new book from SmashingMag aims to bring the learning curve down to an accessible level.”

Aaron Walter, InVision

“Just got the new Smashing Book 6 by SmashingMag. What a blast! From CSS Grid Layout, CSS Custom Properties and service workers all the way to the HTTP/2 and conversational interfaces and many more. I recommend it to all the people who build interfaces.”

Mihael Tomić, Osijek, Croatia

“The books published by SmashingMag and team are getting better each time. I was thrilled to be able to preview it… EVERY CHAPTER IS GOOD! Having focused on a11y for much of my career, Marcy Sutton’s chapter is a personal favorite.”

Stephen Hay, Amsterdam, Netherlands


Smashing Book 6, a thank-you page


The Smashing Book 6, with 536 pages on real-life challenges and solutions for the web. Huge thank-you note to the smashing community for supporting the book and out little magazine all these years. (Large preview)

Thank You For Your Support!

We’re very honored and proud to have worked with wonderful people from the industry who shared what they’ve learned in their work. We kindly thank all the hard-working people involved in making this book reality. We kindly thank you for your ongoing support of the book and our little magazine as well. It would be wonderful if you could mention the book by any chance as well in your social circles and perhaps link to this very post.

We’ve also prepared a little media kit .zip with a few photos and illustrations that you could use if you wanted to — just sayin’!

We can’t wait to hear your thoughts about the book! Happy reading, and we hope that you’ll find the book as useful as we do. Just have a cup of coffee (or tea) ready before you start reading, of course, stay smashing and… meow!


Smashing Book 6: New Frontiers in Web Design

eBook

$19Get the eBook

PDF, ePUB, Kindle. Free for Smashing Members.

Hardcover

$39Get the Print (incl. eBook)

Printed, quality hardcover. Free airmail shipping worldwide.

Smashing Editorial
(ra, il)


Continued here:  

Smashing Book 6 Is Here: New Frontiers In Web Design

Thumbnail

WordPress Notifications Made Easy




WordPress Notifications Made Easy

Jakub Mikita



WordPress doesn’t offer any kind of notification system. All you can use is the wp_mail() function, but all of the settings have to be hardcoded, or else you have to create a separate settings screen to allow the user tweak the options. It takes many hours to write a system that is reliable, configurable and easy to use. But not anymore. I’ll show you how to create your own notification system within minutes with the free Notification plugin. By notification, I mean any kind of notification. Most of the time, it will be email, but with the plugin we’ll be using, you can also send webhooks and other kinds of notifications.

While creating a project for one of my clients, I encountered this problem I’ve described. The requirement was to have multiple custom email alerts with configurable content. Instead of hardcoding each and every alert, I decided to build a system. I wanted it to be very flexible, and the aim was to be able to code new scenarios as quickly as possible.

The code I wrote was the start of a great development journey. It turned out that the system I created was flexible enough that it could work as a separate package. This is how the Notification plugin was born.

Suppose you want to send an email about a user profile being updated by one of your website’s members. WordPress doesn’t provide that functionality, but with the Notification plugin, you can create such an email in minutes. Or suppose you want to synchronize your WooCommerce products with third-party software by sending a webhook to a separate URL every time a new product is published. That’s easy to do with the plugin, too.

Lessons Learned While Developing WordPress Plugins

Good plugin development and support lead to more downloads. More downloads mean more money and a better reputation. Learn how you can develop good-quality products with seven golden rules. Read more →

In this article, you’ll learn how to integrate the plugin in your own application and how to create an advanced WordPress notification system more quickly and easily than ever.

In this article, we’ll cover:

  1. how to install the plugin,
  2. the idea behind the plugin and its architecture,
  3. creating a custom scenario for notifications,
  4. creating the action (step 1 of the process),
  5. creating the trigger (step 2 of the process),
  6. creating the custom notification type,
  7. how to enable white-label mode and bundle the plugin in your package.

Installing The Plugin

To create your own scenarios, you are going to need the Notification plugin. Just install it from the WordPress.org repository in your WordPress dashboard, or download it from the GitHub repository.

Large preview

Later in the article, you’ll learn how to hide this plugin from your clients and make it work as an integrated part of your plugin or theme.

The Idea Of The Plugin

Before going into your code editor, you’ll need to know what the plugin’s architecture looks like. The plugin contains many various components, but its core is really a few abstract classes.

The main components are:

  • The notification
    This could be an email, webhook, push notification or SMS.
  • The trigger
    This is what sends the notification. It’s effectively the WordPress action.
  • The merge tag
    This is a small portion of the dynamic content, like post_title.

To give you a better idea of how it all plays together, you can watch this short video:

The core of the Notification plugin is really just an API. All of the default triggers, like Post published and User registered are things built on top of that API.

Because the plugin was created for developers, adding your own triggers is very easy. All that’s required is a WordPress action, which is just a single line of code and a class declaration.

Custom Scenario

Let’s devise a simple scenario. We’ll add a text area and button to the bottom of each post, allowing bugs in the article to be reported. Then, we’ll trigger the notification upon submission of the form.

This scenario was covered in another article, “Submitting Forms Without Reloading the Page: AJAX Implementation in WordPress”.

For simplicity, let’s make it a static form, but there’s no problem putting the action in an AJAX handler, instead of in the wp_mail() function.

Let’s create the form.

The Form

add_filter( 'the_content', 'report_a_bug_form' );
function report_a_bug_form( $content ) 

    // Display the form only on posts.
    if ( ! is_single() ) 
        return $content;
    

    // Add the form to the bottom of the content.
    $content .= '<form action="' . admin_url( 'admin-post.php' ) . '" method="POST">
        <input type="hidden" name="post_id" value="' . get_ID() . '">
        <input type="hidden" name="action" value="report_a_bug">
        <textarea name="message" placeholder="' . __( 'Describe what's wrong...', 'reportabug' ) . '"></textarea>
        <button>' . __( 'Report a bug', 'reportabug' ) . '</button>
    </div>';

    return $content;

}

Please note that many components are missing, like WordPress nonces, error-handling and display of the action’s result, but these are not the subject of this article. To better understand how to handle these actions, please read the article mentioned above.

Preparing The Action

To trigger the notification, we are going to need just a single action. This doesn’t have to be a custom action like the one below. You can use any of the actions already registered in WordPress core or another plugin.

The Form Handler And Action

add_action( 'admin_post_report_a_bug', 'report_a_bug_handler' );
add_action( 'admin_post_nopriv_report_a_bug', 'report_a_bug_handler' );
function report_a_bug_handler() 

    do_action( 'report_a_bug', $_POST['post_id'], $_POST['message'] );

    // Redirect back to the article.
    wp_safe_redirect( get_permalink( $_POST['post_id'] ) );
    exit;


You can read more on how to use the admin-post.php file in the WordPress Codex.

This is all we need to create a custom, configurable notification. Let’s create the trigger.

Registering The Custom Trigger

The trigger is just a simple class that extends the abstract trigger. The abstract class does all of the work for you. It puts the trigger in the list, and it handles the notifications and merge tags.

Let’s start with the trigger declaration.

Minimal Trigger Definition

class ReportBug extends BracketSpaceNotificationAbstractsTrigger 

    public function __construct() 

        // Add slug and the title.
        parent::__construct(
            'reportabug',
            __( 'Bug report sent', 'reportabug' )
        );

        // Hook to the action.
        $this->add_action( 'report_a_bug', 10, 2 );

    

    public function merge_tags() {}

}

All you need to do is call the parent constructor and pass the trigger slug and nice name.

Then, we can hook into our custom action. The add_action method is very similar to the add_action() function; so, the second parameter is the priority, and the last one is the number of arguments. Only the callback parameter is missing because the abstract class does that for us.

Having the class, we can register it as our new trigger.

register_trigger( new ReportBug() );

This is now a fully working trigger. You can select it from the list when composing a new notification.




(Large preview)

Although the trigger is working and we can already send the notification we want, it’s not very useful. We don’t have any way to show the recipient which post has a bug and what the message is.

This would be the time, then, to register some merge tags and set up the trigger context with the action parameters we have: the post ID and the message.

To do this, we can add another method to the trigger class. This is the action callback, where we can catch the action arguments.

Handling Action Arguments

public function action( $post_ID, $message ) 

    // If the message is empty, don't send any notifications.
    if ( empty( $message ) ) 
        return false;
    

    // Set the trigger properties.
    $this->post    = get_post( $post_ID );
    $this->message = $message;

}

Note the return false; statement. If you return false from this method, the trigger will be stopped, and no notification will be sent. In our case, we don’t want a notification to be submitted with an empty message. In the real world, you’d want to validate that before the form is sent.

Then, we just set the trigger class’ properties, the complete post object and the message. Now, we can use them to add some merge tags to our trigger. We can just fill the content of the merge_tags method we declared earlier.

Defining Merge Tags

public function merge_tags() 

    $this->add_merge_tag( new BracketSpaceNotificationDefaultsMergeTagUrlTag( array(
        'slug'        => 'post_url',
        'name'        => __( 'Post URL', 'reportabug' ),
        'resolver'    => function( $trigger ) 
            return get_permalink( $trigger->post->ID );
        ,
    ) ) );

    $this->add_merge_tag( new BracketSpaceNotificationDefaultsMergeTagStringTag( array(
        'slug'        => 'post_title',
        'name'        => __( 'Post title', 'reportabug' ),
        'resolver'    => function( $trigger ) 
            return $trigger->post->post_title;
        ,
    ) ) );

    $this->add_merge_tag( new BracketSpaceNotificationDefaultsMergeTagHtmlTag( array(
        'slug'        => 'message',
        'name'        => __( 'Message', 'reportabug' ),
        'resolver'    => function( $trigger ) 
            return nl2br( $trigger->message );
        ,
    ) ) );

    $this->add_merge_tag( new BracketSpaceNotificationDefaultsMergeTagEmailTag( array(
        'slug'        => 'post_author_email',
        'name'        => __( 'Post author email', 'reportabug' ),
        'resolver'    => function( $trigger ) 
            $author = get_userdata( $trigger->post->post_author );
            return $author->user_email;
        ,
    ) ) );

}

This will add four merge tags, all ready to use while a notification is being composed.

The merge tag is an instance of a special class. You can see that there are many types of these tags, and we are using them depending on the value that is returned from the resolver. You can see all merge tags in the GitHub repository.

All merge tags are added via the add_merge_tag method, and they require the config array with three keys:

  • slug
    The static value that will be used in the notification (i.e. post_url).
  • name
    The translated label for the merge tag.
  • resolver
    The function that replaces the merge tag with the actual value.

The resolver doesn’t have to be the closure, as in our case, but using it is convenient. You can pass a function name as a string or an array if this is a method in another class.

In the resolver function, only one argument is available: the trigger class instance. Thus, we can access the properties we just set in the action method and return the value we need.

And that’s all! The merge tags are not available to use with our trigger, and we can set up as many notifications of the bug report as we want.




(Large preview)

Creating The Custom Notification Type

The Notification plugin offers not only custom triggers, but also custom notification types. The plugin ships with two types, email and webhook, but it has a simple API to register your own notifications.

It works very similarly to the custom trigger: You also need a class and a call to one simple function to register it.

I’m showing only an example; the implementation will vary according to the system you wish to integrate. You might need to include a third-party library and call its API or operate in WordPress’ file system, but the guide below will set you up with the basic process.

Let’s start with a class declaration:

class CustomNotification extends BracketSpaceNotificationAbstractsNotification 

    public function __construct() 

        // Add slug and the title.
        parent::__construct( 
            'custom_notification',
            __( 'Custom Notification', 'textdomain' )
        );

    

    public function form_fields() {}

    public function send( BracketSpaceNotificationInterfacesTriggerable $trigger ) {}

}

In the constructor, you must call the parent’s class constructor and pass the slug and nice name of the notification.

The form_fields method is used to create a configuration form for notifications. (For example, the email notification would have a subject, body, etc.)

The send method is called by the trigger, and it’s where you can call the third-party API that you wish to integrate with.

Next, you have to register it with the register_notification function.

register_trigger( new CustomNotification() );

The Notification Form

There might be a case in which you have a notification with no configuration fields. That’s fine, but most likely you’ll want to give the WordPress administrator a way to configure the notification content with the merge tags.

That’s why we’ll register two fields, the title and the message, in the form_fields method. It looks like this:

public function form_fields() 

    $this->add_form_field( new BracketSpaceNotificationDefaultsFieldInputField( array(
        'label'       => __( 'Title', 'textdomain' ),
        'name'        => 'title',
        'resolvable'  => true,
        'description' => __( 'You can use merge tags', 'textdomain' ),
    ) ) );

    $this->add_form_field( new BracketSpaceNotificationDefaultsFieldTextareaField( array(
        'label'       => __( 'Message', 'textdomain' ),
        'name'        => 'message',
        'resolvable'  => true,
        'description' => __( 'You can use merge tags', 'textdomain' ),
    ) ) );


As you can see, each field is an object and is registered with the add_form_field method. For the list of all available field types, please visit the GitHub repository.

Each field has the translatable label, the unique name and a set of other properties. You can define whether the field should be resolved with the merge tags with the resolvable key. This means that when someone uses the post_title merge tag in this field, it will be changed with the post’s actual title. You can also provide the description field for a better user experience.

At this point, your custom notification type can be used in the plugin’s interface with any available trigger type.




(Large preview)

Sending The Custom Notification

In order to make it really work, we have to use the send method in our notification class declaration. This is the place where you can write an API call or use WordPress’ file system or any WordPress API, and do whatever you like with the notification data.

This is how you can access it:

public function send( BracketSpaceNotificationInterfacesTriggerable $trigger ) 

    $title   = $this->data['title'];
    $message = $this->data['message'];

    // @todo Write the integration here.


At this point, all of the fields are resolved with the merge tags, which means the variables are ready to be shipped.

That gives you endless possibilities to integrate WordPress with any service, whether it’s your local SMS provider, another WordPress installation or any external API you wish to communicate with.

White Labeling And Bundling The Plugin

It’s not ideal to create a dependency of a plugin that can be easily deactivated and uninstalled. If you are building a system that really requires the Notification plugin to be always available, you can bundle the plugin in your own code.

If you’ve used the Advanced Custom Fields plugin before, then you are probably familiar with the bundling procedure. Just copy the plugin’s files to your plugin or theme, and invoke the plugin manually.

The Notification plugin works very similarly, but invoking the plugin is much simpler than with Advanced Custom Fields.

Just copy the plugin’s files, and require one file to make it work.

require_once( 'path/to/plugin/notification/load.php' );

The plugin will figure out its location and the URLs.

But bundling the plugin might not be enough. Perhaps you need to completely hide that you are using this third-party solution. This is why the Notification plugin comes with a white-label mode, which you can activate at any time.

It also is enabled as a single call to a function:

notification_whitelabel( array(
    // Admin page hook under which the Notifications will be displayed.
    'page_hook'       => 'edit.php?post_type=page',
    // If display extensions page.
    'extensions'      => false,
    // If display settings page.
    'settings'        => false,
    // Limit settings access to user IDs.
    // This works only if settings are enabled.
    'settings_access' => array( 123, 456 ),
) );

By default, calling this function will hide all of the default triggers.

Using both techniques, white labeling and bundling, will completely hide any references to the plugin’s origin, and the solution will behave as a fully integrated part of your system.

Conclusion

The Notification plugin is an all-in-one solution for any custom WordPress notification system. It’s extremely easy to configure, and it works out of the box. All of the triggers that are registered will work with any notification type, and if you have any advanced requirements, you can save some time by using an existing extension.

If you’d like to learn more details and advanced techniques, go to the documentation website.

I’m always open to new ideas, so if you have any, you can reach out to me here in the comments, via the GitHub issues or on Twitter.

Download the plugin from the repository, and give it a try!

Smashing Editorial
(ra, yk, il)


Excerpt from: 

WordPress Notifications Made Easy

Thumbnail

The Holy Grail Of Reusable Components: Custom Elements, Shadow DOM, And NPM




The Holy Grail Of Reusable Components: Custom Elements, Shadow DOM, And NPM

Oliver Williams



For even the simplest of components, the cost in human-labour may have been significant. UX teams do usability testing. An array of stakeholders have to sign off on the design.

Developers conduct AB tests, accessibility audits, unit tests and cross-browser checks. Once you’ve solved a problem, you don’t want to repeat that effort. By building a reusable component library (rather than building everything from scratch), we can continuously utilize past efforts and avoid revisiting already solved design and development challenges.


A screenshot of Google’s material components website – showing various components.


Large preview

Building an arsenal of components is particularly useful for companies such as Google that own a considerable portfolio of websites all sharing a common brand. By codifying their UI into composable widgets, larger companies can both speed up development time and achieve consistency of both visual and user-interaction design across projects. There’s been a rise in interest in style guides and pattern libraries over the last several years. Given multiple developers and designers spread over multiple teams, large companies seek to attain consistency. We can do better than simple color swatches. What we need is easily distributable code.

Sharing And Reusing Code

Manually copy-and-pasting code is effortless. Keeping that code up-to-date, however, is a maintenance nightmare. Many developers, therefore, rely on a package manager to reuse code across projects. Despite its name, the Node Package Manager has become the unrivalled platform for front-end package management. There are currently over 700,000 packages in the NPM registry and billions of packages are downloaded every month. Any folder with a package.json file can be uploaded to NPM as a shareable package. While NPM is primarily associated with JavaScript, a package can include CSS and markup. NPM makes it easy to reuse and, importantly, update code. Rather than needing to amend code in myriad places, you change the code only in the package.

The Markup Problem

Sass and Javascript are easily portable with the use of import statements. Templating languages give HTML the same ability — templates can import other fragments of HTML in the form of partials. You can write the markup for your footer, for example, just once, then include it in other templates. To say there exists a multiplicity of templating languages would be an understatement. Tying yourself to just one severely limits the potential reusability of your code. The alternative is to copy-and-paste markup and to use NPM only for styles and javascript.

This is the approach taken by the Financial Times with their Origami component library. In her talk “Can’t You Just Make It More like Bootstrap?” Alice Bartlett concluded “there is no good way to let people include templates in their projects”. Speaking about his experience of maintaining a component library at Lonely Planet, Ian Feather reiterated the problems with this approach:

“Once they copy that code they are essentially cutting a version which needs to be maintained indefinitely. When they copied the markup for a working component it had an implicit link to a snapshot of the CSS at that point. If you then update the template or refactor the CSS, you need to update all versions of the template scattered around your site.”

A Solution: Web Components

Web components solve this problem by defining markup in JavaScript. The author of a component is free to alter markup, CSS, and Javascript. The consumer of the component can benefit from these upgrades without needing to trawl through a project altering code by hand. Syncing with the latest changes project-wide can be achieved with a terse npm update via terminal. Only the name of the component and its API need to stay consistent.

Installing a web component is as simple as typing npm install component-name into a terminal. The Javascript can be included with an import statement:

<script type="module">
import './node_modules/component-name/index.js';
</script>

Then you can use the component anywhere in your markup. Here is a simple example component that copies text to the clipboard.

See the Pen Simple web component demo by CSS GRID (@cssgrid) on CodePen.

A component-centric approach to front-end development has become ubiquitous, ushered in by Facebook’s React framework. Inevitably, given the pervasiveness of frameworks in modern front-end workflows, a number of companies have built component libraries using their framework of choice. Those components are reusable only within that particular framework.


A component from IBM’s Carbon Design System


A component from IBM’s Carbon Design System. For use in React applications only. Other significant examples of component libraries built in React include Atlaskit from Atlassian and Polaris from Shopify. (Large preview)

It’s rare for a sizeable company to have a uniform front-end and replatorming from one framework to another isn’t uncommon. Frameworks come and go. To enable the maximum amount of potential reuse across projects, we need components that are framework agnostic.


A screenshot from npmjs.com showing components that do that same thing built exclusively for particular javascript frameworks.


Searching for components via npmjs.com reveals a fragmented Javascript ecosystem. (Large preview)


A graph charting the popularity of frameworks over time. Ember, Knockout and Backbone have plunged in popularity, replaced by newer offerings.


The ever-changing popularity of frameworks over time. (Large preview)

“I have built web applications using: Dojo, Mootools, Prototype, jQuery, Backbone, Thorax, and React over the years…I would love to have been able to bring that killer Dojo component that I slaved over with me to my React app of today.”

Dion Almaer, Director of Engineering, Google

When we talk about a web component, we are talking about the combination of a custom element with shadow DOM. Custom Elements and shadow DOM are part of both the W3C DOM specification and the WHATWG DOM Standard — meaning web components are a web standard. Custom elements and shadow DOM are finally set to achieve cross-browser support this year. By using a standard part of the native web platform, we ensure that our components can survive the fast-moving cycle of front-end restructuring and architectural rethinks. Web components can be used with any templating language and any front-end framework — they’re truly cross-compatible and interoperable. They can be used everywhere from a WordPress blog to a single page application.


The Custom Elements Everywhere project by Rob Dodson documents the interoperability of web components with various client-side Javascript frameworks.


The Custom Elements Everywhere project by Rob Dodson documents the interoperability of web components with various client-side Javascript frameworks. React, the outlier here, will hopefully resolve these issues with React 17. (Large preview)

Making A Web Component

Defining A Custom Element

It’s always been possible to make up tag-names and have their content appear on the page.

<made-up-tag>Hello World!</made-up-tag>

HTML is designed to be fault tolerant. The above will render, even though it’s not a valid HTML element. There’s never been a good reason to do this — deviating from standardized tags has traditionally been a bad practice. By defining a new tag using the custom element API, however, we can augment HTML with reusable elements that have built-in functionality. Creating a custom element is much like creating a component in React — but here were extending HTMLElement.

class ExpandableBox extends HTMLElement 
      constructor() 
        super()
      
    }

A parameter-less call to super() must be the first statement in the constructor. The constructor should be used to set up initial state and default values and to set up any event listeners. A new custom element needs to be defined with a name for its HTML tag and the elements corresponding class:

customElements.define('expandable-box', ExpandableBox)

It’s a convention to capitalize class names. The syntax of the HTML tag is, however, more than a convention. What if browsers wanted to implement a new HTML element and they wanted to call it expandable-box? To prevent naming collisions, no new standardized HTML tags will include a dash. By contrast, the names of custom elements have to include a dash.

customElements.define('whatever', Whatever) // invalid
customElements.define('what-ever', Whatever) // valid

Custom Element Lifecycle

The API offers four custom element reactions — functions that can be defined within the class that will automatically be called in response to certain events in the lifecycle of a custom element.

connectedCallback is run when the custom element is added to the DOM.

connectedCallback() 
    console.log("custom element is on the page!")

This includes adding an element with Javascript:

document.body.appendChild(document.createElement("expandable-box")) //“custom element is on the page”

as well as simply including the element within the page with a HTML tag:

<expandable-box></expandable-box> // "custom element is on the page"

Any work that involves fetching resources or rendering should be in here.

disconnectedCallback is run when the custom element is removed from the DOM.

disconnectedCallback() 
    console.log("element has been removed")

document.querySelector("expandable-box").remove() //"element has been removed"

adoptedCallback is run when the custom element is adopted into a new document. You probably don’t need to worry about this one too often.

attributeChangedCallback is run when an attribute is added, changed, or removed. It can be used to listen for changes to both standardized native attributes like disabled or src, as well as any custom ones we make up. This is one of the most powerful aspects of custom elements as it enables the creation of a user-friendly API.

Custom Element Attributes

There are a great many HTML attributes. So that the browser doesn’t waste time calling our attributeChangedCallback when any attribute is changed, we need to provide a list of the attribute changes we want to listen for. For this example, we’re only interested in one.

static get observedAttributes() 
            return ['expanded']
        

So now our attributeChangedCallback will only be called when we change the value of the expanded attribute on the custom element, as it’s the only attribute we’ve listed.

HTML attributes can have corresponding values (think href, src, alt, value etc) while others are either true or false (e.g. disabled, selected, required). For an attribute with a corresponding value, we would include the following within the custom element’s class definition.

get yourCustomAttributeName() 
  return this.getAttribute('yourCustomAttributeName');

set yourCustomAttributeName(newValue) 
  this.setAttribute('yourCustomAttributeName', newValue);

For our example element, the attribute will either be true or false, so defining the getter and setter is a little different.

get expanded() 
  return this.hasAttribute('expanded')

        
// the second argument for setAttribute is mandatory, so we’ll use an empty string
set expanded(val) 
  if (val) 
    this.setAttribute('expanded', '');
  
  else 
    this.removeAttribute('expanded')
  
}

Now that the boilerplate has been dealt with, we can make use of attributeChangedCallback.

attributeChangedCallback(name, oldval, newval) 
  console.log(`the $name attribute has changed from $oldval to $newval!!`);
  // do something every time the attribute changes
}

Traditionally, configuring a Javascript component would have involved passing arguments to an init function. By utilising the attributeChangedCallback, its possible to make a custom element that’s configurable just with markup.

Shadow DOM and custom elements can be used separately, and you may find custom elements useful all by themselves. Unlike shadow DOM, they can be polyfilled. However, the two specs work well in conjunction.

Attaching Markup And Styles With Shadow DOM

So far, we’ve handled the behavior of a custom element. In regard to markup and styles, however, our custom element is equivalent to an empty unstyled <span>. To encapsulate HTML and CSS as part of the component, we need to attach a shadow DOM. It’s best to do this within the constructor function.

class FancyComponent extends HTMLElement 
        constructor() 
            super()
            var shadowRoot = this.attachShadow(mode: 'open')
            shadowRoot.innerHTML = `<h2>hello world!</h2>`
            }

Don’t worry about understanding what the mode means — its boilerplate you have to include, but you’ll pretty much always want open. This simple example component will just render the text “hello world”. Like most other HTML elements, a custom element can have children — but not by default. So far the above custom element we’ve defined won’t render any children to the screen. To display any content between the tags, we need to make use of a slot element.

shadowRoot.innerHTML = `
<h2>hello world!</h2>
<slot></slot>
`

We can use a style tag to apply some CSS to the component.

shadowRoot.innerHTML = 
`<style>
p 
color: red;

</style>
<h2>hello world!</h2>
<slot>some default content</slot>`

These styles will only apply to the component, so we are free to make use of element selectors without the styles affecting anything else of the page. This simplifies writing CSS, making naming conventions like BEM unnecessary.

Publishing A Component On NPM

NPM packages are published via the command line. Open a terminal window and move into a directory that you would like to turn into a reusable package. Then type the following commands into the terminal:

  1. If your project doesn’t already have a package.json, npm init will walk you through generating one.
  2. npm adduser links your machine to your NPM account. If you don’t have a preexisting account, it will create a new one for you.
  3. npm publish

NPM packages are published via the command line


Large preview

If all’s gone well, you now have a component in the NPM registry, ready to be installed and used in your own projects — and shared with the world.


An example of a component in the NPM registry, ready to be installed and used in your own projects.


Large preview

The web components API isn’t perfect. Custom elements are currently unable to include data in form submissions. The progressive enhancement story isn’t great. Dealing with accessibility isn’t as easy as it should be.

Although originally announced in 2011, browser support still isn’t universal. Firefox support is due later this year. Nevertheless, some high-profile websites (like Youtube) are already making use of them. Despite their current shortcomings, for universally shareable components they’re the singular option and in the future we can expect exciting additions to what they have to offer.

Smashing Editorial
(il, ra, yk)


See the original article here:

The Holy Grail Of Reusable Components: Custom Elements, Shadow DOM, And NPM

Customizing Admin Columns In WordPress

(This is a sponsored article.) If you manage a WordPress website, you’ve probably faced a common problem. How do you get insight into all of your content at a glance? WordPress’ admin area does not show you much about your pages, posts, users and comments. That can make it hard to find the right page, to check if all associated fields are properly filled, or simply to get a general sense of your website’s content.

See original: 

Customizing Admin Columns In WordPress

Tracking Internal Marketing Campaigns With Google Analytics

Editor’s Note: This article is targeted at readers experienced in using Google Analytics. If you’re new to Analytics, the following guide might be challenging.
Many websites use internal advertising in the form of banners or personalized product recommendations to bring additional products and services to the attention of visitors and to increase conversions and leads.
Example: Some internal advertising on smashingmagazine.com (View large version) Naturally, the performance and effectiveness of internal marketing campaigns should be assessed, too, as this is one of the most powerful instruments for generating more leads, more conversions and more revenue on your website.

Read More:  

Tracking Internal Marketing Campaigns With Google Analytics

Instantly Boost Your Facebook Ad ROI With These 5 Advanced Tactics

At this very moment, there are marketers out there achieving great things with the help of Facebook Advertising. However, there’s a good chance that a lot of these marketers aren’t taking full advantage of what Facebook Advertising actually has to offer. In fact, a lot of them might be able to take their Facebook Ad Campaigns to the next level, by making use of some of Facebook’s ‘Advanced features.’ In this post, we’re going to take a look at what those advanced features are and how you can make use of them. Once you’ve finished reading, you’ll know how to…

The post Instantly Boost Your Facebook Ad ROI With These 5 Advanced Tactics appeared first on The Daily Egg.

Originally from:  

Instantly Boost Your Facebook Ad ROI With These 5 Advanced Tactics

CSS Variables: The Architecture Backbone

When they hit the front-end landscape a few years ago, preprocessors were heralded as the saviour of CSS, bringing modularity, meaning and even a degree of sexiness. Terms like “Sass architecture” became commonplace, ushering in a new generation of CSS developers who occasionally went to excess with their new-found power. The results were marvellous, and sometimes undesirable.
One of the unpleasant side effects was a preprocessor elitism that continues to persist.

See original article:

CSS Variables: The Architecture Backbone

Variables: The Backbone Of CSS Architecture


When they hit the front-end landscape a few years ago, preprocessors were heralded as the saviour of CSS, bringing modularity, meaning and even a degree of sexiness. Terms like “Sass architecture” became commonplace, ushering in a new generation of CSS developers who occasionally went to excess with their new-found power. The results were marvellous, and sometimes undesirable.

Variables: The Backbone Of CSS Architecture

One of the unpleasant side effects was a preprocessor elitism that continues to persist. Neophyte designers who were just getting their hands dirty with CSS were overwhelmed by an influx of must-have tools and confused by the bitter partisan wars in web development forums.

The post Variables: The Backbone Of CSS Architecture appeared first on Smashing Magazine.

Continued here:  

Variables: The Backbone Of CSS Architecture

Extending WordPress With Custom Content Types

WordPress does some pretty amazing things out of the box. It handles content management as well as any other open-source solution out there — and better than many commercial solutions. One of the best attributes of WordPress is its ease of use. It’s easy because there’s not a significant amount of bloat with endless bells and whistles that steepen the learning curve.

On the flip side, some might find WordPress a little… well, light. It does a lot, but not quite enough. If you find yourself hacking WordPress to do the things you wish it would do, then the chances are high that this article is for you.

WordPress can be easily extended to fit the requirements of a custom data architecture. We’re going to explore the process of registering new data types in a fully compliant manner.

If you want to follow along at home, we’ve provided the full source code1 (TXT, 5.0 KB).

Custom Post Types

WordPress gives you a very simple and straightforward way to extend the standard two data types (Posts and Pages) into an endless array for your custom needs. A digital agency or freelancer would need a “Project” post type. A mall would need a “Location” post type.

Quick point. Spinning off custom post types is a great idea for content that is intrinsically different than either Posts or Pages. There could be a case where you would want press releases to live in their own type. But more often than not, the press releases would be a Post and categorized as a press release. Or you may want to create a post type for landing pages. It may very well belong as a custom type, but it likely could also exist as a Page.

For the sake of this article, we’re going to follow a real-world scenario of creating a Project post type to store samples of work. We’ll register the post type, add some meta data to it, include additional information in WordPress’ administration screens, and create custom taxonomies to supplement.

Registering The Post Type

To get started, we’ll need some code to register the post type. We’re going to go with an object-oriented approach because we’ll be spinning off this post type later with some added functionality that would be done much more efficiently with an object model. To start, let’s create the function that registers the post type.

function create_post_type() 
  $labels = array(
    'name'               => 'Projects',
    'singular_name'      => 'Project',
    'menu_name'          => 'Projects',
    'name_admin_bar'     => 'Project',
    'add_new'            => 'Add New',
    'add_new_item'       => 'Add New Project',
    'new_item'           => 'New Project',
    'edit_item'          => 'Edit Project',
    'view_item'          => 'View Project',
    'all_items'          => 'All Projects',
    'search_items'       => 'Search Projects',
    'parent_item_colon'  => 'Parent Project',
    'not_found'          => 'No Projects Found',
    'not_found_in_trash' => 'No Projects Found in Trash'
  );

  $args = array(
    'labels'              => $labels,
    'public'              => true,
    'exclude_from_search' => false,
    'publicly_queryable'  => true,
    'show_ui'             => true,
    'show_in_nav_menus'   => true,
    'show_in_menu'        => true,
    'show_in_admin_bar'   => true,
    'menu_position'       => 5,
    'menu_icon'           => 'dashicons-admin-appearance',
    'capability_type'     => 'post',
    'hierarchical'        => false,
    'supports'            => array( 'title', 'editor', 'author', 'thumbnail', 'excerpt', 'comments' ),
    'has_archive'         => true,
    'rewrite'             => array( 'slug' => 'projects' ),
    'query_var'           => true
  );

  register_post_type( 'sm_project', $args );

Not much mysterious here. We’re calling the create_post_type function, which registers our post type. We’re giving the type some labels for back-end identification and giving it a list of specifications in what it can do. For a full list of reference for each of these variables, take a look at the WordPress Codex2, but we’ll hit on a few key items.

labels

For brevity, we’ve created a labels array and simply passed it to the arguments array. WordPress enables us to identify a slew of labels for singular, plural and other purposes.

public

This setting is a parent of sorts for a few of the other settings that appear later in the list. The default value for the public attribute is false. The value of public is passed to the following other attributes when they are not explicitly defined: exclude_from_search, publicly_queryable, show_in_nav_menus and show_ui.

exclude_from_search

The default setting here is the opposite of the public attribute. If your post type is public, then it will be included in the website’s search results. Note that this has no implication for SEO and only restricts or allows searches based on WordPress’ native search protocol. There’s a chance you would want the post type to be public but not appear in these search results. If that’s the case, set this attribute to true.

publicly_queryable

This attribute is exclusively for front-end queries and has no real back-end implications. The default value is the same as the public attribute. Note that when it’s set to false, you will not be able to view or preview the post type in the front end. For example, if you wanted to create a post type that populates a personnel page with a list of everyone’s name, title and bio but didn’t want them to have their own URL on the website, then you would set publicly_queryable to false.

show_ui

Most of the time, you’ll want to set show_ui to true. The default value pulls from the public attribute but can be overridden. When it’s set to false, then a UI element on WordPress’ administration screen won’t be available to you. A practical reason why you would want this set to false is if you had a post type that merely managed data. For example, you may want an Events post type that has a recurring attribute. When you save an event, new posts of a different type would be created to handle each event occurrence. You would want the UI to show only the primary Events post type and not the event occurrence’s meta data.

show_in_nav_menus

Pretty simple and straightforward. If you don’t want this post type to appear in WordPress’ default menu functionality, set this to false. It takes the value of public as default.

show_in_menu

You can modify the position of the post type in the back end. When set to true, the post type defaults as a top-level menu (on the same hierarchical level as Posts and Pages). If false, it won’t show at all. You can use a string value here to explicitly nest the post type into a top level’s submenu. The type of string you would provide is tools.php, which would place the post type as a nested element under “Tools.” It derives its default value from show_ui. Note that show_ui must be set to true in order for you to be able to control this attribute.

show_in_admin_bar

Pretty self-explanatory. If you want UI elements added to WordPress’ administration bar, set this to true.

menu_position

The default value of null will place the menu (at the top level and if not overridden using show_in_menu) below “Comments” in the back end. You can control this further by specifying an integer value corresponding to WordPress’ default menu placements. A value of 5 will place the post type under “Posts,” 10 under “Media,” 15 under “Links,” and 20 under “Pages.” For a full list of values, check out the WordPress Codex3.

menu_icon

You can pass a URL to this attribute, but you could also simply use the name of an icon from Dashicons for a quick solution. Supplying the attribute dashicons-admin-appearance would give you a paint brush4. A full list of Dashicons is available5 as a handy resource. The default is the thumbtack icon used for Posts.

capability_type

This attribute quickly gets into some advanced user-role segmenting concepts. Essentially, assigning post to this attribute generates a capability structure that exactly mimics how access to Posts works. Using this value, subscribers would not be able to access this post type, whereas Authors, Editors and Administrators would. Using page here would limit access to just Editors and Administrators. You can define a more granular structure using capability_type and capabilities attributes in the arguments list. Note that we did not use the capabilities attribute in this example because we’re not explicitly defining a custom capability structure to be used with this post type. This is an advanced concept and one for a completely different article.

hierarchical

This is basically the difference between a Post and a Page. When set to true, a parent post can be identified on a per-post basis (basically, Pages). When false, it behaves as a Post.

supports

A whole bunch of default functionality is attached to each new post type. This array tells WordPress which one of those to include by default. There may be an instance when you don’t want the editor on your post type. Removing that from the array will remove the editor box on the post’s editing screen. Eligible items for the array include the following:

  • title
  • editor
  • author
  • thumbnail
  • excerpt
  • trackbacks
  • custom-fields
  • comments
  • revisions
  • page-attributes
  • post-formats

has_archive

When this is set to true, WordPress creates a hierarchical structure for the post type. So, accessing /projects/ would give us the standard archive.php view of the data. You can template out a variant of archive.php for this particular archive by creating a new file in your theme system named archive-sm_project.php. You can control the default behavior at a more granular level by spinning it off from your primary archive.php.

rewrite

The rewrite option allows you to form a URL structure for the post type. In this instance, our URL would be http://www.example.com/projects/slug/, where the slug is the portion assigned by each post when it’s created (normally, based on the title of the post). A second variable can be assigned inside the rewrite array. If you add with_front => false (it defaults to true), it will not use the identified front half of the URL, which is set in “Settings” → “Permalinks.” For example, if your default WordPress permalink structure is /blog/%postname%/, then your custom post type would automatically be /blog/projects/%postname%/. That’s not a good outcome, so set with_front to false.

query_var

This attribute controls where you can use a PHP query variable to retrieve the post type. The default is true and renders with the permalink structure (when set). You can use a string instead of a variable and control the key portion of the query variable with the string’s value.

Extending The Post Type With A Taxonomy (Or Two)

Out of the box, WordPress Posts have categories and tags attached to them that enable you to appropriately place content in these buckets. By default, new post types don’t have any taxonomies attached to them. You may not want to categorize or tag your post type, but if you do, you’d need to register some new ones. There are two variants of taxonomies, one that behaves like categories (the checklist to the right of the posts) and one like tags, which have no hierarchical structure. They behave in the back end pretty much in the same way (the only discernable difference being that categories can have children, whereas tags cannot), but how they’re presented on the administration screen varies quite wildly. We’ll register two taxonomies to give us one of each type.

function create_taxonomies() 

  // Add a taxonomy like categories
  $labels = array(
    'name'              => 'Types',
    'singular_name'     => 'Type',
    'search_items'      => 'Search Types',
    'all_items'         => 'All Types',
    'parent_item'       => 'Parent Type',
    'parent_item_colon' => 'Parent Type:',
    'edit_item'         => 'Edit Type',
    'update_item'       => 'Update Type',
    'add_new_item'      => 'Add New Type',
    'new_item_name'     => 'New Type Name',
    'menu_name'         => 'Types',
  );

  $args = array(
    'hierarchical'      => true,
    'labels'            => $labels,
    'show_ui'           => true,
    'show_admin_column' => true,
    'query_var'         => true,
    'rewrite'           => array( 'slug' => 'type' ),
  );

  register_taxonomy('sm_project_type',array('sm_project'),$args);

  // Add a taxonomy like tags
  $labels = array(
    'name'                       => 'Attributes',
    'singular_name'              => 'Attribute',
    'search_items'               => 'Attributes',
    'popular_items'              => 'Popular Attributes',
    'all_items'                  => 'All Attributes',
    'parent_item'                => null,
    'parent_item_colon'          => null,
    'edit_item'                  => 'Edit Attribute',
    'update_item'                => 'Update Attribute',
    'add_new_item'               => 'Add New Attribute',
    'new_item_name'              => 'New Attribute Name',
    'separate_items_with_commas' => 'Separate Attributes with commas',
    'add_or_remove_items'        => 'Add or remove Attributes',
    'choose_from_most_used'      => 'Choose from most used Attributes',
    'not_found'                  => 'No Attributes found',
    'menu_name'                  => 'Attributes',
  );

  $args = array(
    'hierarchical'          => false,
    'labels'                => $labels,
    'show_ui'               => true,
    'show_admin_column'     => true,
    'update_count_callback' => '_update_post_term_count',
    'query_var'             => true,
    'rewrite'               => array( 'slug' => 'attribute' ),
  );

  register_taxonomy('sm_project_attribute','sm_project',$args);

When registering a post type, a new menu will appear in the dashboard.6
After you register the new post type and taxonomies, you’ll be greeted with a handy menu in the back end. (View large version7)

All right, now we have two new taxonomies attached to the new post type. The register_taxonomy function takes three arguments. The first is the taxonomy’s name, the second is an array or string of post types, and the third is the arguments defined above.

A quick note on our prefixing. Our post type and taxonomies are all prefixed with sm_. This is by design. We don’t want future plugins to interrupt our infrastructure, so we simply prefix. The name of the prefix is completely up to you.

So, we’ve got a new post type and two new taxonomies attached to it. This essentially replicates the default Posts behavior of WordPress. This is all good stuff, but let’s dig a little deeper to make it more integrated.

Enhancing The Experience With Meta Data

Creating additional fields available to the author in WordPress’ administration screen can be a bit tricky — but abundantly useful. Where WordPress underperforms its competitors is precisely in this area. There’s no user interface where you can define additional pieces of information on a per-post basis. Make no mistake, WordPress fully supports this behavior, but it’s more of a developer tool than an out-of-the-box tool, which makes sense. One might need an endless number of combinations of additional fields. Even if WordPress provided a slick back-end interface to allow a non-technical user to define these fields, there’s no real seamless way to display that information in the front end without a developer putting their hands on it and making it so.

This is where Advanced Custom Fields8 comes in. ACF is a wonderful plugin that gives developers this interface and a full array of templating functions to pull the data in the front end. This article doesn’t detail how to do that, but ACF gives ample documentation9 to get you started and working in the ACF environment.

A preview of the ACF UI for creating custom metadata.10
ACF makes creating meta data and conditionally attaching to custom post types a snap. (View large version11)

Using ACF, you can define new fields and conditionally attach them to content throughout the website. For example, we could create a timeframe meta field that collects how long a particular project has taken. We could add additional fields for awards won or create fields to represent a list of references for any given project.

Using ACF really opens up the hood for what’s possible in WordPress.

Adding Columns To The Administration Screen

Viewing a list of your posts on the administration screen will give you the checkbox, the title and the date published. When registering taxonomies to the post type, you’ll get an additional column for each additional taxonomy. For the majority of cases, this is sufficient. But there may be an additional case or two where you need to provide a little more information. For example, referencing pieces of meta data in the administration grid might be useful. Maybe you want a quick reference for the timeframe or the awards field we defined above. We’ll need two functions attached to some WordPress hooks.

WordPress will give you a standard UI that will closely mirror the Post UI.12
WordPress gives you a standard administration screen out of the box that closely mirrors the built-in Post post type. (View large version13)

Let’s look at the code:

function columns($columns) 
  unset($columns['date']);
  unset($columns['taxonomy-sm_project_attribute']);
  unset($columns['comments']);
  unset($columns['author']);
  return array_merge(
    $columns,
    array(
      'sm_awards' => 'Awards',
      'sm_timeframe' => 'Timeframe'
    ));

The first line unsets the date column. You can unset any of the default columns that you wish. The second line unsets the custom taxonomy we registered (the tag-like one, not category). This could be useful for keeping the admin screen neat and tidy. As you may have noticed, we also unset the comments and author — information we didn’t think was necessary on the screen.

Then, we’re simply defining the new columns and merging them with the array that was passed in the function. We created two new columns, one for awards and one for timeline. The array keys are completely arbitrary. They could be anything, but we’ll need to reference them again when it comes time to pull data into those columns… which is what we’re going to do next.

function column_data($column,$post_id) 
  switch($column) 
  case 'sm_awards' :
    echo get_post_meta($post_id,'awards',1);
    break;
  case 'sm_timeframe' :
    echo get_post_meta($post_id,'timeframe',1);
    break;

All right, we’ve fetched the meta data and conditionally outputted it based on what column we’re on. This is where we’re referencing the array key from above. So, as long as they’re both the same, we could use any arbitrary string we want. Note that we’re pulling the meta fields over using WordPress’ native get_post_meta function.

Removing a few built-in columns and adding some of our own enhances the UI.14
Removing some built-in columns and adding a few of our own enhances the UI and streamlines the information displayed. (View large version15)

Sorting

Ah, sorting. As you probably know, WordPress sorts Pages by menu order and then alphabetically by title and Posts by date published. Let’s get fancy and sort our new post type by the number of awards won. The use case here is easy to see. You want your most award-winning work at the top of the list at all times. If we use standard WordPress queries, the order we’re about to establish will be honored – universally across the website. We will need a function to join the wp_posts and wp_postmeta tables and another to revise how the data is sorted.

function join($wp_join) 
  global $wpdb;
  if(get_query_var('post_type') == 'sm_project') 
    $wp_join .= " LEFT JOIN (
      SELECT post_id, meta_value as awards
      FROM $wpdb->postmeta
      WHERE meta_key =  'awards' ) AS meta
      ON $wpdb->posts.ID = meta.post_id ";
  
  return ($wp_join);
}

This function does the joining for us. We won’t get into why that select statement works (that’s for another article altogether). Pay attention to the if statement here. We’re determining the post type and then conditionally running the join if it meets the sm_project condition. Absent this if statement, you would be doing this join regardless of type, which is not likely something you want.

There could also be a case where you just want to sort the administration screens and not the front end. Fortunately, we can use WordPress’ built-in conditional statements to do that job. Just wrap your statement with another conditional and check against is_admin.

function set_default_sort($orderby,&$query) 
  global $wpdb;
  if(get_query_var('post_type') == 'sm_project') 
    return "meta.awards DESC";
  
  return $orderby;
}

Once again, we’re verifying our post type and then returning an amended order statement. Now we’re telling WordPress to order by the value from the wp_postmeta table descending. So, we’ll get a list of our awards from the most won per project to the least won per project.

Putting It All Together

None of these functions will do anything until they’re called and attached to WordPress hooks. We’ll do this and keep it neat by creating an object around the post type and using the constructor to attach each function to the appropriate hook. For brevity, we’re not going to repeat the code already referenced above.

class sm_project 

  function __construct() 
    add_action('init',array($this,'create_post_type'));
    add_action('init',array($this,'create_taxonomies'));
    add_action('manage_sm_project_posts_columns',array($this,'columns'),10,2);
    add_action('manage_sm_project_posts_custom_column',array($this,'column_data'),11,2);
    add_filter('posts_join',array($this,'join'),10,1);
    add_filter('posts_orderby',array($this,'set_default_sort'),20,2);
  

  function create_post_type() 
    …
  

  function create_taxonomies() 
    …
  

  function columns($columns) 
    …
  

  function column_data($column,$post_id) 
    …
  

  function join($wp_join) 
    …
  

  function set_default_sort($orderby,&$query) 
    …
  
}

new sm_project();

Voila! Everything has come together quite nicely. In our constructor, we referenced the appropriate actions and filters. We’re performing these functions in a particular order — and this must be followed. The post type has to be created first, the taxonomies attached second, then any sort of custom sorting. Keep that in mind as you’re creating your data type.

Summing Up

Once you get the hang of it and you create a few of these, it’ll start to come naturally. I’ve got a bunch of these clips saved up in my toolbelt. I rarely create these from scratch anymore. Although this article is long and in-depth, it really is about a 10-minute process from concept to conclusion once you fully understand what’s going on.

References

(dp, al)

Footnotes

  1. 1 http://provide.smashingmagazine.com/full-source-code.txt
  2. 2 http://codex.wordpress.org/Function_Reference/register_post_type
  3. 3 http://codex.wordpress.org/Function_Reference/register_post_type
  4. 4 https://developer.wordpress.org/resource/dashicons/#admin-appearance
  5. 5 https://developer.wordpress.org/resource/dashicons/
  6. 6 http://www.smashingmagazine.com/wp-content/uploads/2015/04/wordpress-custom-post-type-menu-large-preview-opt.png
  7. 7 http://www.smashingmagazine.com/wp-content/uploads/2015/04/wordpress-custom-post-type-menu-large-preview-opt.png
  8. 8 http://www.advancedcustomfields.com/
  9. 9 http://www.advancedcustomfields.com/resources/
  10. 10 http://www.smashingmagazine.com/wp-content/uploads/2015/04/acf-ui-large-preview-opt.png
  11. 11 http://www.smashingmagazine.com/wp-content/uploads/2015/04/acf-ui-large-preview-opt.png
  12. 12 http://www.smashingmagazine.com/wp-content/uploads/2015/04/Custom-Post-Type-Administration-Screen-Before-large-preview-opt.png
  13. 13 http://www.smashingmagazine.com/wp-content/uploads/2015/04/Custom-Post-Type-Administration-Screen-Before-large-preview-opt.png
  14. 14 http://www.smashingmagazine.com/wp-content/uploads/2015/04/Custom-Post-Type-Administration-Screen-After-large-preview-opt.png
  15. 15 http://www.smashingmagazine.com/wp-content/uploads/2015/04/Custom-Post-Type-Administration-Screen-After-large-preview-opt.png
  16. 16 http://codex.wordpress.org/Function_Reference/register_post_type
  17. 17 http://codex.wordpress.org/Function_Reference/register_taxonomy
  18. 18 https://codex.wordpress.org/Metadata_API
  19. 19 http://codex.wordpress.org/Function_Reference/get_post_meta
  20. 20 http://www.advancedcustomfields.com/resources/get_fields/
  21. 21 http://codex.wordpress.org/Template_Hierarchy
  22. 22 http://codex.wordpress.org/Plugin_API/Action_Reference
  23. 23 http://codex.wordpress.org/Plugin_API/Filter_Reference

The post Extending WordPress With Custom Content Types appeared first on Smashing Magazine.

From:  

Extending WordPress With Custom Content Types

How To Build A Custom WordPress Archive Page

If I were to ask you what the least used default page type in WordPress is, chances are you’d say the archive template. Or, more likely, you’d probably not even think of the archive template at all — that’s how unpopular it is. The reason is simple. As great as WordPress is, the standard way in which it approaches the archive is far from user-friendly.
Let’s fix that today! Let’s build an archive page for WordPress that’s actually useful.

Jump to original – 

How To Build A Custom WordPress Archive Page