emGee Software Solutions Custom Database Applications

Share this

Web Design

A Sneak-Peek Inside The Southeast Asian Web Community

Smashing Magazine - Thu, 12/28/2017 - 06:56
A few weeks ago, Vitaly Friedman (co-founder of this little magazine) and I had the pleasure to join Mozilla’s Developer Roadshow, traveling through four countries in Southeast Asia in just two weeks. We visited cities that are buzzing with life and met people who share our passion for the web. Our mission: To get up close with the Southeast Asian web community. We wanted to learn how different local communities are compared to Europe and the US.
Categories: Web Design

Standing Out From The Crowd: Improving Your Mobile App With Competitive Analysis

Smashing Magazine - Thu, 12/28/2017 - 02:42
The mobile app industry is arguably one of the most competitive industries in the world. With around 2.8 million apps available for download in the Google Play store and 2.2 million in Apple’s App Store, getting your app seen, let alone downloaded, can be difficult. With such fierce competition, it is important to make your app the best it can be. One of the most productive ways to do this is by conducting a competitive analysis to see where your competitors are at, what is working for them, what isn’t and what you can do better.
Categories: Web Design

Productivity Tips And Tricks: The Community Shares Its Piece Of Advice

Smashing Magazine - Wed, 12/27/2017 - 07:04
Productivity tips always make for a popular topic for an article, as everyone is looking for the silver bullet, that one weird trick that turns you into a productivity machine. However, the tips that work well for one person may not work so well for another. We asked the community on Twitter and Facebook to share their best productivity tips, and in this article I’m going to round these up alongside some things I’ve learned that work well for me.
Categories: Web Design

Components in Vue.js

Tuts+ Code - Web Development - Tue, 12/26/2017 - 04:00
Introduction

Vue.js components are important to understand as you work with Vue.js. In this tutorial we are going to dig into Vue.js components, understanding the basics and applying them to an application. Let's get started.

What Are Components?

Components enable us to break the complexity of an application into tiny chunks. For example, a typical web application will have sections like header, sidebar, content, and footer.

Vue.js allows us to break each of these sections into separate modular code called components. These components can be extended, and then attached to the application you are working on. Components are a great way of reusing your code throughout your application.

Let's say you have a blog application, and you would like to display a list of blog posts. Using a Vue component, you can do:

<blog-post></blog-post>

Vue handles the rest.

Create a simple HTML page that mounts a Vue instance to your DOM element. You will use this to learn about components. Here is what the sample HTML page should look like:

<!DOCTYPE html> <html> <head> <title>VueJs Components</title> </head> <body> <!-- Div where Vue instance will be mounted --> <div id="app"></div> <!-- Vue.js is included in your page via CDN --> <script src="https://unpkg.com/vue"></script> <script> // A new Vue instance is created and mounted to your div element new Vue({ el: '#app', data: { domain: 'Tutsplus' }, template: '<p>Welcome to {{ domain }}</p> }); </script> </body> </html>

In the above, you created a simple Vue instance, with no component factor in the code. Now if you want the welcome message to appear twice, how do you do it? Try getting that to work.

Your guess might be to have the div where the Vue instance is mounted appear twice. That will not work. Try changing it from id to class so you have this:

<!DOCTYPE html> <html> <head> <title>VueJs Components</title> </head> <body> <!-- Div where Vue instance will be mounted --> <div class="app"></div> <div class="app"></div> <!-- Vue.js is included in your page via CDN --> <script src="https://unpkg.com/vue"></script> <script> // A new Vue instance is created and mounted to your div element new Vue({ el: '.app', data: { domain: 'Tutsplus' }, template: '<p>Welcome to {{ domain }}</p> }); </script> </body> </html>

It still will not work!

The only way to get around this is to create a component. How do you create a component?

Components are created using the Vue.component() constructor. This constructor takes two parameters: the name of your component (which can also be called the tag name), and an object containing options for your component.

Let's create a component using what you have above.

Vue.component('welcome-message', { data: function() { return { domain: 'Tutsplus' } }, template: '<p>Welcome to {{ domain }}</p>' })

In the above, the component name is called welcome-message. Your component can have whatever name you choose. Yet it is important that the name does not interfere with any HTML tags, as you will not want to override it.

The options object passed to the constructor contains the data and template. When creating components, your data should be a function, as you can see above. The data being held should then be returned as an object.

In situations where there are no data to pass, you can pass only the template like so:

Vue.component('welcome-message', { template: '<p>Welcome to Tutsplus</p>' })

With that done, you can use your component in your application by calling it like a regular HTML element using the name you passed to the constructor. It is called like this: <welcome-message></welcome-message>.

To output the template more than once, you call the component as many times as you want—as I did below.

<!DOCTYPE html> <html> <head> <title>VueJs Components</title> </head> <body> <!-- Div where Vue instance will be mounted --> <div id="app"> <welcome-message></welcome-message> <welcome-message></welcome-message> <welcome-message></welcome-message> <welcome-message></welcome-message> </div> <!-- Vue.js is included in your page via CDN --> <script src="https://unpkg.com/vue"></script> <script> Vue.component('welcome-message', { data: function() { return { domain: 'Tutsplus' } }, template: '<p>Welcome to {{ domain }}</p>' }) // A new Vue instance is created and mounted to your div element new Vue({ el: '#app' }); </script> </body> </html>

From the above, this will display the welcome message four times.

Store Data in Components

Above I mentioned that data has to be a function, and the information it holds has to be returned as an object. Why is it like that?

When returned data is not an object, the components that make use of that data share the same source: shared data. Thus a change in data for one component affects the other component. This is not the same when the data is returned as an object.

It is important to see how this works practically. First, let's see a situation where data is returned as an object.

<!DOCTYPE html> <html> <head> <title>VueJs Components</title> </head> <body> <!-- Div where Vue instance will be mounted --> <div id="app"> <welcome-message></welcome-message> <welcome-message></welcome-message> </div> <!-- Vue.js is included in your page via CDN --> <script src="https://unpkg.com/vue"></script> <script> var data = { name: 'Henry' } Vue.component('welcome-message', { data: function() { return data }, template: '<p>Hello {{ name }}, welcome to TutsPlus (<button @click="changeName">Change Name</button>)</p>', methods :{ changeName: function() { this.name = 'Mark' } } }) // A new Vue instance is created and mounted to your div element new Vue({ el: '#app' }); </script> </body> </html>

Can you guess what is happening above?

There are two components, and both components share the same data source as the data is not returned as an object. How do you prove I am right? When you view the above page from your browser, you will see that a change in one component results in a change in the data of the other component. How is it supposed to be?

Like this:

<!DOCTYPE html> <html> <head> <title>VueJs Components</title> </head> <body> <!-- Div where Vue instance will be mounted --> <div id="app"> <welcome-message></welcome-message> <welcome-message></welcome-message> </div> <!-- Vue.js is included in your page via CDN --> <script src="https://unpkg.com/vue"></script> <script> Vue.component('welcome-message', { data: function() { return { name: 'Henry' } }, template: '<p>Hello {{ name }}, welcome to TutsPlus (<button @click="changeName">Change Name</button>)</p>', methods :{ changeName: function() { this.name = 'Mark' } } }) // A new Vue instance is created and mounted to your div element new Vue({ el: '#app' }); </script> </body> </html>

Here the data is returned as an object, and a change in one component does not affect the other. The function is executed for the individual component. When building your applications, it is important you do not forget this.

Creating and Using Components

Using the lessons learned thus far, let us implement this in a new Vue.js project started from scratch using vue-cli. If you do not have vue-cli installed on your machine, you can do that by running:

npm install -g vue-cli

Start your new Vue.js project:

vue init webpack vue-component-app

Navigate to your application, install the dependencies, and run your dev server using the commands below.

cd vue-component-app npm install npm run dev

First, you'll rename the HelloWorld component that was created when you initialized your application to Hello.vue. You'll then register this component as a global component to be used in your application.

So your Hello component should look like this.

#src/components/Hello.vue <template> <div class="hello"> <p>Welcome to TutsPlus {{ name }}</p> <hr> <button @click="changeName">Change Display Name</button> </div> </template> <script> export default { name: 'Hello', data () { return { name: 'Henry' } }, methods: { changeName () { this.name = 'Mark' } } } </script> <!-- Add "scoped" attribute to limit CSS to this component only --> <style scoped> h1, h2 { font-weight: normal; } ul { list-style-type: none; padding: 0; } li { display: inline-block; margin: 0 10px; } a { color: #42b983; } </style>

Nothing serious is happening here. You have your welcome text displaying the welcome message and a name which is passed as data. When the button underneath the welcome message gets clicked, the changeName method is called. This changes the name from Henry to Mark.

To use this component globally it has to be registered. Can you guess where that will be done? If you said main.js, you are absolutely correct.

To register a component, you import it and then use the Vue.component() constructor to set it up. Try that on your own.

I bet you got that to work. Here is how things should look in your main.js file.

#src/main.js // The Vue build version to load with the `import` command // (runtime-only or standalone) has been set in webpack.base.conf with an alias. import Vue from 'vue' import App from './App' import Home from './components/Hello' Vue.config.productionTip = false Vue.component('display-name', Home) /* eslint-disable no-new */ new Vue({ el: '#app', template: '<App/>', components: { App } })

Nothing new here except the line that imports your Hello component. The component is then registered using the constructor. Finally, for this part, the component needs to be displayed using the component name you entered. In this case, the component is display-name. This will be done in your App.vue file.

Open up src/App.vue and make it look like this.

#src/App.vue <template> <div id="app"> <display-name/> </div> </template> <script> export default { } </script> <style> #app { font-family: 'Avenir', Helvetica, Arial, sans-serif; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; text-align: center; color: #2c3e50; margin-top: 60px; } </style>

With your server on, point your browser to http://localhost:8080. Click on the button and the name should change.

Let's see how to use a component locally.

Create a file called Detail.vue in your components directory. This component will not do anything special—it will be used in the Hello component.

Make your Detail.vue file look like this.

#src/components/Detail.vue <template> <div class="hello"> <p>This component is imported locally.</p> </div> </template> <script> export default { name: 'Detail' } </script> <!-- Add "scoped" attribute to limit CSS to this component only --> <style scoped> h1, h2 { font-weight: normal; } ul { list-style-type: none; padding: 0; } li { display: inline-block; margin: 0 10px; } a { color: #42b983; } </style>

To use it in the Hello component, you start by importing it, as you did with the Hello component. Next, you register it, but this time you will not make use of the Vue.component() constructor.

You register it using the components object inside your exports. The name of the component which will be used as the element tag has to be passed as a value to the object. With that done, you can now use the element tag to output the component.

To understand all that, here is how the Hello component should look.

#src/components/Hello.vue <template> <div class="hello"> <p>Welcome to TutsPlus {{ name }}</p> <hr> <button @click="changeName">Change Display Name</button> <!-- Detail component is outputted using the name it was registered with --> <Detail/> </div> </template> <script> // Importation of Detail component is done import Detail from './Detail' export default { name: 'HelloWorld', data () { return { name: 'Henry' } }, methods: { changeName () { this.name = 'Mark' } }, /** * Detail component gets registered locally. * This component can only be used inside the Hello component * The value passed is the name of the component */ components: { Detail } } </script> <!-- Add "scoped" attribute to limit CSS to this component only --> <style scoped> h1, h2 { font-weight: normal; } ul { list-style-type: none; padding: 0; } li { display: inline-block; margin: 0 10px; } a { color: #42b983; } </style>

Refresh your page to see the new page.

Scoping Component Styles

Vue.js allows you to give global and local styling for your components. What do I mean? There might be scenarios where you want certain elements in a component to be styled differently from their counterparts in another component. Vue.js has got you covered on that.

A good example is available in the little app you just built. The styles in your App.vue are global; how is that possible? Open your App.vue, and the style section looks like this.

<style> #app { font-family: 'Avenir', Helvetica, Arial, sans-serif; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; text-align: center; color: #2c3e50; margin-top: 60px; } </style>

This is different from that of Detail.vue, which looks like this.

<style scoped> h1, h2 { font-weight: normal; } ul { list-style-type: none; padding: 0; } li { display: inline-block; margin: 0 10px; } a { color: #42b983; } </style>

Adding scoped to the style tag makes all the difference. Try editing one of the component styles by removing scoped, and you will see how that works out.

Conclusion

That was a long one, and I trust you enjoyed it.

Now you know how to work effectively with components. You understand how to construct a component in an existing application. When working with vue-cli, you can also create and use components—locally and globally. When you want to use a particular style for a component, you saw how to do that using scoped.

You can now go on to build a complex Vue.js application that uses components. Understand that Vue.js allows you to reuse code—your headers, footer, login panel, and search bar can be used as components.

Categories: Web Design

10 Best HTML5 Sliders for Images and Text

Tuts+ Code - Web Development - Fri, 12/22/2017 - 04:00

HTML5 enables users to have a better and more consistent web experience across several devices. 

Considering that smart devices of varying screen sizes and resolutions are the number one way that most people now access the web, if you have image-rich content or want to present key text in an interesting and exciting way on your website, then you just can't go wrong by using an HTML5 slider. 

Because there are such a large number of sliders out there to choose from, I've pulled together, just for you, a list of the 10 best HTML5 sliders for images and text available at CodeCanyon.

1. Ultimate 3D Carousel

If you’ve ever seen or used an actual slide carousel, you’ll appreciate the design and aesthetics of the Ultimate 3D Carousel. This carousel slider allows you to display multimedia content with a unique 3D layout that mimics the carousels of film photography days. 

There are a number of effects you can apply to your carousel style if you choose, and if you prefer a more traditional slide effect, you can also opt for that instead of the carousel style.

The carousel supports images, MP4 videos, MP3 audio, Google Maps, and more. It runs on all major browsers and uses a responsive layout with auto-scale function so that it works well on all mobile devices.

2. HTML5 Gallery Slideshow

The HTML5 Gallery Slideshow is an excellent choice for showing off your images and text in a slider format. The slideshow’s main selling point is that it is super easy to use. Just add it wherever you want it to appear on your website, and it will adapt its size to the parent container, i.e. the div or other HTML tag. 

Another great feature is that you can have as many galleries on the same page as you want, each with its unique set of images and settings. 

The plugin is also easily customisable. You can change the colour theme and modify the buttons and other aspects, in order to integrate it seamlessly into your site. The slideshow has been coded and optimised to run seamlessly on mobile devices as well.

3. CCSlider Plugin

The CCSlider Plugin offers users a number of options of slider styles, each of which can be customised in numerous ways. You have the choice of 14 3D transitions and 16 2D transitions in total, all of which can be programmed to play automatically, manually, or both.

Captions can be added to each slide, and they can have animated transitions or none at all. The sliders are fully responsive so they work well on mobile devices and support touch gestures.

4. HTML5 Fullscreen Gallery

The HTML5 Fullscreen Gallery was created specifically for showcasing great photographs. The gallery is super easy to incorporate into your existing website and will maintain the correct aspect ratio of all photographs when resizing the browser window. 

You can add titles and descriptions if you wish, and all colours can be altered via the CSS stylesheet. 

For those who want music with their sliders, this gallery comes with piano music played via the HTML5 audio tag, which falls back to Flash music player for incompatible browsers.

5. CSS3 Cube Slider

If you’re looking for a slider with a bit of a difference, check out the CSS3 Cube Slider. This slider shows off your images in a gorgeous slider form like the other sliders here, but it does so by transforming your photos into a choice of six cool 3D cubes as they transition.

The plugin works best in Chrome, Firefox, and Safari browsers, but if the browser doesn’t support CSS3 then the slider falls back to the standard vertical or horizontal slide transition. The plugin is responsive and will adapt to any screen size for the user’s devices.

6. HTML5 Responsive Slider Gallery

HTML5 Responsive Slider Gallery is a wonderful tool that image-rich site owners will want to get their hands on to show off their images to their best advantage.

You just have to check out the live preview for the HTML5 Responsive Slider Gallery to understand why it’s a bestseller at CodeCanyon. 

The slider gallery will adapt both height and width to any space that you added it to based on the parent container. It uses a graphics processing unit for peak performance on both your desktop and mobile devices, comes in three different styles, supports multiple galleries on the same page, and is highly customisable.

7. HTML5 Canvas Carousel

The HTML5 Canvas Carousel gives you another great option to display your images on your website. This 3D photo gallery offers six different options for presenting your images. 

Features include touch-screen navigation support for mobile, support for PNG, JPEG and GIF image files, ability to set the carousel position, and the possibility of featuring multiple carousels on the same page of your website. 

The carousel is highly customisable, and all options can be modified inside the XML file. It is optimized for both Android and iOS mobile devices, and the download file comes with a comprehensive help file explaining all configuration tags and installation.

8. Ultimate Media Gallery

The Ultimate Media Gallery is unique among the sliders in this list, because it can display not just images but video and audio files from a number of external content sources including YouTube, Vimeo, Google Drive media, Podcast, and SoundCloud.  

This highly customisable gallery is fully responsive and mobile friendly. It takes full advantage of Font Awesome Library icons, and all demo examples are included in the download package for quick and easy setup.

9. HTML5 Canvas Cover Flow

The HTML5 Canvas Cover Flow is a 3D photo gallery that takes its inspiration from the Mac Finder viewer of the same name. The slider has tons of features and allows you to present your images in any way you want: horizontal, vertical, oblique, etc. Alternatively, you can make use of the predefined movements and styles if preferred.

In addition, almost every aspect of the slider including colours and graphic elements can be customised to fit your site, and all the options can be easily modified from the configuration XML file, making maintaining the carousel much easier.

Optimised for mobile devices, it not only runs on them, but acts like a native app where you can touch, drag, and rotate the controls.

10. AZEXO Slider

A modernist take on the slider, AZEXO Slider is ideal for those who have a minimalist aesthetic and are looking for a clean yet elegant way to display their images. 

Text can be added over every image, making the slider ideal for presentations that include quotes or important text. 

The transition sequence can be customised, and the slider is easy to incorporate into your website with the addition of the “azexo-slider” class to DIVs which contain images.

Conclusion

These 10 best HTML5 sliders for images and text are by no means the only ones available at Envato Market. So if you haven’t found anything here that meets your needs, we have plenty of other great options on offer.

And if you want to improve your HTML5 skills, check out our ever so useful free HTML5 tutorials.

Categories: Web Design

Introducing the new Webmaster Video Series

Google Webmaster Central Blog - Thu, 12/21/2017 - 08:35

Google has a broad range of resources to help you better understand your website and improve its performance. This Webmaster Central Blog, the Help Center, the Webmaster forum, and the recently released Search Engine Optimization (SEO) Starter Guide are just a few.

We also have a YouTube channel, for answers to your questions in video format. To help with short & to the point answers to specific questions, we've just launched a new series, which we call SEO Snippets.

In this series of short videos, the Google team will be answering some of the webmaster and SEO questions that we regularly see on the Webmaster Central Help Forum. From 404 errors, how and when crawling works, a site's URL structure, to duplicate content, we'll have something here for you.

Check out the links shared in the videos to get more helpful webmaster information, drop by our help forum and subscribe to our YouTube channel for more tips and insights!


Posted by Aurora Morales, Google Search Outreach
Categories: Web Design

Site Authentication in Node.js: User Signup

Tuts+ Code - Web Development - Thu, 12/21/2017 - 04:00
Introduction

Just as authentication is important in APIs, it is also an important feature in certain web applications—those with pages and secrets that should only be accessible to registered and authenticated users.

In this tutorial, you will build a simple web application while learning how to create user registration.

Application Setup

Create a new directory where you will be working from. For the sake of this tutorial, I called mine site-auth. Initialize npm in the new directory you just created. Here is how to initialize npm.

npm init -y

The -y flag tells npm to use the default options.

Edit the dependencies part of your package.json file to look like what I have in mine.

#package.json { "name": "site-auth", "version": "1.0.0", "description": "", "main": "app.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, "keywords": [], "author": "izuchukwu1", "license": "ISC", "dependencies": { "bcryptjs": "^2.4.3", "body-parser": "^1.17.1", "connect-flash": "^0.1.1", "cookie-parser": "^1.4.3", "express": "^4.15.2", "express-handlebars": "^3.0.0", "express-messages": "^1.0.1", "express-session": "^1.15.2", "joi": "^13.0.1", "mongoose": "^4.11.12", "morgan": "^1.8.1", "passport": "^0.4.0", "passport-local": "^1.0.0" } }

With that done, run the command to install the dependencies.

npm install

Create a file in your working directory called app.js.

Start by requiring the dependencies you installed and the necessary files.

#app.js const express = require('express'); const morgan = require('morgan') const path = require('path'); const cookieParser = require('cookie-parser'); const bodyParser = require('body-parser'); const expressHandlebars = require('express-handlebars'); const flash = require('connect-flash'); const session = require('express-session'); const mongoose = require('mongoose') const passport = require('passport') require('./config/passport')

These dependencies were installed when you ran npm install. To use them in your application, you have to require them and save them in their respective variables.

For this tutorial, you will be using MongoDB as your database. You will need to store user information in the database. To work with MongoDB, you will make use of Mongoose—a MongoDB modelling tool for Node.js. Setting up Mongoose is easy, like this.

#app.js mongoose.Promise = global.Promise mongoose.connect('mongodb://localhost:27017/site-auth')

At this point, let's set up our middleware.

// 1 const app = express() app.use(morgan('dev')) // 2 app.set('views', path.join(__dirname, 'views')) app.engine('handlebars', expressHandlebars({ defaultLayout: 'layout' })) app.set('view engine', 'handlebars') // 3 app.use(bodyParser.json()) app.use(bodyParser.urlencoded({ extended: false })) app.use(cookieParser()) app.use(express.static(path.join(__dirname, 'public'))) app.use(session({ cookie: { maxAge: 60000 }, secret: 'codeworkrsecret', saveUninitialized: false, resave: false })); app.use(passport.initialize()) app.use(passport.session()) // 4 app.use(flash()) app.use((req, res, next) => { res.locals.success_mesages = req.flash('success') res.locals.error_messages = req.flash('error') next() }) // 5 app.use('/', require('./routes/index')) app.use('/users', require('./routes/users')) // 6 // catch 404 and forward to error handler app.use((req, res, next) => { res.render('notFound') }); // 7 app.listen(5000, () => console.log('Server started listening on port 5000!'))
  1. Express is initialized and assigned to app.
  2. Middleware to handle views is set up. For the views, you'll be making use of handlebars.
  3. You set up middleware for bodyparser, cookie, session, and passport. Passport will be used when users want to log in.
  4. At some points, you will be displaying flash messages. Thus you need to set up middleware for that, and also create the type of flash messages you want.
  5. Routes middleware—this will handle any request made to a URL path. The URL paths specified here are for the index and users path.
  6. Middleware to handle 404 errors. This middleware kicks in when a request does not map to any of the middleware created above it.
  7. The server is set to listen at port 5000.
Views Setup

Create a new directory called views. Inside the views directory, create two other directories called layouts and partials. You want to achieve a tree structure like this in your views, so create the necessary files in their respective directories.

├── dashboard.handlebars ├── index.handlebars ├── layouts │   └── layout.handlebars ├── login.handlebars ├── notFound.handlebars ├── partials │   └── navbar.handlebars └── register.handlebars

With that done, time to drop the code.

#dashboard.handlebars <!-- Jumbotron --> <div class="jumbotron"> <h1>User DashBoard</h1> </div>

This is a dashboard that should be visible to only registered users. For this tutorial, it will be your secret page.

Now the index page for the application should look like this.

#index.handlebars <!-- Jumbotron --> <div class="jumbotron"> <h1>Site Authentication!</h1> <p class="lead">Welcome aboard.</p> </div>

The application needs a layout that will be used, and here is that layout you will be using.

#layout/layout.handlebars <!DOCTYPE html> <html> <head> <title>Site Authentication</title> <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous"> <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap-theme.min.css" integrity="sha384-rHyoN1iRsVXV4nD0JutlnGaslCJuC7uwjduW9SVrLvRYooPp2bWYgmgJQIXwl/Sp" crossorigin="anonymous"> <link rel="stylesheet" href="/css/style.css"> </head> <body> {{#if success_messages }} <div class="alert alert-success">{{success_messages}}</div> {{/if}} {{#if error_messages }} <div class="alert alert-danger">{{error_messages}}</div> {{/if}} <div class="container"> {{> navbar}} {{{body}}} </div> <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous"></script> </body> </html>

You'll need a login page for registered users.

#views/login.handlebars <form class="form-signin" action="/users/login" method="POST"> <h2 class="form-signin-heading">Please sign in</h2> <label for="inputEmail" class="sr-only">Email address</label> <input type="email" id="inputEmail" name="email" class="form-control" placeholder="Email address" required autofocus> <label for="inputPassword" class="sr-only">Password</label> <input type="password" id="inputPassword" name="password" class="form-control" placeholder="Password" required> <br/> <button class="btn btn-lg btn-default btn-block" type="submit">Sign in</button> </form>

The notFound.handlebars file will be used as your error page.

#views/notFound.handlebars <!-- Jumbotron --> <div class="jumbotron"> <h1>Error</h1> </div>

Your registration page is supposed to look like this.

<form class="form-signin" action="/users/register" method="POST"> <h2 class="form-signin-heading">Please sign up</h2> <label for="inputEmail" class="sr-only">Email address</label> <input type="email" id="inputEmail" name="email" class="form-control" placeholder="Email address" required autofocus> <label for="inputUsername" class="sr-only">Username</label> <input type="text" id="inputUsername" name="username" class="form-control" placeholder="Username" required> <label for="inputPassword" class="sr-only">Password</label> <input type="password" id="inputPassword" name="password" class="form-control" placeholder="Password" required> <label for="inputConfirmPassword" class="sr-only">Confirm Password</label> <input type="password" id="inputConfirmPassword" name="confirmationPassword" class="form-control" placeholder="Confirm Password" required> <br/> <button class="btn btn-lg btn-default btn-block" type="submit">Sign up</button> </form>

Finally for your views, here's your navigation bar.

#partials/navbar.handlebars <div class="masthead"> <h3 class="text-muted">Site Authentication</h3> <nav> <ul class="nav nav-justified"> <li class="active"><a href="/">Home</a></li> {{#if isAuthenticated}} <li><a href="/users/dashboard">Dashboard</a></li> <li><a href="/users/logout">Logout</a></li> {{else}} <li><a href="/users/register">Sign Up</a></li> <li><a href="/users/login">Sign In</a></li> {{/if}} </ul> </nav> </div>

With that done, you are good to go into some deep parts.

Data Validation

You'll need a User model. From the views code above, you can deduce that the properties needed for the User model are email, username, and password. Create a directory called models, and a file in it called user.js.

#models/user.js // 1 const mongoose = require('mongoose') const Schema = mongoose.Schema const bcrypt = require('bcryptjs') // 2 const userSchema = new Schema({ email: String, username: String, password: String }, { // 3 timestamps: { createdAt: 'createdAt', updatedAt: 'updatedAt' } }) // 4 const User = mongoose.model('user', userSchema) module.exports = User
  1. Imports dependencies and saves them in variables.
  2. A new Schema is created. For each user, you want to save the email, username, and password to the database. The Schema shows how the model is to be constructed for each document. Here you want the email, username, and password to be of the String type.
  3. For each user saved to the database, you also want to create timestamps. You utilize Mongoose to obtain the createdAt and updatedAt, and this is then saved to the database.
  4. The model is defined and assigned to a variable called User, which is then exported as a module so it can be used in other parts of the application.
Salting and Hashing of the Password

You do not want to store users' passwords as plain text. Here's what you want to do when a user enters a plain text password while registering. The plain text password should be hashed using a salt that will be generated by your application (using bcryptjs). This hashed password is then stored in the database. 

Sounds great, right? Let's implement that in the user.js file.

#models/user.js module.exports.hashPassword = async (password) => { try { const salt = await bcrypt.genSalt(10) return await bcrypt.hash(password, salt) } catch(error) { throw new Error('Hashing failed', error) } }

You just created a method that will be called in events of user registration. The method will receive the plain text password the user entered. As I mentioned earlier, the plain text password will be hashed using a generated salt. The hashed password will be returned as the password for the user.

Index and Users Routes 

Create a new directory called routes. In this new directory, create two new files: index.js and users.js.

The index.js file will be very simple. It will map to the index of your application. Remember you set up middleware for your routes in your app.js file when you did this.

app.use('/', require('./routes/index')) app.use('/users', require('./routes/users'))

So your index routes, which simply render the index page, should look like this.

#routes/index.js const express = require('express') const router = express.Router() router.get('/', (req, res) => { res.render('index') }) module.exports = router

Now to the users route. For now, this route file will be doing four things.

  1. Require dependencies. You will need to require the dependencies you installed using NPM.
  2. Validate user inputs. You want to make sure that the user does not submit an empty form. All inputs are required, and all must be of the type String. The email has a special validation called .email() which ensures that what is entered matches the email format, while the password is validated using a regular expression. For the confirmation password, you want it to be the same as the password entered. These validations are done using Joi.
  3. Set up your router. The get request renders the registration page, while the POST request kicks in when the user hits the button to submit the form.
  4. The router gets exported as a module.

Here is what the code looks like.

#routes/users.js const express = require('express'); const router = express.Router() const Joi = require('joi') const passport = require('passport') const User = require('../models/user') //validation schema const userSchema = Joi.object().keys({ email: Joi.string().email().required(), username: Joi.string().required(), password: Joi.string().regex(/^[a-zA-Z0-9]{6,30}$/).required(), confirmationPassword: Joi.any().valid(Joi.ref('password')).required() }) router.route('/register') .get((req, res) => { res.render('register') }) .post(async (req, res, next) => { try { const result = Joi.validate(req.body, userSchema) if (result.error) { req.flash('error', 'Data entered is not valid. Please try again.') res.redirect('/users/register') return } const user = await User.findOne({ 'email': result.value.email }) if (user) { req.flash('error', 'Email is already in use.') res.redirect('/users/register') return } const hash = await User.hashPassword(result.value.password) delete result.value.confirmationPassword result.value.password = hash const newUser = await new User(result.value) await newUser.save() req.flash('success', 'Registration successfully, go ahead and login.') res.redirect('/users/login') } catch(error) { next(error) } }) module.exports = router

Let's look deeper into what is happening in that POST request.

The values entered in the registration form are accessible via req.body, and the values look like this.

value: { email: 'chineduizuchkwu1@gmail.com', username: 'izu', password: 'chinedu', confirmationPassword: 'chinedu' },

This is validated using the userSchema you created above, and the values entered by the user are assigned to a variable called result.

If an error is encountered because of the validation, an error message is displayed to the user and a redirection to the registration page takes place.

Otherwise, we try to find if a user with the same email address exists, as you do not want to have two or more users with same email address. If a user is found, the user is told that the email address is already in use.

In a scenario where no registered user has that email address, the next step is to hash the password. This is where you call the hashPassword method you created in your user.js file. The new hashed password is assigned to a variable called hash.

There is no need to store the confirmationPassword in the database. Thus this is deleted. The password available from result is still the plain password. Since you do not want to store the plain password in your database, it is important to reassign the password value to the hash that was created. This is done with a line of code.

result.value.password = hash

The new user instance gets saved to the database. A flash message stating that the registration was successful is displayed, and the user is redirected to the login page.

Start up your server from your terminal by running:

node app.js

Point your browser to http://localhost:5000 and you should see your new app.

Conclusion

Now you know how to implement the registration feature in a Node web application. You have learned the importance of validating user input and how to do that using Joi. You also made use of bcryptjs to salt and hash your password.

Next, you'll see how to implement a login feature for registered users. I trust you enjoyed yourself!

Categories: Web Design

What Is WordPress? A Beginner’s Guide To The Most Popular CMS

Over 74 Million websites! Or 27% of the web. That’s how many websites use WordPress. It can’t be a coincidence for millions of bloggers, businesses, and brands to fall...

The post What Is WordPress? A Beginner’s Guide To The Most Popular CMS appeared first on Onextrapixel.

Categories: Web Design

32 Free And Friendly Office Icons

Smashing Magazine - Wed, 12/20/2017 - 11:19
The web has changed the way we work. Startups rethought what offices look like, and with a laptop in your bag, you can get work done from anywhere anyways — no matter if it’s your desk at home or the cozy coffee shop around the corner. Over are the times of dark and stuffy cubicles — in many companies, at least. To remove the dust from the term “office” and give the visuals revolving around it a fresh and friendly face, too, the creative minds at Vexels designed a set of 32 office-themed icons.
Categories: Web Design

Building Better UI Designs With Layout Grids

Smashing Magazine - Wed, 12/20/2017 - 07:34
Designers of all types constantly face issues with the structure of their designs. One of the easiest ways to control the structure of a layout and to achieve a consistent and organized design is to apply a grid system. A grid is like invisible glue that holds a design together. Even when elements are physically separated from each other, something invisible connects them together. While grids and layout systems are a part of the heritage of design, they’re still relevant in this multiscreen world we live in.
Categories: Web Design

Creating a Task Manager App Using Ionic: Part 2

Tuts+ Code - Web Development - Wed, 12/20/2017 - 05:00

In the first part of the tutorial series, you created the user interface and navigation for the task manager app. In this tutorial, you'll see how to implement the functionality for the Ionic task manager app to add and list tasks.

Getting Started

Let's get started by cloning the source code from the first part of the tutorial series.

git clone https://github.com/royagasthyan/IonicTaskManager-Part1

Navigate to the project directory and install the required dependencies.

cd IonicTaskManager-Part1 npm install

Run your app from the project directory.

ionic serve

You should have the application running at http://localhost:8100/.

Communicating Between Components

You have already created the Add component and List component to add tasks and to list tasks respectively. In order to make them work in sync, you need to maintain communication between the two components. To communicate between the components, you'll make use of an injectable CommonService.  

Create a folder called service in the src/pages folder.

Create a service file called common.service.ts and add the following code:

import { Injectable } from '@angular/core'; @Injectable() export class CommonService { constructor(){ this.tasks = [] } }

You'll keep track of the tasks list in the common service, and it will be shared between the Add and List components.

Define a variable called tasks in the common.service.ts file. You'll keep your task list in this tasks array.

import { Injectable } from '@angular/core'; @Injectable() export class CommonService { public tasks:any; constructor(){ this.tasks = [] } }

Create a folder called task inside the src/pages folder. Create a file called task.model.ts and add the following code:

export class Task{ constructor( public Id: Number, public Name: String, public IsDone: Boolean ) { } }

You'll use the above Task class to create an instance of a new task.

When the user clicks on the Add task button from the Add component, you'll add items to the tasks variable in the common.service.ts file. So create a method called addTask in the common.service.ts file, which you'll call from the Add component.

import { Injectable } from '@angular/core'; import { Task } from '../model/task.model' @Injectable() export class CommonService { public tasks:any; constructor(){ this.tasks = [] } addTask(item){ this.tasks.push(new Task((new Date()).getTime(),item,false)); } }Add a Task to the List

In order to add a task to the task list, you need to import the common.service.ts file inside the AddPage component.

import { CommonService } from '../service/common.service'

Initialize the CommonService inside the AddPage component constructor method.

constructor(public viewCtrl: ViewController, private commonService: CommonService) { }

Inside the AddPage component, create a method called add where you'll add the task to the common service tasks list.

Here is how the add method in the AddPage component looks:

add(){ this.commonService.addTask(this.item); this.dismiss(); }

As seen in the above method, you have called the addTask method from the common service to add a task to the tasks list.

Once the item is added, you have called the dismiss method to dismiss the pop-up overlay. Here is how the add.component.ts file looks:

import { Component } from '@angular/core'; import { ViewController } from 'ionic-angular'; import { CommonService } from '../service/common.service' @Component({ selector: 'page-add', templateUrl: 'add.component.html' }) export class AddPage { public tasks: any = []; public item:String; constructor(public viewCtrl: ViewController, private commonService: CommonService) { } dismiss(){ this.viewCtrl.dismiss(); } add(){ this.commonService.addTask(this.item); this.dismiss(); } }

In the add.component.html page, add the ngModel directive to the input element.

<ion-input name="add" [(ngModel)]="item"></ion-input>

Add the click event to the button in the add.component.html to trigger the add method inside the add.component.ts.

<button ion-button round (click)="add()">Add</button>

Save the above changes and try to restart the ionic server. Navigate the browser URL to http://localhost:8100, and you should be able to view the mobile app in the browser.

Click on the Add icon to add a task. Enter the task name and click the add button. The pop-up should disappear.

Listing Task List Items

Once the task gets added in the tasks list, you need to update the view accordingly. So, to track the task when added to the list, you'll need to use Angular Subject.

Define a subject called task_subject inside the common.service.ts file.

public task_subject = new Subject<String>()

When the task gets added to the tasks list, you need to trigger the subject task_subject to inform the subscriber that a task has been added.

Modify the addTask method inside the common.service.ts file to include the following code:

this.task_subject.next();

Here is the modified addTask method:

addTask(item){ this.tasks.push(new Task((new Date()).getTime(),item,false)); this.task_subject.next(); }

Subscribe to the subject task_subject inside the list.component.ts file.

constructor(public modalCtrl: ModalController, public commonService:CommonService) { this.commonService.task_subject.subscribe(response => { this.tasks = this.commonService.tasks; }) }

Whenever a new task is added the tasks from the commonService is assigned to the tasks in list.component.html and the view is updated.

Here is how the list.component.ts code looks:

import { Component } from '@angular/core'; import { ModalController } from 'ionic-angular'; import { AddPage } from '../add/add.component'; import { CommonService } from '../service/common.service' @Component({ selector: 'page-list', templateUrl: 'list.component.html' }) export class ListPage { public tasks=[]; constructor(public modalCtrl: ModalController, public commonService:CommonService) { this.commonService.task_subject.subscribe(response => { this.tasks = this.commonService.tasks; }) } presentAddModal() { let addModal = this.modalCtrl.create(AddPage); addModal.present(); } }

Modify the list.component.html to iterate over the tasks variable from the list.component.ts file. Here is how it looks: 

<ion-list> <ion-item *ngFor="let item of tasks"> <ion-label>{{item.Name}} </ion-label> <ion-checkbox name="chk"></ion-checkbox> </ion-item> </ion-list>

Save the above changes and restart the server. Try to add a new task and it will get displayed on the listing screen.

Now let's implement the functionality to mark the finished tasks. Each time a new task is added, you are adding an IsDone attribute as false.

Let's keep two different arrays for pending tasks and finished tasks.

public pendingTasks = [] public doneTasks = []

Each time a new task is added, you'll update the above two arrays as shown:

constructor(public modalCtrl: ModalController, public commonService:CommonService) { this.commonService.task_subject.subscribe(response => { this.pendingTasks = this.commonService.tasks.filter(item => { return item.IsDone == false }); this.doneTasks = this.commonService.tasks.filter(item => { return item.IsDone == true }); }) }

When the user clicks on the check box, you need to toggle the IsDone status. Add a method called checkPendingItem to toggle the IsDone status for pending tasks.

checkPendingItem(id){ this.pendingTasks.map((task) => { if(task.Id == id){ if(task.IsDone){ task.IsDone = false; } else{ task.IsDone = true; } } }) this.updateTask() }

Similarly, add another method called checkDoneItem to toggle the task status for done items. Here is how the method looks:

checkDoneItem(id){ this.doneTasks.map((task) => { if(task.Id == id){ if(task.IsDone){ task.IsDone = false; } else{ task.IsDone = true; } } }) this.updateTask() }

Once the IsDone status is toggled, you need to update the tasks. Define a method called updateTask, which is called after IsDone toggle in both of the above methods.

updateTask(){ this.pendingTasks = this.commonService.tasks.filter(item => { return item.IsDone == false }); this.doneTasks = this.commonService.tasks.filter(item => { return item.IsDone == true }); }

Modify the list.component.html code to display the pendingTasks and doneTasks separately. Here is how the modified list.component.html file looks:

<ion-header> <ion-navbar> <ion-title text-center>Ionic Task Manager</ion-title> </ion-navbar> </ion-header> <ion-content padding> <ion-fab top right> <button ion-fab mini (click)="presentAddModal()"><ion-icon name="add"></ion-icon></button> </ion-fab> <ion-card> <ion-card-header> My Tasks </ion-card-header> <ion-list> <ion-item *ngFor="let item of pendingTasks"> <ion-label>{{item.Name}} </ion-label> <ion-checkbox name="chk" (click)="checkPendingItem(item.Id)" [checked]="item.IsDone"></ion-checkbox> </ion-item> </ion-list> </ion-card> <ion-card> <ion-card-header> Archived Tasks </ion-card-header> <ion-list> <ion-item *ngFor="let item of doneTasks"> <ion-label color="light">{{item.Name}} </ion-label> <ion-checkbox name="chk" (click)="checkDoneItem(item.Id)" [checked]="item.IsDone"></ion-checkbox> </ion-item> </ion-list> </ion-card> </ion-content>

Save the above changes and restart the ionic server. You should have the application running at http://localhost:8100.

Wrapping It Up 

In this tutorial, you saw how to implement the functionality to add and list the tasks in the Ionic task manager mobile app. You saw how to use an Angular service to share data between two components. In this tutorial, you used the Angular service to keep data in a common list when added from the Add component and display it in the List component.

Do let us know your thoughts in the comments below.

Source code from this tutorial is available on GitHub.

Categories: Web Design

Introducing Rich Results & the Rich Results Testing Tool

Google Webmaster Central Blog - Tue, 12/19/2017 - 05:56

Over the years, the different ways you can choose to highlight your website's content in search has grown dramatically. In the past, we've called these rich snippets, rich cards, or enriched results. Going forward - to simplify the terminology -  our documentation will use the name "rich results" for all of them. Additionally, we're introducing a new rich results testing tool to make diagnosing your pages' structured data easier.

The new testing tool focuses on the structured data types that are eligible to be shown as rich results. It allows you to test all data sources on your pages, such as JSON-LD (which we recommend), Microdata, or RDFa. The new tool provides a more accurate reflection of the page’s appearance on Search and includes improved handling for Structured Data found on dynamically loaded content. The tests for Recipes, Jobs, Movies, and Courses are currently supported -- but this is just a first step, we plan on expanding over time.

Testing a page is easy: just open the testing tool, enter a URL, and review the output. If there are issues, the tool will highlight the invalid code in the page source. If you're working with others on this page, the share-icon on the bottom-right lets you do that quickly. You can also use preview button to view all the different rich results the page is eligible for. And … once you're happy with the result, use Submit To Google to fetch & index this page for search.

Want to get started with rich snippets rich results? Check out our guides for marking up your content. Feel free to drop by our Webmaster Help forums should you have any questions or get stuck; the awesome experts there can often help resolve issues and give you tips in no time!


Posted by Shachar Pooyae, Software Engineer
Categories: Web Design

Creating a Task Manager App Using Ionic: Part 1

Tuts+ Code - Web Development - Tue, 12/19/2017 - 05:00

In this tutorial series, you'll learn how to get started with creating a mobile app using the Ionic framework. Ionic uses Angular for writing the components and creating the mobile app. 

Throughout the course of this series, you'll be creating a simple task manager mobile app using the Ionic framework.

From the official documentation:

Ionic is the beautiful, free and open source mobile SDK for developing native and progressive web apps with ease. Getting Started

Let's get started by installing Ionic using Node Package Manager (npm). Before installing Ionic, make sure you have Node.js installed on your system.

npm install -g cordova ionic

Once Ionic has been installed, create a new Ionic blank project using the following command:

ionic start angular-ionic blank

You'll be testing the Ionic app in the browser until it's complete. Once complete, you'll test the application on an Android device.

Type in the following command to run the app from the browser.

ionic serve

Point your browser to http://localhost:8100/ and you should have the Ionic project running.

Here is how the project structure looks:

Inside the Ionic project, you have a folder called src/app. Inside the app folder, you will find a file called app.module.ts where the root module AppModule is defined.

In the app.module.ts file inside the imports section, you can see that the root component has been defined using the following code:

IonicModule.forRoot(MyApp)

MyApp has been imported from the app.component where it has set the rootPage as HomePage, which shows up when the app loads.

Creating a List Task Component

Let's create the view for listing the added tasks. Inside the src/pages folder, create another folder for the list component called list.

Inside the list folder, create a file called list.component.html which would be the component template. Add the following code to the list.component.html file:

<ion-header> <ion-navbar> <ion-title>Ionic Task List</ion-title> </ion-navbar> </ion-header> <ion-content> <ion-list> <ion-item> <ion-label>Task 1 </ion-label> <ion-checkbox></ion-checkbox> </ion-item> <ion-item> <ion-label>Task 2</ion-label> <ion-checkbox></ion-checkbox> </ion-item> <ion-item> <ion-label>Task 3 </ion-label> <ion-checkbox></ion-checkbox> </ion-item> </ion-list> </ion-content>

As seen in the code above, you have used Ionic-specific tags for creating the elements. You can refer to the Ionic official documentation to get a list of Ionic component APIs which you can use while creating your templates.

To control the above created template, you'll need a controller class. Create a file called list.component.ts and define the ListPage class. Here is how it looks:

import { Component } from '@angular/core'; @Component({ selector: 'page-list', templateUrl: 'list.component.html' }) export class ListPage { constructor() { } }

You have defined the task listing component using the @Component decorator. Inside the @Component decorator, you have defined the selector using the selector key and the template using the templateUrl key for the component.

The application needs to know that the above created component exists, and hence you need to import it inside the root module.

Import the ListPage class inside the src/app/app.module.ts file and include it in the declarations and entryComponents list. Here is how the modified app.module.ts file looks:

import { BrowserModule } from '@angular/platform-browser'; import { ErrorHandler, NgModule } from '@angular/core'; import { IonicApp, IonicErrorHandler, IonicModule } from 'ionic-angular'; import { SplashScreen } from '@ionic-native/splash-screen'; import { StatusBar } from '@ionic-native/status-bar'; import { ListPage } from '../pages/list/list.component'; import { MyApp } from './app.component'; import { HomePage } from '../pages/home/home'; @NgModule({ declarations: [ MyApp, HomePage, ListPage ], imports: [ BrowserModule, IonicModule.forRoot(MyApp) ], bootstrap: [IonicApp], entryComponents: [ MyApp, HomePage, ListPage ], providers: [ StatusBar, SplashScreen, {provide: ErrorHandler, useClass: IonicErrorHandler} ] }) export class AppModule {}

When the application loads up, you want the newly created List component to show up instead of the HomePage. So modify the rootPage defined inside the app.component.ts file. 

import { Component } from '@angular/core'; import { Platform } from 'ionic-angular'; import { StatusBar } from '@ionic-native/status-bar'; import { SplashScreen } from '@ionic-native/splash-screen'; import { HomePage } from '../pages/home/home'; import { ListPage } from '../pages/list/list.component'; @Component({ templateUrl: 'app.html' }) export class MyApp { rootPage:any = ListPage; constructor(platform: Platform, statusBar: StatusBar, splashScreen: SplashScreen) { platform.ready().then(() => { statusBar.styleDefault(); splashScreen.hide(); }); } }

As seen in the above code, you imported the ListPage inside the app.component.ts file and changed the rootPage to ListPage instead of HomePage.

Save the above changes and start the Ionic server using the following command:

ionic serve

You should have the mobile app running at http://localhost:8100/

Creating the Add Task Component

From the listing screen, you'll add a link to add items to the list. Let's place an add icon on the right side of the screen. Inside the list.component.html file, add the following to add the plus icon.

<ion-fab top right> <button ion-fab mini><ion-icon name="add"></ion-icon></button> </ion-fab>

Here is how the modified list.component.html file looks:

<ion-header> <ion-navbar> <ion-title text-center>Ionic Task Manager</ion-title> </ion-navbar> </ion-header> <ion-content padding> <ion-fab top right> <button ion-fab mini><ion-icon name="add"></ion-icon></button> </ion-fab> <ion-list> <ion-item> <ion-label>Task 1 </ion-label> <ion-checkbox></ion-checkbox> </ion-item> <ion-item> <ion-label>Task 2</ion-label> <ion-checkbox></ion-checkbox> </ion-item> <ion-item> <ion-label>Task 3 </ion-label> <ion-checkbox></ion-checkbox> </ion-item> </ion-list> </ion-content>

Save the above changes and restart the server, and you will have the plus icon displayed on the screen.

When the user clicks on the plus icon, you need to show the screen to add new tasks. So let's create another component called the Add component.

Create a folder called add inside the pages folder. Inside the add folder, create a file called add.component.html and add the following code:

<ion-header> <ion-navbar> <ion-title text-center>Ionic Task Manager</ion-title> </ion-navbar> </ion-header> <ion-content padding> <ion-fab top right> <button ion-fab mini> <ion-icon name="arrow-back"></ion-icon></button> </ion-fab> <ion-list> <ion-item> <ion-label color="primary" floating>Enter task </ion-label> <ion-input></ion-input> </ion-item> </ion-list> <button ion-button round>Add</button> </ion-content>

The above code displays the screen to add a new task.

You need to display the above screen when the user clicks the plus icon on the list screen. So you'll be showing it as a modal popup.

Create a file called add.component.ts and add the following code:

import { Component } from '@angular/core'; @Component({ selector: 'page-add', templateUrl: 'add.component.html' }) export class AddPage { constructor() { } }

As seen in the above code, you just created the Add component by specifying the selector and templateUrl.

Register the component by importing it in the app.module.ts file inside the src/app folder. Here is how the modified app.module.ts file looks:

import { BrowserModule } from '@angular/platform-browser'; import { ErrorHandler, NgModule } from '@angular/core'; import { IonicApp, IonicErrorHandler, IonicModule } from 'ionic-angular'; import { SplashScreen } from '@ionic-native/splash-screen'; import { StatusBar } from '@ionic-native/status-bar'; import { ListPage } from '../pages/list/list.component'; import { AddPage } from '../pages/add/add.component'; import { MyApp } from './app.component'; import { HomePage } from '../pages/home/home'; @NgModule({ declarations: [ MyApp, HomePage, ListPage, AddPage ], imports: [ BrowserModule, IonicModule.forRoot(MyApp) ], bootstrap: [IonicApp], entryComponents: [ MyApp, HomePage, ListPage, AddPage ], providers: [ StatusBar, SplashScreen, {provide: ErrorHandler, useClass: IonicErrorHandler} ] }) export class AppModule {}

To show the AddPage component in a modal popup, you need to import ModalController provided by ionic-angular. Import ModalController in list.component.ts.

import { ModalController } from 'ionic-angular';

Create a method called presentAddModal and create a modal using the imported ModalController. Here is how the list.component.ts file looks:

import { Component } from '@angular/core'; import { ModalController } from 'ionic-angular'; import { AddPage } from '../add/add.component'; @Component({ selector: 'page-list', templateUrl: 'list.component.html' }) export class ListPage { constructor(public modalCtrl: ModalController) {} presentAddModal() { let addModal = this.modalCtrl.create(AddPage); addModal.present(); } }

Register the click event on the add button in list.component.html. 

<button ion-fab mini (click)="presentAddModal()"><ion-icon name="add"></ion-icon></button>

Save the above changes and restart the Ionic server. Click on the add icon in the list page and you will have the add task page.

For the back button on the add task screen, you need to add a dismiss method on the button click in the add.component.ts file.

<button ion-fab mini (click)="dismiss()"> <ion-icon name="arrow-back"></ion-icon></button>

Import the ViewController module and call the dismiss method to go back to the listing screen. Here is how it looks:

import { Component } from '@angular/core'; import { ViewController } from 'ionic-angular'; @Component({ selector: 'page-add', templateUrl: 'add.component.html' }) export class AddPage { constructor(public viewCtrl: ViewController) { } dismiss(){ this.viewCtrl.dismiss(); } } Wrapping It Up

In this tutorial, you saw how to get started with creating a mobile app using the Ionic framework, which uses Angular. You created the view for a task manager app. You created the Add component and List component. 

In the next part of this tutorial series, you'll implement the functionality for the task manager app to add and list tasks.

Source code from this tutorial is available on GitHub.

Do let us know your suggestions in the comments below.

Categories: Web Design

Inspiration From Mobile Dating Apps: How To Improve Your Designs

Smashing Magazine - Tue, 12/19/2017 - 04:58
Making improvements to your mobile app’s design isn’t necessarily the easiest of tasks. After all, how much can really be accomplished within such a limited space? You recognize that mobile users’ attention spans are waning and that, consequently, they expect a speedy, convenient and engaging experience when using apps. Realistically, how many other ways can there be to satisfy these expectations that haven’t already been done before? Let’s take mobile dating apps.
Categories: Web Design

Introduction to Forms in Angular 4: Reactive Forms

Tuts+ Code - Web Development - Tue, 12/19/2017 - 04:00
What You'll Be Creating

This is the second part of the series on Introduction to Forms in Angular 4. In the first part, we created a form using the template-driven approach. We used directives such as ngModel, ngModelGroup and ngForm to supercharge the form elements. In this tutorial, we will be taking a different approach to building forms—the reactive way. 

Reactive Forms

Reactive forms take a different approach compared to that of the template-driven forms. Here, we create and initialize the form control objects in our component class. They are intermediate objects that hold the state of the form. We will then bind them to the form control elements in the template.

The form control object listens to any change in the input control values, and they are immediately reflected in the object's state. Since the component has direct access to the data model structure, all changes can be synchronized between the data model, the form control object, and the input control values. 

Practically speaking, if we are building a form for updating the user profile, the data model is the user object retrieved from the server. By convention, this is often stored inside the component's user property (this.user). The form control object or the form model will be bound to the template's actual form control elements.

Both these models should have similar structures, even if they are not identical. However, the input values shouldn't flow into the data model directly. The image describes how the user input from the template makes its way to the form model.

Let's get started.

Prerequisites

You don’t need to have followed part one of this series, for part two to make sense. However, if you are new to forms in Angular, I would highly recommend going through the template-driven strategy. The code for this project is available on my GitHub repository. Make sure that you are on the right branch and then download the zip or, alternatively, clone the repo to see the form in action. 

If you prefer to start from scratch instead, make sure that you have Angular CLI installed. Use the ng command to generate a new project. 

$ ng new SignupFormProject

Next, generate a new component for the SignupForm or create one manually. 

ng generate component SignupForm

Replace the contents of app.component.html with this:

<app-signup-form> </app-signup-form>

Here is the directory structure for the src/ directory. I've removed some non-essential files to keep things simple.

. ├── app │   ├── app.component.css │   ├── app.component.html │   ├── app.component.ts │   ├── app.module.ts │   ├── signup-form │   │   ├── signup-form.component.css │   │   ├── signup-form.component.html │   │   └── signup-form.component.ts │   └── User.ts ├── index.html ├── main.ts ├── polyfills.ts ├── styles.css ├── tsconfig.app.json └── typings.d.ts

As you can see, a directory for the SignupForm component has been created automatically. That's where most of our code will go. I've also created a new User.ts for storing our User model.

The HTML Template

Before we dive into the actual component template, we need to have an abstract idea of what we are building. So here is the form structure that I have in my mind. The signup form will have several input fields, a select element, and a checkbox element. 


Here is the HTML template that we will be using for our registration page. 

HTML Template <div class="row custom-row"> <div class= "col-sm-5 custom-container jumbotron"> <form class="form-horizontal"> <fieldset> <legend>SignUp</legend> <!--- Email Block ---> <div class="form-group"> <label for="inputEmail">Email</label> <input type="text" id="inputEmail" placeholder="Email"> </div> <!--- Password Block ---> <div class="form-group"> <label for="inputPassword">Password</label> <input type="password" id="inputPassword" placeholder="Password"> </div> <div class="form-group"> <label for="confirmPassword" >Confirm Password</label> <input type="password" id="confirmPassword" placeholder="Password"> </div> <!--- Select gender Block ---> <div class="form-group"> <label for="select">Gender</label> <select id="select"> <option>Male</option> <option>Female</option> <option>Other</option> </select> </div> <!--- Terms and conditions Block ---> <div class="form-group checkbox"> <label> <input type="checkbox"> Confirm that you've read the Terms and Conditions </label> </div> <!--- Buttons Block ---> <div class="form-group"> <button type="reset" class="btn btn-default">Cancel</button> <button type="submit" class="btn btn-primary">Submit</button> </div> </fieldset> </form> </div> </div>

The CSS classes used in the HTML template are part of the Bootstrap library used for making things pretty. Since this is a not a design tutorial, I won't be talking much about the CSS aspects of the form unless necessary. 

Basic Form Setup

To create a Reactive form, you need to import  the ReactiveFormsModule from @angular/forms and add it to the imports array in app.module.ts.

app/app.module.ts// Import ReactiveFormsModule import { ReactiveFormsModule } from '@angular/forms'; @NgModule({ . . //Add the module to the imports Array imports: [ BrowserModule, ReactiveFormsModule . . }) export class AppModule { }

Next, create a User model for the registration form. We can either use a class or an interface for creating the model. For this tutorial, I am going to export a class with the following properties.

app/User.tsexport class User { id: number; email: string; //Both the passwords are in a single object password: { pwd: string; confirmPwd: string; }; gender: string; terms: boolean; constructor(values: Object = {}) { //Constructor initialization Object.assign(this, values); } }

Now, create an instance of the User model in the SignupForm component. 

app/signup-form/signup-form.component.tsimport { Component, OnInit } from '@angular/core'; // Import the User model import { User } from './../User'; @Component({ selector: 'app-signup-form', templateUrl: './signup-form.component.html', styleUrls: ['./signup-form.component.css'] }) export class SignupFormComponent implements OnInit { //Gender list for the select control element private genderList: string[]; //Property for the user private user:User; ngOnInit() { this.genderList = ['Male', 'Female', 'Others']; }

For the signup-form.component.html file, I am going to use the same HTML template discussed above, but with minor changes. The signup form has a select field with a list of options. Although that works, we will do it the Angular way by looping through the list using the ngFor directive.

app/signup-form/signup-form.component.html<div class="row custom-row"> <div class= "col-sm-5 custom-container jumbotron"> <form class="form-horizontal"> <fieldset> <legend>SignUp</legend> . . <!--- Gender Block --> <div class="form-group"> <label for="select">Gender</label> <select id="select"> <option *ngFor = "let g of genderList" [value] = "g"> {{g}} </option> </select> </div> . . </fieldset> </form> </div> </div>

Note: You might get an error that says No provider for ControlContainer. The error appears when a component has a <form> tag without a formGroup directive. The error will disappear once we add a FormGroup directive later in the tutorial.

We have a component, a model, and a form template at hand. What now? It's time to get our hands dirty and become acquainted with the APIs that you need to create reactive forms. This includes FormControl and FormGroup. 

Tracking the State Using FormControl

While building forms with the reactive forms strategy, you won't come across the ngModel and ngForm directives. Instead, we use the underlying FormControl and FormGroup API.

A FormControl is a directive used to create a FormControl instance that you can use to keep track of a particular form element's state and its validation status. This is how FormControl works:

/* Import FormControl first */ import { FormControl } from '@angular/forms'; /* Example of creating a new FormControl instance */ export class SignupFormComponent { email = new FormControl(); }

email is now a FormControl instance, and you can bind it to an input control element in your template as follows:

<h2>Signup</h2> <label class="control-label">Email: <input class="form-control" [formControl]="email"> </label>

The template form element is now bound to the FormControl instance in the component. What that means is any change to the input control value gets reflected at the other end. 

A FormControl constructor accepts three arguments—an initial value, an array of sync validators, and an array of async validators—and as you might have guessed, they are all optional. We will be covering the first two arguments here. 

import { Validators } from '@angular/forms'; . . . /* FormControl with initial value and a validator */ email = new FormControl('bob@example.com', Validators.required);

Angular has a limited set of built-in validators. The popular validator methods include Validators.required, Validators.minLength, Validators.maxlength, and Validators.pattern. However, to use them, you have to import the Validator API first.

For our signup form, we have multiple input control fields (for email and password), a selector field, and a checkbox field. Rather than creating individual FormControl objects, wouldn't it make more sense to group all these FormControls under a single entity? This is beneficial because we can now track the value and the validity of all the sub-FormControl objects in one place. That's what FormGroup is for. So we will register a parent FormGroup with multiple child FormControls. 

Group Multiple FormControls With FormGroup

To add a FormGroup, import it first. Next, declare signupForm as a class property and initialize it as follows:

app/signup-form/signup-form.component.ts//Import the API for building a form import { FormControl, FormGroup, Validators } from '@angular/forms'; export class SignupFormComponent implements OnInit { genderList: String[]; signupForm: FormGroup; . . ngOnInit() { this.genderList = ['Male', 'Female', 'Others']; this.signupForm = new FormGroup ({ email: new FormControl('',Validators.required), pwd: new FormControl(), confirmPwd: new FormControl(), gender: new FormControl(), terms: new FormControl() }) } }

Bind the FormGroup model to the DOM as follows: 

app/signup-form/signup-form.component.html <form class="form-horizontal" [formGroup]="signupForm" > <fieldset> <legend>SignUp</legend> <!--- Email Block --> <div class="form-group"> <label for="inputEmail">Email</label> <input type="text" formControlName = "email" id="inputEmail" placeholder="Email"> . . </fieldset> </form>

[formGroup] = "signupForm" tells Angular that you want to associate this form with the FormGroup declared in the component class. When Angular sees formControlName="email", it checks for an instance of FormControl with the key value email inside the parent FormGroup. 

Similarly, update the other form elements by adding a formControlName="value" attribute as we just did here.

To see if everything is working as expected, add the following after the form tag:

app/signup-form/signup-form.component.html<!--- Log the FormGroup values to see if the binding is working --> <p>Form value {{ signupForm.value | json }} </p> <p> Form status {{ signupForm.status | json}} </p>

Pipe the SignupForm property through the JsonPipe to render the model as JSON in the browser. This is helpful for debugging and logging. You should see a JSON output like this.

There are two things to note here:

  1. The JSON doesn't exactly match the structure of the user model that we created earlier. 
  2. The signupForm.status displays that the status of the form is INVALID. This clearly shows that the Validators.required on the email control field is working as expected. 

The structure of the form model and the data model should match. 

// Form model { "email": "", "pwd": "", "confirmPwd": "", "gender": "", "terms": false } //User model { "email": "", "password": { "pwd": "", "confirmPwd": "", }, "gender": "", "terms": false }

To get the hierarchical structure of the data model, we should use a nested FormGroup. Additionally, it's always a good idea to have related form elements under a single FormGroup. 

Nested FormGroup

Create a new FormGroup for the password.

app/signup-form/signup-form.component.ts
this.signupForm = new FormGroup ({ email: new FormControl('',Validators.required), password: new FormGroup({ pwd: new FormControl(), confirmPwd: new FormControl() }), gender: new FormControl(), terms: new FormControl() })

Now, to bind the new form model with the DOM, make the following changes:

app/signup-form/signup-form.component.html<!--- Password Block --> <div formGroupName = "password"> <div class="form-group"> <label for="inputPassword">Password</label> <input type="password" formControlName = "pwd" id="inputPassword" placeholder="Password"> </div> <div class="form-group"> <label for="confirmPassword" >Confirm Password</label> <input type="password" formControlName = "confirmPwd" id="confirmPassword" placeholder="Password"> </div> </div>

formGroupName = "password" performs the binding for the nested FormGroup. Now, the structure of the form model matches our requirements.

Form value: { "email": "", " password": { "pwd": null, "confirmPwd": null }, "gender": null, "terms": null } Form status "INVALID"

Next up, we need to validate the form controls.

Validating the Form

We have a simple validation in place for the email input control. However, that's not sufficient. Here is the entire list of our requirements for the validation.

  • All form control elements are required.
  • Disable the submit button until the status of the form is VALID.
  • The email field should strictly contain an email id.
  • The password field should have a minimum length of 8.

The first one is easy. Add Validator.required to all the FormControls in the form model. 

app/signup-form/signup-form.component.ts  this.signupForm = new FormGroup ({ email: new FormControl('',Validators.required), password: new FormGroup({ pwd: new FormControl('', Validators.required), confirmPwd: new FormControl('', Validators.required) }), gender: new FormControl('', Validators.required), //requiredTrue so that the terms field isvalid only if checked terms: new FormControl('', Validators.requiredTrue) })

Next, disable the button while the form is INVALID.

app/signup-form/signup-form.component.html<!--- Buttons Block --> <div class="form-group"> <button type="reset" class="btn btn-default">Cancel</button> <button type="submit" [disabled] = "!signupForm.valid" class="btn btn-primary">Submit</button> </div>

To add a constraint on email, you can either use the default Validators.email or create a custom Validators.pattern() that specifies regular expressions like the one below:

email: new FormControl('', [Validators.required, Validators.pattern('[a-z0-9._%+-]+@[a-z0-9.-]+\.[a-z]{2,3}$')])

Use the minLength validator for the password fields.

password: new FormGroup({ pwd: new FormControl('', [Validators.required, Validators.minLength(8)]), confirmPwd: new FormControl('', [Validators.required, Validators.minLength(8)]) }),

That's it for the validation. However, the form model logic appears cluttered and repetitive. Let's clean that up first. 

Refactoring the Code Using FormBuilder

Angular provides you with a syntax sugar for creating new instances of FormGroup and FormControl called FormBuilder. The FormBuilder API doesn't do anything special other than what we've covered here.

It simplifies our code and makes the process of building a form easy on the eyes. To create a FormBuilder, you have to import it into signup-form.component.ts and inject the FormBuilder into the constructor.

app/signup-form/signup-form.component.ts import { FormBuilder, FormGroup, Validators } from '@angular/forms'; . . export class SignupFormComponent implements OnInit { signupForm: FormGroup; // Declare the signupForm //Inject the formbuilder into the constructor constructor(private fb:FormBuilder) {} ngOnInit() { ... } }

Instead of a creating a new FormGroup(), we are using this.fb.group to build a form. Except for the syntax, everything else remains the same.

app/signup-form/signup-form.component.ts  ngOnInit() { ... this.signupForm = this.fb.group({ email: ['',[Validators.required, Validators.pattern('[a-z0-9._%+-]+@[a-z0-9.-]+\.[a-z]{2,3}$')]], password: this.fb.group({ pwd: ['', [Validators.required, Validators.minLength(8)]], confirmPwd: ['', [Validators.required, Validators.minLength(8)]] }), gender: ['', Validators.required], terms: ['', Validators.requiredTrue] }) }Displaying Validation Errors 

For displaying the errors, I am going to use the conditional directive ngIf on a div element. Let's start with the input control field for email:

<!-- Email error block --> <div *ngIf="signupForm.controls.email.invalid && signupForm.controls.email.touched" Email is invalid </div>

There are a couple of issues here. 

  1. Where did invalid and pristine come from? 
  2. signupForm.controls.email.invalid is too long and deep.
  3. The error doesn't explicitly say why it's invalid.

To answer the first question, each FormControl has certain properties like invalid, valid, pristine, dirty, touched, and untouched. We can use these to determine whether an error message or a warning should be displayed or not. The image below describes each of those properties in detail.

So the div element with the *ngIf will be rendered only if the email is invalid. However, the user will be greeted with errors about the input fields being blank even before they have a chance to edit the form. 

To avoid this scenario, we've added the second condition. The error will be displayed only after the control has been visited.

To get rid of the long chain of method names (signupForm.controls.email.invalid), I am going to add a couple of shorthand getter methods. This keeps them more accessible and short. 

app/signup-form/signup-form.component.ts export class SignupFormComponent implements OnInit { ... get email() { return this.signupForm.get('email'); } get password() { return this.signupForm.get('password'); } get gender() { return this.signupForm.get('gender'); } get terms() { return this.signupForm.get('terms'); } }

To make the error more explicit, I've added nested ngIf conditions below:

app/signup-form/signup-form.component.html<!-- Email error block --> <div *ngIf="email.invalid && email.touched" class="col-sm-3 text-danger"> <div *ngIf = "email.errors?.required"> Email field can't be blank </div> <div *ngIf = "email.errors?.pattern"> The email id doesn't seem right </div> </div>

We use email.errors to check all possible validation errors and then display them back to the user in the form of custom messages. Now, follow the same procedure for the other form elements. Here is how I've coded the validation for the passwords and the terms input control.

app/signup-form/signup-form.component.html <!-- Password error block --> <div *ngIf="(password.invalid && password.touched)" class="col-sm-3 text-danger"> Password needs to be more than 8 characters </div> . . . <!--- Terms error block --> <div *ngIf="(terms.invalid && terms.touched)" class="col-sm-3 text-danger"> Please accept the Terms and conditions first. </div> </div>Submit the Form Using ngSubmit

We are nearly done with the form. It lacks the submit functionality, which we are about to implement now.

<form class="form-horizontal" [formGroup]="signupForm" (ngSubmit)="onFormSubmit()" >

On form submit, the form model values should flow into the component's user property.

app/signup-form/signup-form.component.tspublic onFormSubmit() { if(this.signupForm.valid) { this.user = this.signupForm.value; console.log(this.user); /* Any API call logic via services goes here */ } }Final Demo

Here is the final version of the application. I've added a few Bootstrap classes to make the form pretty.

Wrapping It Up

If you've been following this tutorial series from the start, we had a hands-on experience with two popular form building technologies in Angular. The template-driven and model-driven techniques are two ways of achieving the same thing. Personally, I prefer to use the reactive forms for the following reasons:

  • All the form validation logic will be located in a single place—inside your component class. This is way more productive than the template approach, where the ngModel directives are scattered across the template.
  • Unlike template-driven forms, Model-driven forms are easier to test. You don't have to resort to end-to-end testing libraries to test your form.
  • Validation logic will go inside the component class and not in the template.
  • For a form with a large number of form elements, this approach has something called FormBuilder to make the creation of FormControl objects easier.

We missed out on one thing, and that is writing a validator for the password mismatch. In the final part of the series, we will cover everything you need to know about creating custom validator functions in Angular. Stay tuned until then.

In the meantime, there are plenty of frameworks and libraries to keep you busy, with lots of items on Envato Market to read, study, and use.

Categories: Web Design

#NoHacked 3.0: Fixing common hack cases

Google Webmaster Central Blog - Mon, 12/18/2017 - 14:05
So far on #NoHacked, we have shared some tips on detection and prevention. Now that you are able to detect hack attack, we would like to introduce some common hacking techniques and guides on how to fix them!

  • Fixing the Cloaked Keywords and Links Hack The cloaked keywords and link hack automatically creates many pages with nonsensical sentences, links, and images. These pages sometimes contain basic template elements from the original site, so at first glance, the pages might look like normal parts of the target site until you read the content. In this type of attack, hackers usually use cloaking techniques to hide the malicious content and make the injected page appear as part of the original site or a 404 error page.
  • Fixing the Gibberish Hack The gibberish hack automatically creates many pages with nonsensical sentences filled with keywords on the target site. Hackers do this so the hacked pages show up in Google Search. Then, when people try to visit these pages, they'll be redirected to an unrelated page, like a porn site for example.
  • Fixing the Japanese Keywords Hack The Japanese keywords hack typically creates new pages with Japanese text on the target site in randomly generated directory names. These pages are monetized using affiliate links to stores selling fake brand merchandise and then shown in Google search. Sometimes the accounts of the hackers get added in Search Console as site owners.

Lastly, after you clean your site and fix the problem, make sure to file for a reconsideration request to have our teams review your site.

If you have any questions, post your questions on our Webmaster Help Forums!

.blgimg1 { width: 100%; padding: 0 0 -10px 0; margin: 0; border: 0; } .blgimg2 { width: 100%; padding: 0 0 -10px 0; margin: 0; border: 0; } .blgimg3 { width: 100%; padding: 0 0 -10px 0; margin: 0; border: 0; } .blgimg4 { width: 100%; padding: 0 0 -10px 0; margin: 0; border: 0; }
Categories: Web Design

Breaking The Rules: Using SQLite To Demo Web Apps

Smashing Magazine - Mon, 12/18/2017 - 07:14
Most potential users will want to try out the software or service before committing any time and money. Some products work great by just giving users a free trial, while other apps are best experienced with sample data already in place. Often this is where the age-old demo account comes into play. However, anyone who has ever implemented a demo account can attest to the problems associated. You know how things run on the Internet: Anyone can enter data (whether it makes sense or not to the product) and there is a good chance that the content added by anonymous users or bots could be offensive to others.
Categories: Web Design

Getting your site ready for mobile-first indexing

Google Webmaster Central Blog - Mon, 12/18/2017 - 05:08
When we announced almost a year ago that we're experimenting with mobile-first indexing, we said we'd update publishers about our progress, something that we've done the past few months through public talks in office hours on Hangouts on Air and at conferences like Pubcon.

To recap, currently our crawling, indexing, and ranking systems typically look at the desktop version of a page's content, which may cause issues for mobile searchers when that version is vastly different from the mobile version. Mobile-first indexing means that we'll use the mobile version of the content for indexing and ranking, to better help our – primarily mobile – users find what they're looking for. Webmasters will see significantly increased crawling by Smartphone Googlebot, and the snippets in the results, as well as the content on the Google cache pages, will be from the mobile version of the pages.

As we said, sites that make use of responsive web design and correctly implement dynamic serving (that include all of the desktop content and markup) generally don't have to do anything. Here are some extra tips that help ensure a site is ready for mobile-first indexing:
  • Make sure the mobile version of the site also has the important, high-quality content. This includes text, images (with alt-attributes), and videos - in the usual crawlable and indexable formats.
  • Structured data is important for indexing and search features that users love: it should be both on the mobile and desktop version of the site. Ensure URLs within the structured data are updated to the mobile version on the mobile pages.
  • Metadata should be present on both versions of the site. It provides hints about the content on a page for indexing and serving. For example, make sure that titles and meta descriptions are equivalent across both versions of all pages on the site.
  • No changes are necessary for interlinking with separate mobile URLs (m.-dot sites). For sites using separate mobile URLs, keep the existing link rel=canonical and link rel=alternate elements between these versions.
  • Check hreflang links on separate mobile URLs. When using link rel=hreflang elements for internationalization, link between mobile and desktop URLs separately. Your mobile URLs' hreflang should point to the other language/region versions on other mobile URLs, and similarly link desktop with other desktop URLs using hreflang link elements there.
  • Ensure the servers hosting the site have enough capacity to handle potentially increased crawl rate. This doesn't affect sites that use responsive web design and dynamic serving, only sites where the mobile version is on a separate host, such as m.example.com.
We will be evaluating sites independently on their readiness for mobile-first indexing based on the above criteria and transitioning them when ready. This process has already started for a handful of sites and is closely being monitored by the search team.

We continue to be cautious with rolling out mobile-first indexing. We believe taking this slowly will help webmasters get their sites ready for mobile users, and because of that, we currently don't have a timeline for when it's going to be completed. If you have any questions, drop by our Webmaster forums or our public events.

Posted by Gary

Categories: Web Design

Deferring Tasks in Laravel Using Queues

Tuts+ Code - Web Development - Mon, 12/18/2017 - 05:00

In this article, we're going to explore the Queue API in the Laravel web framework. It allows you to defer resource-intensive tasks during script execution to enhance the overall end user experience. After introducing the basic terminology, I'll demonstrate it by implementing a real-world example.

Page load time is an important aspect of any successful website, and one should not overlook the importance of that as it affects the SEO of the site and the overall end user experience as well. More often than not, you end up needing to debug web pages with long page load times. Of course, there are different approaches you could use to rectify this issue.

Upon investigation, you often realize that there are certain code blocks causing a delay in the page execution. The next thing you could try is identifying blocks that can be deferred for processing and that have no real impact on the end result of the current page. That should really improve the overall web page speed as we've eliminated code blocks that were causing a delay.

Today, we're going to explore a similar concept in the context of the Laravel web framework. In fact, Laravel already provides a useful built-in API that allows us to defer the processing of tasks—the Queue API. Without wasting much of your time, I'll go ahead and discuss the basic elements of the Queue API.

Drivers, Connections, Queues, and Jobs

The basic purpose of the Queue API is to run jobs that are added in a queue. Next, the queue could belong to a specific connection, and that connection may belong to a specific queue driver configured with that connection itself. Let's briefly try to understand what I've just said.

Queue Drivers

In the same way you would have used a different driver for your database connection, you could also choose from a variety of different queue drivers. The Queue API supports different adapters like database, beanstalkd, sqs, and redis.

The queue driver is just a place that is used to store queue-related information. So if you're using a database queue driver, for example, the new job will be added in the jobs table in the database. On the other hand, if you've configured redis as the default queue driver, the job will be added to the redis server.

The Queue API also provides two special queue drivers for testing purposes—sync and null. The sync queue driver is used to execute a queue job immediately, while the null queue driver is used to skip a job so that it won't be executed at all.

Connections

When you configure the Queue API for the first time, you need to specify a default connection that should be used for default queue processing. At the very least, the connection is expected to provide the following information:

  • the queue driver that will be used
  • the queue driver's specific configuration values
  • the default queue name in which the job will be added
Queues

When you add any job into a queue, it'll be added into the default queue. In fact, that should be fine in most cases, unless you have jobs that need to be given higher priority over other jobs. In that case, you could create a queue named high and place the higher priority jobs in that particular queue.

When you run a queue worker that processes queued jobs, you could optionally pass the --queue parameter, which allows you to list queue names in the order in which they need to be processed. For example, if you specify --queue=high,default, it will first process jobs in the high queue, and once it's completed it fetches jobs in the default queue.

Jobs

A job in the Queue API is a task that's deferred from the main execution flow. For example, if you want to create a thumbnail when the user uploads an image from the front-end, you could create a new job that handles the thumbnail processing. In this way, you could defer the task of thumbnail processing from the main execution flow.

That was a basic introduction to the Queue API terminology. From the next section onwards, we'll explore how to create a custom queue job and run it by using a Laravel queue worker.

Create Your First Queue Job

By now, you should feel confident about queue jobs. From this section onwards, we're going to implement a real-world example that demonstrates the concept of queue jobs in Laravel.

More often than not, you end up in the situation where you need to create different thumbnail versions of an image uploaded by a user. In most cases, the developer tries to process it in real time so that different versions of images are created right away when the user uploads an image.

It seems to be a reasonable approach if you're going to create a couple of versions and it doesn't take too much time in the first place. On the other hand, if you're dealing with an application that requires heavy processing and thus eats up more resources, real-time processing could end up in a bad user experience.

The obvious option that pops up in your mind in the first place is to defer processing of the thumbnail generation as late as possible. The simplest approach you could implement in this specific scenario is to set a cron job that triggers processing at regular intervals, and you should be fine.

A much better approach, on the other hand, is to defer and push the task into a queue, and let the queue worker process it when it gets a chance to do so. In a production environment, the queue worker is a daemon script that's always running and processing tasks in a queue. The obvious benefit of this approach is a much better end user experience, and you don't have to wait for the cron run as the job will be processed as soon as possible.

I guess that's enough theory to get started with an actual implementation.

In our case, we're going to use the database queue driver, and it requires us to create the jobs table in the database. The jobs table holds all the jobs that need to be processed in the next queue worker run.

Before we go ahead and create the jobs table, let's change the default queue configuration from sync to database in the config/queue.php file.

... ... /* |-------------------------------------------------------------------------- | Default Queue Driver |-------------------------------------------------------------------------- | | Laravel's queue API supports an assortment of back-ends via a single | API, giving you convenient access to each back-end using the same | syntax for each one. Here you may set the default queue driver. | | Supported: "sync", "database", "beanstalkd", "sqs", "redis", "null" | */ 'default' => env('QUEUE_DRIVER', 'database'), ... ...

In fact, Laravel already provides an artisan command that helps us to create the jobs table. Run the following command in the root of your Laravel application, and it should create the necessary database migration that creates the jobs table.

$php artisan queue:table

The migration file that's generated at database/migrations/YYYY_MM_DD_HHMMSS_create_jobs_table.php should look like this:

<?php use Illuminate\Support\Facades\Schema; use Illuminate\Database\Schema\Blueprint; use Illuminate\Database\Migrations\Migration; class CreateJobsTable extends Migration { /** * Run the migrations. * * @return void */ public function up() { Schema::create('jobs', function (Blueprint $table) { $table->bigIncrements('id'); $table->string('queue'); $table->longText('payload'); $table->unsignedTinyInteger('attempts'); $table->unsignedInteger('reserved_at')->nullable(); $table->unsignedInteger('available_at'); $table->unsignedInteger('created_at'); $table->index(['queue', 'reserved_at']); }); } /** * Reverse the migrations. * * @return void */ public function down() { Schema::dropIfExists('jobs'); } }

Next, let's run the migrate command so that it actually creates the jobs table in a database.

php artisan migrate

That's it as far as the jobs migration is concerned.

Next, let's create the Image model that will be used to manage images uploaded by the end user. The image model also requires an associated database table, so we'll use the --migrate option while creating the Image model.

php artisan make:model Image --migration

The above command should create the Image model class and an associated database migration as well.

The Image model class should look like this:

<?php // app/Image.php namespace App; use Illuminate\Database\Eloquent\Model; class Image extends Model { // }

And the database migration file should be created at database/migrations/YYYY_MM_DD_HHMMSS_create_images_table.php. We also want to store the original path of the image uploaded by the end user. Let's revise the code of the Image database migration file to look like the following.

<?php // database/migrations/YYYY_MM_DD_HHMMSS_create_images_table.php use Illuminate\Support\Facades\Schema; use Illuminate\Database\Schema\Blueprint; use Illuminate\Database\Migrations\Migration; class CreateImagesTable extends Migration { /** * Run the migrations. * * @return void */ public function up() { Schema::create('images', function (Blueprint $table) { $table->increments('id'); $table->timestamps(); $table->string('org_path'); }); } /** * Reverse the migrations. * * @return void */ public function down() { Schema::dropIfExists('images'); } }

As you can see, we've added the $table->string('org_path') column to store the path of the original image. Next, you just need to run the migrate command to actually create that table in the database.

$php artisan migrate

And that's it as far as the Image model is concerned.

Next, let's create an actual queue job that's responsible for processing image thumbnails. For the thumbnail processing, we're going to use a very popular image processing library—Intervention Image.

To install the Intervention Image library, go ahead and run the following command at the root of your application.

$php composer.phar require intervention/image

Now, it's time to create the Job class, and we'll use an artisan command to do that.

$php artisan make:job ProcessImageThumbnails

That should create the Job class template at app/Jobs/ProcessImageThumbnails.php. Let's replace the contents of that file with the following.

<?php // app/Jobs/ProcessImageThumbnails.php namespace App\Jobs; use App\Image as ImageModel; use Illuminate\Bus\Queueable; use Illuminate\Queue\SerializesModels; use Illuminate\Queue\InteractsWithQueue; use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Foundation\Bus\Dispatchable; use Illuminate\Support\Facades\DB; class ProcessImageThumbnails implements ShouldQueue { use Dispatchable, InteractsWithQueue, Queueable, SerializesModels; protected $image; /** * Create a new job instance. * * @return void */ public function __construct(ImageModel $image) { $this->image = $image; } /** * Execute the job. * * @return void */ public function handle() { // access the model in the queue for processing $image = $this->image; $full_image_path = public_path($image->org_path); $resized_image_path = public_path('thumbs' . DIRECTORY_SEPARATOR . $image->org_path); // create image thumbs from the original image $img = \Image::make($full_image_path)->resize(300, 200); $img->save($resized_image_path); } }

When the queue worker starts processing any job, it looks for the handle method. So it's the handle method that holds the main logic of your job.

In our case, we need to create a thumbnail of an image uploaded by the user. The code of the handle method is pretty straightforward—we retrieve an image from the ImageModel model and create a thumbnail using the Intervention Image library. Of course, we need to pass the corresponding Image model when we dispatch our job, and we'll see it in a moment.

To test our newly created job, we'll create a simple upload form that allows the user to upload an image. Of course, we won't create image thumbnails right away; we'll defer that task so that it could be processed by the queue worker.

Let's create a controller file at app/Http/Controllers/ImageController.php as shown below.

<?php namespace App\Http\Controllers; use App\Image; use App\Jobs\ProcessImageThumbnails; use Illuminate\Http\Request; use Illuminate\Support\Facades\Redirect; use App\Http\Controllers\Controller; use Validator; class ImageController extends Controller { /** * Show Upload Form * * @param Request $request * @return Response */ public function index(Request $request) { return view('upload_form'); } /** * Upload Image * * @param Request $request * @return Response */ public function upload(Request $request) { // upload image $this->validate($request, [ 'demo_image' => 'required|image|mimes:jpeg,png,jpg,gif,svg|max:2048', ]); $image = $request->file('demo_image'); $input['demo_image'] = time().'.'.$image->getClientOriginalExtension(); $destinationPath = public_path('/images'); $image->move($destinationPath, $input['demo_image']); // make db entry of that image $image = new Image; $image->org_path = 'images' . DIRECTORY_SEPARATOR . $input['demo_image']; $image->save(); // defer the processing of the image thumbnails ProcessImageThumbnails::dispatch($image); return Redirect::to('image/index')->with('message', 'Image uploaded successfully!'); } }

Let's create an associated view file at resources/views/upload_form.blade.php.

<!DOCTYPE html> <html lang="{{ config('app.locale') }}"> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1"> <meta name="csrf-token" content="{{ csrf_token() }}" /> <title>Laravel</title> <!-- Fonts --> <link href="https://fonts.googleapis.com/css?family=Raleway:100,600" rel="stylesheet" type="text/css"> <!-- Styles --> <style> html, body { background-color: #fff; color: #636b6f; font-family: 'Raleway', sans-serif; font-weight: 100; height: 100vh; margin: 0; } .full-height { height: 100vh; } .flex-center { align-items: center; display: flex; justify-content: center; } .position-ref { position: relative; } .top-right { position: absolute; right: 10px; top: 18px; } .content { text-align: center; } .title { font-size: 84px; } .links > a { color: #636b6f; padding: 0 25px; font-size: 12px; font-weight: 600; letter-spacing: .1rem; text-decoration: none; text-transform: uppercase; } .m-b-md { margin-bottom: 30px; } .alert { color: red; font-weight: bold; margin: 10px; } .success { color: blue; font-weight: bold; margin: 10px; } </style> </head> <body> <div class="flex-center position-ref full-height"> @if (Route::has('login')) <div class="top-right links"> @if (Auth::check()) <a href="{{ url('/home') }}">Home</a> @else <a href="{{ url('/login') }}">Login</a> <a href="{{ url('/register') }}">Register</a> @endif </div> @endif <div class="content"> <div class="m-b-md"> <h1 class="title">Demo Upload Form</h1> @if ($errors->any()) <div class="alert alert-danger"> <ul> @foreach ($errors->all() as $error) <li>{{ $error }}</li> @endforeach </ul> </div> @endif @if (session('message')) <div class="success"> {{ session('message') }} </div> @endif <form method="post" action="{{ url('/image/upload') }}" enctype="multipart/form-data"> <div> <input type="file" name="demo_image" /> </div> <br/> <div> <input type="hidden" name="_token" value="{{ csrf_token() }}"> <input type="submit" value="Upload Image"/> </div> </form> </div> </div> </div> </body> </html>

Finally, let's add routes for the index and upload actions in the routes/web.php file.

Route::get('image/index', 'ImageController@index'); Route::post('image/upload', 'ImageController@upload');

In the ImageController controller, the index method is used to render an upload form.

public function index(Request $request) { return view('upload_form'); }

When the user submits a form, the upload method is invoked.

public function upload(Request $request) { // upload image $this->validate($request, [ 'demo_image' => 'required|image|mimes:jpeg,png,jpg,gif,svg|max:2048', ]); $image = $request->file('demo_image'); $input['demo_image'] = time().'.'.$image->getClientOriginalExtension(); $destinationPath = public_path('/images'); $image->move($destinationPath, $input['demo_image']); // make db entry of that image $image = new Image; $image->org_path = 'images' . DIRECTORY_SEPARATOR . $input['demo_image']; $image->save(); // defer the processing of the image thumbnails ProcessImageThumbnails::dispatch($image); return Redirect::to('image/index')->with('message', 'Image uploaded successfully!'); }

At the beginning of the upload method, you'll notice the usual file upload code that moves the uploaded file to the public/images directory. Next, we insert a database record using the App/Image model.

Finally, we use the ProcessImageThumbnails job to defer the thumbnail processing task. It's important to note that it's the dispatch method that's used to defer a task. At the end, the user is redirected to the upload page with a success message.

At this point in time, the job is added to the jobs table for processing. Let's confirm it by issuing the following query.

mysql> select * FROM lvl_jobs; | 1 | default | {"displayName":"App\\Jobs\\ProcessImageThumbnails","job":"Illuminate\\Queue\\CallQueuedHandler@call","maxTries":null,"timeout":null,"data":{"commandName":"App\\Jobs\\ProcessImageThumbnails","command":"O:31:\"App\\Jobs\\ProcessImageThumbnails\":5:{s:8:\"\u0000*\u0000image\";O:45:\"Illuminate\\Contracts\\Database\\ModelIdentifier\":2:{s:5:\"class\";s:9:\"App\\Image\";s:2:\"id\";i:2;}s:6:\"\u0000*\u0000job\";N;s:10:\"connection\";N;s:5:\"queue\";N;s:5:\"delay\";N;}"}} | 0 | NULL | 1510219099 | 1510219099 |

You must be wondering, what does it take to process a job then? Don't worry—that's what we're going to discuss in the very next section.

Queue Worker

The job of the Laravel queue worker is to process jobs that are queued up for processing. In fact, there's an artisan command that helps us to start the queue worker process.

$php artisan queue:work

As soon as you run that command, it processes pending jobs. In our case, it should process the ProcessImageThumbnails job that was queued up when the user uploaded an image earlier.

$php artisan queue:work [YYYY-MM-DD HHMMSS] Processing: App\Jobs\ProcessImageThumbnails [YYYY-MM-DD HHMMSS] Processed: App\Jobs\ProcessImageThumbnails

You would have noticed that when you start a queue worker, it keeps running until you kill it manually or close the terminal. In fact, it's waiting for the next job to be processed. As soon as there's a new job in the queue, it'll be processed right away if the queue worker is running.

Of course, we can't keep it running that way, so we need to find a way for the queue worker to run permanently in the background.

To our rescue, there are several process management tools out there you could choose from. To name a few, here's a list:

  • Circus
  • daemontools
  • Monit
  • Supervisor
  • Upstart

You should choose a tool that you're comfortable with to manage the Laravel queue worker. Basically, we want to make sure that the queue worker should run indefinitely so that it processes queued jobs right away.

So that's the Queue API at your disposal. You can use it in your day-to-day development to defer time-consuming tasks for the betterment of the end user experience.

Conclusion

In this article, we discussed the Queue API in Laravel, which is really helpful should you wish to defer processing of resource-consuming tasks.

We started with a basic introduction to the Queue API, which involved a discussion of connections, queues, and jobs. In the second half of the article, we created a custom queue job that demonstrated how you could use the Queue API in the real world.

For those of you who are either just getting started with Laravel or looking to expand your knowledge, site, or application with extensions, we have a variety of things you can study in Envato Market.

Feel free to use the feedback form below to post your queries and suggestions.

Categories: Web Design

50 Plugins to Improve Your WordPress E-Commerce Site

Who Is Hosting This Feed - Mon, 12/18/2017 - 05:00

Running an e-commerce website can be hard. It’s necessary to be aware of all the ways you can make it easy for your customers to find what they’re looking for and make purchases. Although there are various e-commerce providers out there, building a store on WordPress gives you access to its countless themes and plugins, […]

The post 50 Plugins to Improve Your WordPress E-Commerce Site appeared first on Who Is Hosting This: The Blog.

Categories: Web Design

Pages