Tag Archives: KnockoutJS

Part 3: KO Components – Routes and Hashes

Part 1: Dipping your feet into Knockout JS Components
Part 2: Knockout Components – Separating Templates from View Model

As we continue our journey to learn more about KO Components, today we look at how we can  navigate around different ‘views’ and manage hyperlinks.

There are multiple libraries out there that allow you to do this. Today we’ll see how to use Crossroads for routing and Hasher for managing URLs. They internally use the Signals JS library. All three are written by Miller Medeiros. Now you could do all things these three libraries to with Sammy.js too. I will probably look at Sammy.js at some point in future, but Sammy is more opinionated on how it does routing and event handling, while I wanted to go one level lower and fiddle around myself. BTW I am in no way promoting one over the other, just that today’s sample uses Crossroads, Hasher and Signals.

Adding dependencies

All three libraries are not available as Nuget packages so we’ve to get them from their Github Repos directly. I have linked to the repos above.

Apart from the above three we will also use knockout-projections extension library by Steve Sanderson. This provides helper methods to deal with KO arrays.

I have downloaded them and added to the solution resulting in the following folder layout:

image
Figure 1

Updating require.config.js

We update the require.config.js to add the additional references so Require knows where to get them from as and when required.

var require = {
baseUrl: “/”,
paths: {
“bootstrap”: “Scripts/bootstrap/bootstrap”,
“crossroads”: “Scripts/crossroads/crossroads”,
“jquery”: “Scripts/jquery/jquery-1.9.0”,
“knockout”: “Scripts/knockout/knockout-3.2.0beta.debug”,
“knockout-projections”: “Scripts/knockout/knockout-projections.min”,
“signals”: “Scripts/crossroads/signals”,
“hasher”: “Scripts/crossroads/hasher”,
“text”: “Scripts/require/text”
},
shim: {
“bootstrap”: {
deps: [“jquery”]
}
}
}

Restructuring the App layout and adding a page

Since we are going to demo navigation, it’s good to have at least one more page to navigate to. So we’ll introduce a loosely coupled concept of ‘page-components’. These are basically registered as ko.components but they are containers and in turn use other ko components.

As I said in my previous article the folder structure I was using is pretty arbitrary and open to updates.

Under App we will add a pages folder which will have all our ‘page’ components. I have added two, home and settings.

image
Figure 2

The home page-component

The Home page component has the standard HTML + JS structure. I have in-fact taken out the greeter instances from Index.html. We’ll see how we can pass data between two components. We’ll add a collection of ‘guests’ in home view model which will be passed to the greeter component. So our home.js will be as follows:

define([“knockout”, “text!./home.html”], function (ko, homeTemplate) {
function homeViewModel(params) {
var self = this;
self.title = ko.observable(‘Dipping your feet into KnockoutJS’);
self.guests = ko.observableArray([]);
self.guests.push({ guestName: “Sumit” });
self.guests.push({ guestName: “Optimus” });
self.guests.push({ guestName: “Bumblebee” });
return self;
}
return { viewModel: homeViewModel, template: homeTemplate };
});

We have put the header text in a property called title. We also have an observable array of guests who the greeter component needs to greet. Instead of hard-coding the names this could have come from a server API call.

The home.html is as follows

<h2 data-bind=”text: title”></h2>
<hr />
<!– ko foreach: guests –>
<greeter params=’name: guestName’></greeter>
<!– /ko –>
<pre data-bind=”text: ko.toJSON($data, null, 5)”></pre>

We have bound the title to the header element.

Next we have a standard ko foreach that loops through each element in guests collection. The params attribute takes a JSON snippet so we pass it appropriately as name: guestName. KO can evaluate the observable and pass the appropriate value to the greeter component.

Setting up Routing using Crossroads and Hasher

In Figure 2 above you’ll note we have a new file called router.js.

The Router is defined as an AMD module. It takes in an object with the property routes that has an array of routes that are ‘registered’. So the routes property is going to hold all our routes.

As of now we have defined two routes, one is the home page that is at the root of the site and the second is the settings page that should be at the /settings URL.

When the module is initialized the Router function is invoked (acts as the ‘constructor’) with the routes defined. These are added to crossroads. I have added a method to log every routing event to the console.

The activateCrossroads function sets up Hasher to listen for hash changes and on change invoke crossroads to do the routing.

/// <reference path=”/Scripts/crossroads/crossroads.js” />
define([“jquery”,”knockout”, “crossroads”, “hasher”], function ($, ko, crossroads, hasher) {

    return new Router({
routes: [
{ url: ”, params: { page: ‘home’ } },
{ url: ‘settings’, params: { page: ‘settings’ } }
]
});

    function Router(config) {
var currentRoute = this.currentRoute = ko.observable({});

        ko.utils.arrayForEach(config.routes, function (route)
{
crossroads.addRoute(route.url, function (requestParams)
{
currentRoute(ko.utils.extend(requestParams, route.params));
});
});
crossroads.routed.add(console.log, console);
activateCrossroads();
}

    function activateCrossroads() {
function parseHash(newHash, oldHash){
crossroads.parse(newHash);
}
        crossroads.normalizeFn = crossroads.NORM_AS_OBJECT;

        hasher.initialized.add(parseHash);
hasher.changed.add(parseHash);
hasher.init();
}
});

With routing all set, let’s setup the Index page and register the new components before we can test out our changes.

Updating the Index.html page

The Index page has now become a nearly empty shell. We will add two links in the header, one for Home and the other for Settings page.

<div class=”navbar navbar-inverse navbar-fixed-top”>
<div class=”container”>
<div class=”navbar-header”>
<button type=”button” class=”navbar-toggle” data-toggle=”collapse” data-target=”.navbar-collapse”>
<span class=”icon-bar”></span>
<span class=”icon-bar”></span>
<span class=”icon-bar”></span>
</button>
<a class=”navbar-brand” href=”/”>KO Components</a>
<ul class=”nav navbar-nav”>
<li>
<a href=”#”>Home</a>
                </li>
<li>
<a href=”#settings”>Settings</a>
                </li>
</ul>
</div>
</div>
</div>
<div id=”page” class=”container” style=”padding-top:50px” data-bind=”component: { name: route().page, params: route }”></div>


By default the page will land at the Home page and when user clicks on Settings the routing library will take it to the Settings page (or back to home page depending on the link clicked).

The div with id=page is our equivalent of RenderBody in MVC. The current page as defined by the route with be displayed here. As you can see it is using a div to bind any component that is presented to it by the router. If you remember we have setup two routes with page names home and settings. So these are the names of our home and page components. Let’s register them in startup.js.

Registering new components

We’ll add the two new components to startup.js and also initialize our router and pass it to ko as root view model.

To initialize router we use Require’s module loading to request for it in the required collection. Note the syntax ./router. This is because router.js is not a part of the Scripts folder rather it is in the same folder as the startup.js and also the fact that it’s not defined in require.config.js.

Another difference to note is how we are setting up settings component. This is the way to setup HTML only components that have no Javascript associated with them.

The home component is registered like greeter as we had done before.

define([‘jquery’, ‘knockout’, ‘./router’, ‘bootstrap’, ‘knockout-projections’], function ($, ko, router) {
ko.components.register(‘greeter’, { require: ‘App/components/greeter/greeting’ });
ko.components.register(‘home’, { require: ‘App/pages/home/home’ });
    ko.components.register(‘settings’, {
        template: { require: ‘text!App/pages/settings/settings.html’ }
});
ko.applyBindings({ route: router.currentRoute });
});

With our components registered, we are all set to try it out.

Demo time

When we run the app, and see the Debug window, you will notice we have downloads the styles and templates that pertain to the Index page, the Home page and the greeter component. The Settings component has not been downloaded yet.

image

Now if you clear the Network activity window and click on Settings, you will note that only one file is downloaded and that is settings.html. This may seem insignificant for this demo, but has a huge impact when your applications grow big and have hundreds of components (yes, they can have 100s of components, just take my word for it Winking smile).

image

It is all the more fun to note that now if you switch back to Home page no components are called from the server because the browser has everything it needs, so unless you want to force refresh the page with data from server, navigating between pages is as fluid as a client app!

image

So we have navigation between pages and just in time loads. What about the dreaded browser Back button? Well, if you play around with it, you’ll notice back button works perfectly fine and crossroads is able to switch between views thanks to Hasher monitoring hash changes. Excellent, we could have stopped here and gone home happy but…!

Hashes in URLs, bot accessibility and best practices

If you were a observing keenly, you would have noticed that when we navigated to settings page the URL is /settings instead it is #settings. This is because we are using the age old # prefix to prevent the browser from hitting the server when someone clicks on a link. Now you realize what Hasher is doing. It’s listening to the hashchanged event and invoking crossroads (albeit in a cross browser compliant way).

This gives us a problem where our URLs are not semantic. This is a headache from bot accessibility because search robots don’t really ‘invoke’ AJAX calls to get new views when they encounter a # url. There is a nice series by Derick Bailey on drawbacks of hash URLs on Los Techies site.

As you will see from his articles, HTML5 pushState comes to the rescue to a large extent. I say large extent because once we get pushState into picture we have to start looking at the server side as well because if you don’t have # in your URL, bookmarked URLs will directly request the server to serve the URL e.g. the /settings page. In our case there is no /settings page only index.html that uses client side manipulation to get you to /settings URL. But fear not, we’ll work everything out.

Pushstate is important enough to warrant a separate article in itself. You can refer to Derick’s article for the basics, his sample is in Backbone.js and Rails. You should be able to grasp the idea, but either ways I will do it in KO and ASP.NET MVC.

Side note – Google search and Hashbangs ( #! )

Once AJAX apps became popular Google came up with a suggestion for appending a bang ( ! ) after the hash to make it apparent to search engines that the URL warranted an AJAX call, but after the initial rush to hashbang everything, the industry settled back into semantic URLs primarily because of problems associated with handling #! at the server and it’s non-standard nature.

Source Code

I have branched the master out part Part3 and it is available on Github at https://github.com/sumitkm/BuildingSpaUsingKO/tree/Part3

Tagged , , , ,

Knockout Components – Separating Templates from View Model

Part 1: Dipping your feet into Knockout JS Components

This is the second part in my Knockout JS Components series. So far we have made a simple ‘greeter’ component and used it multiple times. But our HTML template was rather simple and hard coded in the ViewModel as a string. That was fine for a small snippet but for involved templates you don’t want to stick an HTML as string. Rather you would like it to be an independent HTML that’s loaded as required.

Today we’ll see how we can separate the HTML and load it dynamically using another library called RequireJS and a plugin for it (RequireJS-Text).

If you want to follow along, you can get the source code branch for the previous article.

Quick intro to RequireJS

RequireJS is a library that is used for ‘Automatic Module Detection’ and loading of JavaScript modules and references. It was developed by James Burke from Mozilla. It is an open source project hosted on Github with a vibrant community that helps maintain it. It also has good documentation that you can refer to for getting started.

This article is not a RequireJS tutorial, instead we’ll jump right in and start using it, I’ll explain the syntax as we go along. If you have not used RequireJS before, well don’t panic, neither have I Smile.

Installing RequireJS and RequireJS-Text plugins

RequireJS has an official Nuget channel so getting the base library is easy to install via Nuget Package Manager Console, simply type in

install-package requirejs

Next we have to get the Text plugin from Github directly. You can either clone the repo from here https://github.com/requirejs/text or just download the JS file.

Once you have the file, add it to your scripts folder. I have started creating sub-folders for each library because it will come in handy later.

image

  • App/boot : This folder will contain scripts that initialize our libraries
  • App/components : This folder will contain all the components we create. Each component in turn has it’s own folder that may contain the ViewModel, HTML template and more.
  • Scripts/*: As mentioned earlier I’ve moved each library into it’s respective sub-folder under the Scripts folder. So Scripts is essentially for all libraries and frameworks that we will use (and not modify), and everything that we build will go under App.

NOTE: This folder structure is completely arbitrary. I ‘feel’ this works, you can use it, you can totally use your own structure. Just remember where your ‘root’ (folder) is Smile.

Now that we are done with the structure of the libs and sources let’s move on and configure RequireJS.

Configuring RequireJS

Under App/boot folder add a new JS file called require.configure.js. The name is, again, not a part of any convention, use what works for you, just refer it in Index.html correctly).

I have configured RequireJS initially as follows

var require = {
baseUrl: “/”,
paths: {
“bootstrap”: “Scripts/bootstrap/bootstrap”,
“jquery”: “Scripts/jquery/jquery-1.9.0”,
“knockout”: “Scripts/knockout/knockout-3.2.0beta.debug”,
“text”: “Scripts/require/text”
},
shim: {
“bootstrap”: {
deps: [“jquery”]
}
}
}

  • I’ve created a require global variable that has three properties, baseUrl, paths and shim.
  • The baseUrl property sets the root location with respect to which all other paths will be considered.
  • The paths property is assigned an object with name value pairs corresponding to the library names and their relative locations. Not the .js is stripped away from the paths.
  • The shim property provides additional dependency information. Here it shows bootstrap is dependent of jquery. The value ‘jquery’ matches the name used in ‘paths’ above.

Updating references

Now that we have configured RequireJS, technically all we need to do is load RequireJS using the configuration and all should be fine!

Well, let’s update the Index.html file to load RequireJS and remove all other Script references. We update the script references as follows:

<!–<script src=”Scripts/jquery-1.9.0.js”></script>
<script src=”Scripts/bootstrap.js”></script>
<script src=”Scripts/knockout-3.2.0beta.debug.js”></script>–>

<script src=”App/boot/require.config.js”></script>
<script src=”Scripts/require/require.js”></script>

Now you are wondering where is the greeting.js gone and how is it going to be loaded? Well there is no magic, we have a couple of more steps to go.

Add App/boot/Startup.js

In the App/boot folder add a new JavaScript file called startup.js. The name is to help us understand the process, it’s not a convention.

Add the following ‘module-definition’. You can read up about RequireJS Modules here.

define([‘jquery’, ‘knockout’, ‘bootstrap’], function ($, ko)
{
ko.components.register(‘greeter’,
{
require: ‘App/components/greeter/greeting’
});
ko.applyBindings();
});

The Startup module says that it is dependent on jQuery, KnockoutJS and BootStrap. Note, it uses the same names that were used in RequireJS configuration above. The function parameters are instances of the dependencies requested in the array, so if you put another input parameter like boots it would have instance of the bootstrap library. We’ll just keep this in mind for now.

Next it declares a function that has jQuery and KO lib references as input parameters.

In the function we ‘register’ our ‘greeter’ component. Note, that we have moved the registration from the greeting.js to startup. Also note instead of specifying the hard-coded template and view model, we are simply configuring a ‘require’ property, that points to the folder where the greeting.js is (without the js).

Well, that’s the startup configuration. Needless to say, as we add more components they will need to be registered here.

Updating our ‘greeter’ component

The first thing we do is add a greeting.html (name same as JavaScript is again not a convention, just easier to map in our heads).

It contains the same markup that we had hardcoded in the template:

image

Update greeting.js

Finally we update the greeting.js component. We comment out all the old code and replace it with the the following:

define([“knockout”, “text!./greeting.html”], function (ko, greeterTemplate) {
function greeterViewModel(params) {
var self = this;
self.greeting = ko.observable(params.name);
self.date = ko.observable(new Date());
return self;
}
return { viewModel: greeterViewModel, template: greeterTemplate };
});

So essentially we have morphed our component to a RequireJS module. Key thing to note here is use of the text plugin to load load the greeting.html. Require does all the work to load the template and stuff it into the greeterTemplate parameter.

Finally we return an object that KO accepts as definition for a module.

One more thing!

We are almost there. Those paying close attention would have noticed that we didn’t put in reference to the startup.js anywhere. How does RequireJS know how to initialize our app and it’s dependencies?

Back to the Index.html, we update the script tag that refers to RequireJS as follows:

<script data-main=”App/boot/startup” src=”Scripts/require/require.js”></script>

The data-main tag, tells Require that the main module to initialize the app is in that JS file. Thus RequireJS knows what to invoke once fully initialized.

Done!

Conclusion

If you run the application now, you’ll see the same old screen we saw in the first part. So what have we done new? Well plenty:

1. Let RequireJS load scripts dynamically.
2. Separated our KO components’ view from it’s model
3. Defined a central place to register all KO components

What we have not done is do more ‘webby’ stuff like putting in links to other possible pages of the app and creating different types of modules for each page and then showing how our app can navigate to those pages as well as load those dependencies on-demand. That’s what we’ll cover in the next part – Routing!

Source Code

The source is on Github as usual (note, after each article I am branching the code out and keeping the master for the latest updates)!

https://github.com/sumitkm/BuildingSpaUsingKO/tree/Part2

Tagged , , , ,

Dipping your feet into KnockoutJS Components

Last week I saw Steve Sanderson’s NDC 2014 talk on how to build large Single Page Applications using KnockoutJS and other tooling. It struck a chord because SPA is something that I am dealing with right now and really wanted to get neck deep into how to use KO and other tools to build one ‘correctly’.

I have tried with AngularJS in the past and you may have read my multipart series on Devcurry. While I have nothing against AngularJS I still find myself more inclined towards using KO more than anything else. Don’t read too much into it, it’s just me, I like KO!

Anyway, Steve’s talk is very deep and he rightly says, you feel like you are hanging on to a race car when sitting through his talk. So I’ve decided to really slow things down and take it one small bit at a time to see how we can use the latest and greatest version of KO (3.2.0 Beta) to build a front-end framework.

Today we’ll look at something new that’s not available in the release version of KO 3.1 as of date – Components.

Components allow you to build HTML+JS snippets that can be reused just like old server side controls of yester-years or like Directives in AngularJS. They actually mimic an upcoming web standard called Web Components.

Steve also used a set of tooling that I am unfamiliar with, so I’ll try to map stuff he did to how I would do if I were using Visual Studio (as far as possible). Lets get started.

Getting Knockout 3.2Beta

As soon as 3.2 goes live it will be available for use via Nuget and the Nuget Package Manager from inside Visual Studio. Today you can download the build from the Releases page on KO’s Github repo – https://github.com/knockout/knockout/releases

If you are a JS ninja you can get the entire library source and build it using NPM and Grunt.

Starting with a clean slate

I’ll start with an empty Web Project in Visual Studio 2013.

Screenshot 2014-07-18 20.55.33

Screenshot 2014-07-18 20.55.57

Screenshot 2014-07-18 20.56.28

As you can see, we get a really really empty template. If you run this in VS, you will get an error saying you don’t have directory browsing permissions.

The Home Page

Since our project is all clean, let’s first install Bootstrap that we’ll use for styling. In the PM console type:

install-package bootstrap

This gives us the following folder structure, where Content has the StyleSheets and Scripts has the JavaScripts required.

image

Now add a new HTML page to the root of the project, call it Index.html (or home.html)

image

Thanks to Visual Studio I have forgotten how to setup a basic startup page using Bootstrap. Serves me right, that, I have to scratch my head and wonder ‘now what’:

image

After ‘considerable’ struggle Winking smile, I update the HTML to include Bootstrap styling and jQuery references.

<!DOCTYPE html>
<html xmlns=”
http://www.w3.org/1999/xhtml”>
<head>
<title>Dipping your feet into KnockoutJS Components</title>
<link href=”Content/bootstrap.css” rel=”stylesheet” />
<link href=”Content/bootstrap-theme.css” rel=”stylesheet” />
</head>
<body>
<div class=”navbar navbar-inverse navbar-fixed-top”>
<div class=”container”>
<div class=”navbar-header”>
<button type=”button” class=”navbar-toggle” data-toggle=”collapse” data-target=”.navbar-collapse”>
<span class=”icon-bar”></span>
<span class=”icon-bar”></span>
<span class=”icon-bar”></span>
</button>
<a class=”navbar-brand” href=”/”>KO Components</a>
</div>
</div>
</div>
<div class=”container body-content” style=”padding-top:50px”>
<h2>Dipping your feet into KnockoutJS Components</h2>
<hr />
</div>
<footer class=”navbar navbar-fixed-bottom”>
<p>&copy; 2014 – Still Learning </p>
</footer>
<script src=”Scripts/jquery-1.9.0.js”></script>
<script src=”Scripts/bootstrap.js”></script>
</body>
</html>

Now if I run this in Visual Studio we’ll get the following page:

image

Let’s see some KO!

I am assuming you have downloaded the KO library as instructed above, so add it to the scripts folder and add a reference to it in our HTML file.

image

Now our App is going to be all HTML and JavaScript and I don’t see the need for CSHTML files at the moment. So let’s create an App folder in the application to consolidate ‘our stuff’.

We add a folder called App and add a js file called greeting.js to it.

In this file we add a simple view model with two properties greeting and date. For now we’ll hardcode the greeting to a standard “Hello World”.

var viewModel = {
greeting: ko.observable(“Hello world!”),
date: ko.observable(new Date())
};

$(function () {
ko.applyBindings(viewModel);
});

Finally we add reference to this script in our Index.html and add a couple of spans to show our greeting.


<div class=”container body-content” style=”padding-top:50px”>
<h2>Dipping your feet into KnockoutJS Components</h2>
<hr />
<div class=”container-fluid”>
<div> Hello <span data-bind=”text: greeting”></span></div>
<div> It is <span data-bind=”text: date”></span></div>
</div>
</div>

<script src=”Scripts/jquery-1.9.0.js”></script>
<script src=”Scripts/bootstrap.js”></script>
<script src=”Scripts/knockout-3.2.0beta.debug.js”></script>
<script src=”App/greeting.js”></script>

Refresh the Index.html on your browser and you should see something similar:

image

Now if you are wondering what’s so great about this, it’s exactly how KO works, you are right!

Where are my komponentz?!?

Well, let’s say we want to convert our ‘Greeting’ HTML + View Model into a reusable component that can be applied anywhere we want? Hello KO components!!!

Change the greeting.js to the following:

ko.components.register(‘greeter’, {
    // The register method needs a config object with
// 2 properties

template: // template is a string with the HTML template to apply
// Here we have directly hardcoded the string we originally
// had in index.html
        “<div class=’container-fluid’>” +
“<div> Hello <span data-bind=’text: greeting’></span></div>” +
“<div> It is <span data-bind=’text: date’></span></div>” +
“</div>”,
viewModel: function(){ // viewModel that can be an object or function
        greeting = ko.observable(“Hello world!”);
date = ko.observable(new Date());
}
});

$(function () {
ko.applyBindings();
//We have removed the explicit reference to the viewModel
});

As we can see above, we have used the new ko.components API to declare a new component called ‘greeter’ (first parameter).

The component needs two parts to be initialized properly, one is the HTML template (in the template) property, and other is the View Model in the viewModel property of the initialization object.

As of now, we have hardcoded the HTML that we had added to our Index.html as the template. Later on, we’ll see how to get it from a separate file etc.

We have used the constructor method technique to define the view Model with the same two properties we had earlier. Why? We’ll see in a minute.

Now that our ‘component’ is ready how do we ‘use’ it? Simple, the name of the component is also the name of the tag, so switch back to Index.html and update the body as follows:

<div class=”container body-content” style=”padding-top:50px”>
<h2>Dipping your feet into KnockoutJS Components</h2>
<hr />
<greeter></greeter>
</div>

Refresh your Index.html in browser and you’ll see things still work as they were! Congratulations, you’ve just built your first component.

Passing Parameters to components

Well, the hard coded Greeting is not quite flexible, what if we wanted to pass in a message to the component?

It is very simple to pass parameters into a component. Add a ‘params’ attribute to the tag and pass in name: value pairs. You will get it as an object in the constructor of your viewModel and you can use it accordingly.

So change the component setup in greeting.js as follows

ko.components.register(‘greeter’, {
// The register method needs a config object with
// 2 properties
template: // template is a string with the HTML template to apply
// Here we have directly hardcoded the string we originally
// had in index.html
“<div class=’container-fluid’>” +
“<div> Hello <span data-bind=’text: greeting’></span></div>” +
“<div> It is <span data-bind=’text: date’></span></div>” +
“</div>”,
viewModel: function(
params){ // viewModel that can be an object or function
greeting = ko.observable(params.name);
date = ko.observable(new Date());
}
});

Next update the Index.html to pass parameters to our component.

<greeter params = ‘name: ” Sumit!”‘></greeter>

Refresh the page and you see the following:

image

Copy paste multiple <greeter … /> instances and pass different names to them

<greeter params=’name: ” Sumit!”‘></greeter>
<greeter params=’name: ” Optimus!”‘></greeter>
<greeter params=’name: ” Bumblebee!”‘></greeter>

Refresh Index again and things work as expected!

image

Congratulations, you have built your first KO component!

This concludes the first 15 (approx.) minutes of Steve’s talk. Lots of more stuff is in store. As I explore these things, I’ll continue to share what I learn, first of which will be using RequireJS and Automatic Module Detection. So watch out for the next part in the series.

Source code on my Github repo here – https://github.com/sumitkm/BuildingSpaUsingKO/tree/Part1

Tagged , , , ,
%d bloggers like this: