The websites made with AJAX are difficult to crawl by the search engines, so Google propose to create snapshot of the site to do it crawlable, it means like save a render version of your site and give this version to the search bot and the ‘live’ version of your site to the users.

The basics
Before to follow, i will not rewrite the wheel, so is good idea that you read this article to figure out how we can solve it with AngularJS and how the search engines bot will know that we have a snapshot of our site ready for them and how a snapshot will look.

Creating the snapshots
And now that you know how the bot works and what we should to do with our site to do it crawlable, let’s see how to create the snapshots: yep, i will recommend
other article first, please read it.

So, now that you read the last link, you know that we will need PhantonJS to create the snapshots. If you are using Ubuntu 12.04 LTS i will recommend install PhantonJS using the NodeJS package manager (npm) and not from the official repository, because it install an old version of PhantonJS where it need X server to run anyway.

Solving the ‘flag’ bug
So, you saw this section from the last article link that they use this PhantonJS script called .phantomjs-runner.js to generate the site snapshot, and the script wait to read a flag in the body of our site to know that all the AJAX call are finished and our site is fully rendered before save it. But there is something wrong about it.. do you can figure it? not? okay.. read this comment in the article, but instead to use magic hooks not documented by Angular (that also didn’t work for me in Angular 1.2) we will use a better approach, i modify this module called ng-BlockUI that use interceptors to know when all the http request are completed, and this is the code:

and the flag page body

Don’t forget to add the module injection to your app definition, and if you have some doubt read the module documentation.

and like we are not more using the string ‘ready’ to say that all the http responses are complete, we also should modify the .phantomjs-runner.js script and it now will look like that:

 

Integrating with Laravel
Until now, we have the PhantonJS script to create the site snapshots and the AngularJS module used to create a flag that communicate to the PhantonJS script that all the AJAX calls are finished so the script can save the totally render page snapshot.

A good idea is to integrate this script call with Laravel creating a new artisan command, we will see soon how to do it, but first a note: In my case the website is multisite, in my case it means that depending the domain the site language change and i want a snapshot for each language then Google can crawl the site for the both domains in different languages, so my .htaccess to say to the engines bot that i have a diferent snapshot depending the domain look like that:

(i am not like a .htaccess kung-fu master, so i think that i can merge this two rewrite condition in one, but i didn’t have time yet to see it)

Let’s see now the artisan command code that take the arguments from a custom config file:

 

and the configuration file look like that:

 

and finally, add the call to artisan cc:snapshots to your cron to have a updated AngularJS site crawlable :)

if you have any doubt, feel free to write a comment.

happy code!

UPDATE
If you will test the crawling using the Google Web Master Tools Fecth as GoogleBot, keep in mind it:

Looking at your blog’s homepage, one thing to keep in mind is that the Fetch as Googlebot feature does not parse the content that it fetches. So when you submit toddmoyer.net/blog/ , it fetches that URL. After fetching the URL, it doesn’t parse it to check for the “fragment” meta tag, it just returns it to you. However, if you fetch toddmoyer.net/blog/#! , then it should rewrite the URL and fetch the URL toddmoyer.net/blog/?_escaped_fragment_= .

When we crawl and index your pages, we’ll notice the meta-tag and act accordingly. It’s just the Fetch as Googlebot feature that doesn’t check for meta-tags, and instead just returns the raw content.

 

 

Hello,

We will see a quick example of how to add animation support to Angular using the new ngAnimate module and animate.css library, also we will use LESS to do it more clear and transparent for Angular.

Let’s start..

Like maybe do you know, the development team of Angular put out the animation behavior from the AngularJS core and one of reason to take this decision was to support easily third party libraries.

We can use animate.css without use ngAnimate module, just like the documentation of the library describe to use it, but it will be a bit dirty and messy, so let’s do it in a more elegant way, we will use ngAnimate to add animation support to our directives in a legacy way and LESS to mixins the animate.css class with the ngAnimate module classes.

First, do you need to have some knowledge of how ngAnimate works, i will recommend this article Remastered Animation in AngularJS 1.2 and more precise this section, because here i will use a ngShow and ngHide directive example.

So in resume, ngAnimate can manage all the animation by CSS adding dynamically subclass to our element class when it start and finish an action (in our directive example case), so we will add the animate.css class like mixins to this subclasses and to do it we will use LESS.

 

remember to add support for ngAnimate in your Angular app

and now you can try it (don’t forget to add the class to the element)

Easy? yes, it is when you figure how to use it in a good way.

Also i want to recommend this article to use Laravel with Bootstrap, Bower and Grunt,

Happy coding!

TODAY, FEBRUARY 11TH, 2014 IS
THE DAY WE FIGHT BACK
AGAINST MASS SURVEILLANCE

https://thedaywefightback.org/
https://www.dontspyonus.org.uk/org

 

We will implement the Datapicker for Bootstrap using AngularJS that is more beautiful than the jQuery UI datepicker because keep the bootstrap style, so we will need warp the datepicker in an AngularJS directive and it look like that:

(in this case on the onRender event i am telling to the Datapicker that only allow dates <= today)

to use the directive on the view, this will be the html code:

So, now every time that the datapicker changeDate event occurs we will update the ng-model value.

 

Something you will prefer also call an AngularJS controller method from the datapicker onChange event, one of the best way to implement it and still keeping directive’s free dependency is passing the controller method via html attribute to the directive, so better see a code example (i will avoid the myApp initialization):

Controller:

Html:

(be aware of the x-bt-date-picker=”myFn” in the second line)

and finally, the directive with the changes:

How do you can see we are passing the controller method like a directive attribute doing the directive more reusable and keeping it free of dependency injection

 

For further understanding of what and how we are doing all the magic here, please refer to this links AngularJS and scope.$apply and Angular.js binding to jQuery UI.

But if you are lazy and you don’t mind about the datepicker style you can use the UI Bootstrap for AngularJS

Issac Asimov speaking about the internet before it really was accessible in ours home and how it would change the learning way, for me, internet was my best teacher ever


what about you?

If you are using Chef, AWS OpsWorks or something where do you need to do an unattended command call.. you will find problems if you are trying to run apt-get with the -f option to solve unmet dependency problem.

apt-get doesn’t “listen” to the -y or –force-yes option with -f, so anyway you will get a prompt waiting for you entry that look like that:

so, it’s come from a call of apt-get to dpkg and not from apt-get and it’s for it that -y and –force-yes doesn’t work, them to solve it you should pass to apt-get some options that later it will pass to dpkg, and it’s look like that:

for a full specification and more example check Everything you need to know about conffiles: configuration files managed by dpkg

take me some days figure out it, and i was playing with expect to solve the problem..

Natively KO 3.3 don’t have support for SQLite with ORM, but with a little of code we can do it!

First one, make sure that you have installed the pdo_sqlite extension in your PHP, to check it you can run the follow lines:

if one of you driver is sqlite everything is right

Now, to connect with SQLite we will use PDO but we must do a little change in the Kohana_Database_PDO database connection class to support SQLite using ORM. We will extend the PDO connection class and create own connection driver overridden the conflictive methods

application/classes/Database/PDOSQLite.php

now to connect to the SQLite database, we must use own new driver

application/config/database.php

and that it’s all :)

Tip: Be sure that your SQLite file-database directory have write privileges for the application, yes the directory not only the file, because for default SQLite use the file-database directory like temporal space

[0] Reference: K03, ORM and SQLite via PDO

 

Do you need some php function in your js code?

There is a useful library for it with the tagline “Learn how to do it in JavaScript. Explore boundaries porting languages. Enjoy functions that turn out to be useful.”

Here the page and the full list of all the functions ported: http://phpjs.org/functions/

Happy Coding!

or best know, in our area, like Social Engineering

by Dr. Robert Cialdini

Sometimes in our application we want bind some keys to a certain functionality like in a normal menu on W32 applications and prevent the browser action for this keys (preventDefault).

Here i leave an example of a MVC Controller binding the key F1 to our application, basically the controller open a window component when the user press F1 or just click in the menu item

but, what about if we want pass another arguments to the method onBuscarClientClick? or use the parameters coming from the control call? and more yet, what about to don’t have to write the line code if(e) e.preventDefault(); in all our methods?

well, solve it is easy

Happy Coding!