In a prior discussion we looked at how to set up a project so that we could develop an Apache Cordova application using HTML5 and JavaScript. In that section we mostly covered how to set up, build, and run the project — which consisted of the same application in the www folder that Apache Crodova bootstraps when you create a new project. In what follows we will look at the approach for actually writing own code for our app and will look at how an app in Apache Cordova gets initialized. We will also look at how we can extend the Apache Cordova platform by using plugins to give ourselves additional features and functionality that will make for an all around better user-experience (UX) for the users of our app.
Now that we have our project set up and all our platforms added all that we have left to do now is create our application by creating what basically amounts to a website that runs HTML and JavaScript in the “www” folder. How should one develop for Apache Cordova? Personally, I would delete all of the boilerplate files and folders and start from scratch. That is what we will do here. Just take a quick note of how things are referenced in the index.html file and do the same for your own files.
In doing this, I have modified the index.html file in the “www” folder to the following…
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Security-Policy" content="default-src 'self' data: gap: https://ssl.gstatic.com 'unsafe-eval'; style-src 'self' 'unsafe-inline'; media-src *">
<meta name="format-detection" content="telephone=no">
<meta name="msapplication-tap-highlight" content="no">
<meta name="viewport" content="user-scalable=no, initial-scale=1, maximum-scale=1, minimum-scale=1, width=device-width">
<link rel="stylesheet" type="text/css" href="css/index.css">
<title>Cordova Application</title>
</head>
<body>
<div id="main">Initializing...</div>
<script type="text/javascript" src="cordova.js"></script>
<script type="text/javascript" src="js/index.js"></script>
</body>
</html>
Note: Do not worry about that “cordova.js” reference or the fact that this file is nowhere to be found in our “www” folder. Apache Cordova will utilize this in the proper context when the app runs (so leave it in there).
So as far as the index.html goes, there is nothing too fancy. I have a css file (index.css) and a js file (index.js). That is all you need to get started.
Next, let’s look at our JavaScript in the index.js file. There is really only one thing you need to make note of when you develop Apache Cordova applications in JavaScript. There is a special event that Apache Cordova uses to tell the platform that the everything is loaded and the device you are using is ready to start running JavaScript in your Cordova application. This is what is known as the “deviceready” event. It only fires when you are running an app within a Cordova context (i.e. on a device or an emulator of a device). In a lean version of JavaScript for a cordova application would look like the following (in index.js)…
var app = {
init: function() {
document.addEventListener('deviceready', this.main, false);
},
main: function() {
document.getElementById('main').innerText = 'App is ready...'
}
};
app.init();
Here we are calling the “init” function which will add a listener for the “deviceready” event. When this event fires the “main” function will run, which in this case just changes the inner text of a div element So if we run this using
$ cordova emulate android
or
$ cordova emulate ios
from the root of our project we will see our device boot up, our app launch, and if all goes well we will see the text “App is ready…” so we know that our event is firing.
Read More »
Obviously at the time of this writing in the 2nd decade of the 21st century, you are no doubt well acquainted with the immense proliferation and impact that mobile apps have had in and on our world. It was not long ago that we were all sitting at our computers at our desks for the large majority of the time we spent in our various avenues of technological communications over the Internet — complete with our with our giant monitors, whirring computer fans, buzzing drives, and the garbled noise of dial-up modems. Now, mobile phones and tablets probably make up as much, if not more, of our time spent working, playing, and communicating online. Everyone has a ~$100 to $600 smartphone (i.e. computer) in their pocket. And with this rise of mobile, apps found on the popular stores — like Apple’s iOS App Store, Google Play (Android), Amazon and a host of others — have completely transformed the way that we do anything and everything because well, there is an app for anything and everything. Every single facet of life probably has an app to manage some aspect of it. Need to remember to breathe? There is an app for that! Yeah, that is a joke (probably)… but there are plenty of “real” apps out there (e.g. iBeer) that are just as pointless. Fun and goofy, yes, but pointless. And they all post their pointlessness to Facebook and/or Twitter.
Whether you want to develop an app to manage some minute aspect of life or just create a fun game, or whatever else, you can download the SDK for the platform(s) that you want to release your app on, do some tutorials, and start building. That’s all well and good, but if you want to port your application to another platform (e.g. release an iOS app also for Android), you will essentially have to try rebuild the same app using the languages in tools of a different platform. For example, iOS apps for iPhone and iPad have traditionally been developed on a Mac in the Xcode IDE using the Objective-C programming language (though Apple has recently released a new language called Swift that can also be used to build iOS apps). Android apps, by contrast are built using Java and Eclipse or the more recently released Android Studio. Native Windows Phone apps are built using C# and XAML in Visual Studio. Other platforms have their own setups. If you want to take this approach you definitely can, but it should be fairly apparent that developing and maintaining a number of different codebases for multiple platforms quickly adds up to a lot of time, effort, and often money as the sizes and complexity of your apps increase.
At the same time as the rise of mobile in the past decade, something else has occurred: the rise of HTML5 and JavaScript web applications. Beginning at around 2009 – 2010 one of the more noticeable developments was the rise of websites and web applications making use of more open technologies such as HTML5 and JavaScript to bring interactivity and 2-way communication between clients (usually browsers) and servers. With Flash on the way out due its proprietary nature, resource hogging, security issues, poor SEO — along with its being snubbed by Apple for support on iPhones and iPads for basically all these reasons — meant that something had to fill the void. HTML5 and JavaScript moved into this space and developers started turning to it for creating interactive “app-like” experiences.
Wouldn’t it be awesome if there were a way to write a single application in HTML and JavaScript with a single codebase and have a way to port this application to all of the different mobile platforms? I am so glad you asked.
Apache Cordova — also commonly known as “PhoneGap” (the only difference between the two is propriety) — allows us combine combine these open technologies together with the SDKs of the various mobile application platforms to make native mobile applications using technologies such as HTML and JavaScript. You can basically create a small static HTML and JavaScript website or web application and this code will be imported into native iOS, Android, Windows Phone projects and configured specifically for the respective platforms. Thus, you *do* still have to have the SDK of the platform installed to build, run, and release the apps. So to create an iOS app you will still need a Mac and Xcode. To create Android apps you will need to install the Android SDK (which comes with the Android Studio IDE). If you don’t want to mess around with Android Studio, you can just try downloading the old standalone SDK tools here and updating from there. But the important aspect of using Cordova is that the HTML and JavaScript that each project will pull in and build will be the same across all platforms. Want to release an update with some slick new features or fix some bugs that have been reported by your users? You need only change your code in your HTML and JavaScript. You don’t have to try and rewrite the same code and/or functionality in a different language on each platform. From there all you need to do is run a few simple commands from the command lines and your HTML and JavaScript will get built and converted into an application that can run on the platform(s) you are targeting.
In what follows we will explore what it looks like to use Cordova to create a mobile application in HTML and JavaScript that can run on a number of different platform. For our examples, we will build our app for iOS and Android, but the process is essentially the same for building for other platforms (e.g. Microsoft Windows Phone, Amazon Kindle Fire). You would just need to download the SDKs for those platforms if you wanted to run your app on those types of devices as well.
Read More »
One of the more common ways that you see collections of items displayed on the web are tile based layouts. Usually these tiles will consist of a container with an image and some sort of descriptive text below the image or as an overlay. Accomplishing this sort of layout in HTML and CSS is not particularly difficult but in some scenarios there are some interesting challenges to tackle, especially when it comes to responsive views. We will explore some of these in what follows.
Certainly in doing a layout of tiles you could use the grid of a CSS framework like Bootstrap or Foundation to put each individual tile into a grid column. But there are, shall we say, annoyances that come with trying to do this. For one thing, because Bootstrap is on a system of rows and grids you will have to count the number of items as they come back to figure out when to close out one row and start a new one. For example, if you wanted a two column grid of items and you were returning markup from the server you would have close out the Bootstrap row on every second item. We’ll be using PHP in our example. I do realize that normally in a production-grade app you would not (or should not) mix this UI content with your server sided logic like we do below. You’d probably use a templating engine of some sort. But this is just an example for the purposes of illustration… and developers do mix these two components together at times as I am sure you are probably aware.
So let’s say we have an associative array $data that has a “text” property as one of its keys. We could print the value of each item in our set in a Bootstrap grid layout like so…
$count = 0;
foreach ($data as $item) {
if($count == 0) {
$markup .= '<div class="row">';
}
$markup .= '<div class="col-md-6">'. $item["text"] .'</div>';
if ($count++ %2 == 0) {
$markup .= '</div>'
$count = 0;
}
}
Which might give us something like what we see here.
This works but it seems a bit awkward and weird. Because we are using a 2 column grid we have to count every other item and close out the row before starting a new row. If we wanted a 3 column grid we’d have to count every 3 items and so on. This might work okay in some scenarios, but in others we may not have the luxury of being able to use the Bootstrap grid with ease and consistency. What if, say, these results that we currently have could also be appended to via AJAX calls? You see a lot of this sort of thing on sites like Pinterest or Instagram and their infinite scrolling capabilities. As you scroll to the bottom more content gets loaded dynamically from the server from client side calls made in JavaScript.
The point is if you use Bootstrap and want to keep the layout consistent you’re going to have to always be keeping track of how many items you have and where you are in the Bootstrap row closing and opening phase. It’ gets a bit messy and awkward to maintain as functionality gets a bit more dynamic and complex. There probably is, for lack of a better term, a “cleaner” implementation we can take a look at.
Read More »
If you have been doing anything with front-end web development since ca. 2010 you will have no doubt come across the concept of responsive web development and along with it, responsive grids. Responsive grids are great and, as of early 2015, have become completely ubiquitous across the Internet. Whether you are using Twitter Bootstrap or ZURB Foundation or any one of the numerous lesser-known responsive grid systems they all provide a nice way to clreate flexible fluid web layouts that display well on all devices.
Fluid responsive grids are not without their drawbacks, however, Their structure tends to bring about some challenges in doing some more complex positioning of content. For example, if one column in a group of columns placed next to each other in a row has more content than adjacent columns, you can have some unwanted effects in your layout. For example, in the example below (using Twitter Bootstrap), we can see that with more content in the right column the left column will get pushed down.
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<title>Responsive Grid Rowspan</title>
<link rel="stylesheet" type="text/css" href="css/style1.css" />
</head>
<body>
<div class="row">
<div class="col-lg-8">
<div class="inner">
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras ut justo vel ante fringilla accumsan quis et est. In euismod convallis porta. Mauris condimentum sapien erat, et scelerisque velit dapibus ut. Cras et blandit justo. In laoreet sapien et nulla bibendum, ac fermentum massa lacinia. Etiam ornare est lectus, et posuere velit elementum sed. Fusce sed felis ante. Integer consequat bibendum mi ut porta. Nulla quis egestas est.</p>
</div>
</div>
<div class="col-lg-4">
<div class="inner" style="background:#999;">
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras ut justo vel ante fringilla accumsan quis et est. In euismod convallis porta. Mauris condimentum sapien erat, et scelerisque velit dapibus ut. Cras et blandit justo. In laoreet sapien et nulla bibendum, ac fermentum massa lacinia. Etiam ornare est lectus, et posuere velit elementum sed. Fusce sed felis ante. Integer consequat bibendum mi ut porta. Nulla quis egestas est.</p>
<p>Duis ac risus congue, interdum felis sed, maximus ligula. Aenean mollis convallis libero, non efficitur justo blandit vel. Proin ultrices orci massa, vel pharetra ex convallis in. Mauris fringilla ullamcorper nibh a auctor. In consectetur justo sed tellus iaculis, in vehicula nibh sodales. Nullam tincidunt dignissim odio at vestibulum. Nullam in eros nisl. In vel arcu quis lacus pellentesque rhoncus. Suspendisse quis diam auctor, maximus odio sed, malesuada nulla. Duis rhoncus lorem elit, hendrerit volutpat eros suscipit ac. Cras id magna dui. Donec sit amet massa non libero malesuada sodales sit amet sed sapien. Praesent in arcu ut quam faucibus vehicula non at ligula.</p>
</div>
</div>
</div>
<div class="row">
<div class="col-lg-8">
<div class="inner">
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras ut justo vel ante fringilla accumsan quis et est. In euismod convallis porta. Mauris condimentum sapien erat, et scelerisque velit dapibus ut. Cras et blandit justo. In laoreet sapien et nulla bibendum, ac fermentum massa lacinia. Etiam ornare est lectus, et posuere velit elementum sed. Fusce sed felis ante. Integer consequat bibendum mi ut porta. Nulla quis egestas est.</p>
<p>Duis ac risus congue, interdum felis sed, maximus ligula. Aenean mollis convallis libero, non efficitur justo blandit vel. Proin ultrices orci massa, vel pharetra ex convallis in. Mauris fringilla ullamcorper nibh a auctor. In consectetur justo sed tellus iaculis, in vehicula nibh sodales. Nullam tincidunt dignissim odio at vestibulum. Nullam in eros nisl. In vel arcu quis lacus pellentesque rhoncus. Suspendisse quis diam auctor, maximus odio sed, malesuada nulla. Duis rhoncus lorem elit, hendrerit volutpat eros suscipit ac. Cras id magna dui. Donec sit amet massa non libero malesuada sodales sit amet sed sapien. Praesent in arcu ut quam faucibus vehicula non at ligula.</p>
</div>
</div>
<div class="col-lg-4">
<div class="inner">
<p>Duis ac risus congue, interdum felis sed, maximus ligula. Aenean mollis convallis libero, non efficitur justo blandit vel. Proin ultrices orci massa, vel pharetra ex convallis in. Mauris fringilla ullamcorper nibh a auctor. In consectetur justo sed tellus iaculis, in vehicula nibh sodales. Nullam tincidunt dignissim odio at vestibulum. Nullam in eros nisl. In vel arcu quis lacus pellentesque rhoncus. Suspendisse quis diam auctor, maximus odio sed, malesuada nulla. Duis rhoncus lorem elit, hendrerit volutpat eros suscipit ac. Cras id magna dui. Donec sit amet massa non libero malesuada sodales sit amet sed sapien. Praesent in arcu ut quam faucibus vehicula non at ligula.</p>
</div>
</div>
</div>
</body>
</html>
It would be great if we could have sort of a “rowspan” effect where we could fit the content nicely together. Fortunately, with a little reordering of the columns and floating the column right, this can be done in an elegant CSS only manner. We’ll move the grid in the second row into the same row as our column with a lot of content. From there we can apply a float:right to the second column.
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<title>Responsive Grid Rowspan</title>
<link rel="stylesheet" type="text/css" href="css/style1.css" />
</head>
<body>
<div class="row">
<div class="col-lg-8">
<div class="inner">
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras ut justo vel ante fringilla accumsan quis et est. In euismod convallis porta. Mauris condimentum sapien erat, et scelerisque velit dapibus ut. Cras et blandit justo. In laoreet sapien et nulla bibendum, ac fermentum massa lacinia. Etiam ornare est lectus, et posuere velit elementum sed. Fusce sed felis ante. Integer consequat bibendum mi ut porta. Nulla quis egestas est.</p>
</div>
</div>
<div class="col-lg-4 rowspan">
<div class="inner" style="background:#999;">
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras ut justo vel ante fringilla accumsan quis et est. In euismod convallis porta. Mauris condimentum sapien erat, et scelerisque velit dapibus ut. Cras et blandit justo. In laoreet sapien et nulla bibendum, ac fermentum massa lacinia. Etiam ornare est lectus, et posuere velit elementum sed. Fusce sed felis ante. Integer consequat bibendum mi ut porta. Nulla quis egestas est.</p>
<p>Duis ac risus congue, interdum felis sed, maximus ligula. Aenean mollis convallis libero, non efficitur justo blandit vel. Proin ultrices orci massa, vel pharetra ex convallis in. Mauris fringilla ullamcorper nibh a auctor. In consectetur justo sed tellus iaculis, in vehicula nibh sodales. Nullam tincidunt dignissim odio at vestibulum. Nullam in eros nisl. In vel arcu quis lacus pellentesque rhoncus. Suspendisse quis diam auctor, maximus odio sed, malesuada nulla. Duis rhoncus lorem elit, hendrerit volutpat eros suscipit ac. Cras id magna dui. Donec sit amet massa non libero malesuada sodales sit amet sed sapien. Praesent in arcu ut quam faucibus vehicula non at ligula.</p>
</div>
</div>
<div class="col-lg-8">
<div class="inner">
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras ut justo vel ante fringilla accumsan quis et est. In euismod convallis porta. Mauris condimentum sapien erat, et scelerisque velit dapibus ut. Cras et blandit justo. In laoreet sapien et nulla bibendum, ac fermentum massa lacinia. Etiam ornare est lectus, et posuere velit elementum sed. Fusce sed felis ante. Integer consequat bibendum mi ut porta. Nulla quis egestas est.</p>
<p>Duis ac risus congue, interdum felis sed, maximus ligula. Aenean mollis convallis libero, non efficitur justo blandit vel. Proin ultrices orci massa, vel pharetra ex convallis in. Mauris fringilla ullamcorper nibh a auctor. In consectetur justo sed tellus iaculis, in vehicula nibh sodales. Nullam tincidunt dignissim odio at vestibulum. Nullam in eros nisl. In vel arcu quis lacus pellentesque rhoncus. Suspendisse quis diam auctor, maximus odio sed, malesuada nulla. Duis rhoncus lorem elit, hendrerit volutpat eros suscipit ac. Cras id magna dui. Donec sit amet massa non libero malesuada sodales sit amet sed sapien. Praesent in arcu ut quam faucibus vehicula non at ligula.</p>
</div>
</div>
</div>
</body>
</html>
And there you have it. With a little bit of finagling, you can get slightly more interesting layouts with a grid. You can see the result of this here…
View Demo »
In this post I am going to show you how to create an accordion that will slide down on click using CSS and jQuery. There are a lot of tutorials out there that will show you how to do something similar to this but what I like about this accordion is that it uses <div>’s of content rather than list items for each of the accordion sections. A lot of tutorials show how to make menu-style accordions but not necessarily ones for any content that you want. That’s what this aims to accomplish.
Before we start, I think I should mention that this accordion is not technically “responsive” in the sense that it has any media queries attached to it, only that the percentage-width based fluidity of it should allow you to fit it into any content area as the viewport resizes.
View Demo
It’s also going to be “vanilla” enough such that it’s not overstyled to the point where you’re going to have to undo a lot of the styling to fit the theme of your website (should you want to integrate it). It’s going to be fairly bland, boilerplate, and basic, but that’s always a good place to build from.
The width of the accordion is going to be percentage based so that it should adapt well for responsive designs as well.
So start and we’re going to lay out our basic structure in the HTML….
<div class="accordion">
<div class="accordionHeader"><span>One</span></div>
<div class="accordionContent">Mauris quis tellus sed mi bibendum vulputate. Nam nec fermentum leo. Donec ante nisl, varius nec scelerisque nec, pulvinar id ipsum. Phasellus sodales tellus quis odio tincidunt quis feugiat sapien mollis. Ut hendrerit nisl eu turpis mattis sit amet accumsan ante pretium.
</div>
<div class="accordionHeader"><span>Two</span></div>
<div class="accordionContent">Vestibulum neque justo, rutrum eu interdum sed, aliquam sit amet nulla. Pellentesque ultricies enim sit amet urna fringilla venenatis. Etiam eleifend dolor ut felis sagittis quis dignissim neque venenatis. In posuere tempus sodales. Aliquam tellus ante, posuere vitae congue at, tempus sed dolor. Etiam ac urna leo, at pellentesque augue osuere vitae congue at. Imperdiet ac euismod leo viverra. Maecenas convallis, lectus sit amet eleifend vehicula, sapien sem pretium dolor, in tincidunt est sapien eget orci. Sed vel libero urna. Aliquam ornare sodales egestas. Duis feugiat vulputate libero id tempor. Pellentesque elementum molestie nisi ac elementum
</div>
<div class="accordionHeader"><span>Three</span></div>
<div class="accordionContent">Nunc elit nisl, vestibulum ac laoreet nec, cursus sed leo. Aenean sit amet nibh justo. Quisque dui arcu, pharetra non sollicitudin nec, rhoncus at ligula. Etiam placerat porttitor adipiscing. Aenean fermentum nulla a justo malesuada id pulvinar urna sagittis. Morbi urna orci, faucibus sed sollicitudin sit amet, faucibus dictum massa. In sit amet enim at nisi rutrum vulputate. Vestibulum quis mattis nulla. Duis viverra orci ut enim tincidunt auctor. Ut molestie eros eget mauris consectetur eget tristique arcu elementum. </div>
<div class="accordionHeader"><span>Four</span></div>
<div class="accordionContent">Nulla sollicitudin laoreet nulla quis suscipit. Curabitur tristique, dolor vel condimentum molestie, purus leo sodales enim, ac vehicula sem est eget eros. Sed vehicula, metus vel convallis tempus, mauris lorem tristique ipsum, ac condimentum arcu tellus vel nisi. Aliquam mauris est, adipiscing a pharetra ut, molestie egestas mi. Fusce vulputate blandit sagittis. Praesent eget dignissim felis. Integer ac libero eu felis congue cursus. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Fusce vel dui a sapien posuere consequat in quis mi. Proin eros nisi, lacinia id tempus id, congue eget justo. Proin ac justo non mi pretium vehicula sed id odio. Vivamus felis nibh, facilisis ut adipiscing at, blandit vitae magna. Praesent tellus est, molestie ut elementum at, pretium nec eros. Etiam diam nisl, varius non gravida eu, facilisis eu nunc.
</div>
Seems straightforward enough. We’ve basically just defined a header item for the accordion titles and a content section for each wrapped into a wrapper <div> with the class “accordion”…
With that out of the way, we can give it a little bit of styling using CSS…
.accordion .accordionHeader {
display: block;
background: #eee;
background: #eeeeee -moz-linear-gradient(top, #fcfcfc 0%, #eeeeee 100%);
background: #eeeeee -webkit-linear-gradient(top, #fcfcfc 0%, #eeeeee 100%);
background: #eeeeee -o-linear-gradient(top, #fcfcfc 0%, #eeeeee 100%);
background: #eeeeee -ms-linear-gradient(top, #fcfcfc 0%, #eeeeee 100%);
background: #eeeeee linear-gradient(top, #fcfcfc 0%, #eeeeee 100%);
border: 1px solid #ccc;
border-radius: 3px;
-moz-border-radius: 3px;
-webkit-border-radius: 3px;
padding: 10px;
font-size: 16px;
font-weight: normal;
cursor: pointer;
margin-bottom: 10px;
}
.accordion .accordionHeader span {
background: url(images/plus.png) center left no-repeat;
padding-left: 30px;
}
.accordion .accordionHeader:hover {
background: #fcfcfc;
}
.accordion .activeItem span {
background: url(images/minus.png) center left no-repeat;
}
.accordion .accordionContent {
margin-bottom: 10px;
}
And lastly we can bring it to life with jQuery…
$(document).ready(function () {
var nbsAccordionSliding = false;
$('.accordion').find('.accordionHeader').click(function() {
if(!nbsAccordionSliding) {
nbsAccordionSliding = true;
$(this).toggleClass('activeItem')
$(this).next().slideToggle({duration: 300, queue: false, easing: 'linear', complete: function() {
nbsAccordionSliding = false;
}});
}
}).next().hide();
});
UPDATE: What if you wanted to have everything collapse and only show one at a time. To do that, you’ll want to replace the $(document).ready code block with the following…
$(document).ready(function () {
var nbsAccordionSliding = false;
$('.accordion').find('.accordionHeader').click(function() {
$('.accordionHeader').removeClass('activeItem');
$(this).addClass('activeItem');
if(!nbsAccordionSliding) {
nbsAccordionSliding = true;
if($(this).next().is(':visible')){
$(this).next().slideUp(function(){
nbsAccordionSliding = false;
});
}
else {
$('.accordion').find('.accordionHeader').next().slideUp();
$(this).next().slideToggle({duration: 300, queue: false, easing: 'linear', complete: function() {
nbsAccordionSliding = false;
}});
}
}
}).next().hide();
});
Click below to view the demo of the final finished product. If you like what you see, you can download the files and use them wherever you like 🙂
View Demo Download Files