Sencha Touch container tap events!

Sencha Touch is awesome, but sometimes can be frustrating. Some components just don’t have the events that you need. For example you can’t add a tap listener for a container inside of your controller’s config. I know you can add a listener on the component in the view, but I hate doing this because it moves controller logic in your view.

How do you get a container to listen for a tap event?

Since the component doesn’t have a tap listener we can add one to the components element object! Attaching a listener to the component’s element object gives you access to pretty much any event you will need. In this demo I’m going to use the tap event.

The view with the container component

Ext.define("MainView", {
    extend: 'Ext.Container',
    xtype: "main",
    name: "MainView",
    config: {
        layout: {
            type: 'fit',
            align: 'center',
            pack: 'center'
        },
        items: [
           {
            xtype: 'container',
            items: [{
                xtype: 'container',
                name:'clickableContainer',
                html: 'Hello there click me!'
            }, {
                xtype: 'container',
                html: 'Not clickable'
            }]
        }]
    }
});

The controller

Ext.define('MainController', {
	extend: 'Ext.app.Controller',
	config: {
		
	    control: {
	        MainView:{
		    initialize:'init'
		},
            },
	    refs: {
		MainView:"container[name=clickableContainer]",
	    }
	},
	init:function () {
          var containerView = Ext.ComponentQuery.query('container[name=clickableContainer]')[0];
	  var containerViewEl = containerView.element;
          containerViewEl.on('tap', 
            function( event, node, options, eOpts ){
         	alert('clicked the container');
    	    }
          );
	}
});

First thing we do is set up an init method, which is where we get a reference to the container view. Once we have the container view we can get the component’s element and use the on method to set up a listener (you could substitute the onBefore or onAfter method here), and just like that we have a container with a tap event!

Pull to refresh UITableView | UIRefreshViewControl

I use UITableViews in almost every app I build, and sometimes I need to implement a pull to refresh like a boss. Its pretty easy so lets get started.

Adding a UIRefreshViewControl

Lets set up the scenario first. You have a storyboard with a view controller, and inside the view controller is the the UITableView that you want to add the UIRefreshViewControl to. You cannot add a UIRefreshViewControl in the storyboard so we will have to add it to our table view in the ViewController.

What if you don’t have a UITableViewController!

You can’t add a UiRefresViewControl directly to a UITableView so if you are inside a UIViewControlelr and only have tableview, you can just add one!

- (void)viewDidLoad
{
    [super viewDidLoad];

    UITableViewController *tableViewController = [[UITableViewController alloc] init];
    tableViewController.tableView = tweetsTableView;

    self.refreshControl = [[UIRefreshControl alloc] init];
    [self.refreshControl addTarget:self action:@selector(refreshTweets) forControlEvents:UIControlEventValueChanged];
    tableViewController.refreshControl = self.refreshControl;
    self.refreshControl.tintColor = [UIColor colorWithRed:(254/255.0) green:(153/255.0) blue:(0/255.0) alpha:1];

}

First we create the UITableViewController and set the UITableView from the storyboard as its tableview property. Next I alloc and init the refreshControl and add a target and action. This is the callback method when the tableview is pulled to refresh!

Hide the UIRefreshControl

- (void)refreshTweets{
    // refresh logic 
    //End refresh control
    [self.refreshControl endRefreshing];
}

The endRefreshing method removes the loading icon from the top of the TableView and we are back where we started with our TableView!

Build a scraper with php

There are a lot of ways to get data from websites, most of the time this is in the form of an API. When this isn’t available, you can build a scrapper to pull data right off of the website through its html.

When can you use a scraper?

Anytime you have access to html you can use a scraper to parse that information and gather the data you are looking for. The main issue with scrapers is you are relying on the structure of the page to be the same every time you send your script off to gather data.  This is why I’m weary about using scrapers as long term solution for data gathering.

Is PHP the only programming language to use with scrapers?

No,  you can pretty much use any programming language as long as it has the ability to pull in a web page’s content and parse the html that is returned. One thing to look for that is extremely helpfully is a pre built HTML dom parser. To find if the language you are using has one search “(programming language) html parser”  and you will find a ton of different options. I will be using http://sourceforge.net/projects/simplehtmldom/. A dom parser allows you to easily search through the returned html and find specific tags and the data contained within the tags. Now that we have a basic understanding of what tools we will be using lets get started!

Start Scraping!

Download this sample from github https://github.com/barrettbreshears/PHPTwitterScraper

Well actually lets hold off on that. Before we write any code I always like to get and idea of what the html structure looks like, and if there is a pattern or unique class or id I will be able to use to grab the data from the website. I will be using my twitter page for this demo https://twitter.com/BarrettBreshear and I will be grabbing all the tweets and when they were tweeted from the page. Also if you guys would like to follow me on twitter I would really appreciate it! Anyway when I inspect the page’s html I see that all the tweets are nested inside of an <ol> and each tweet is located inside of a <li> and all the tweet data is located inside of a div with the class .tweet!

Screen Shot 2014-02-11 at 10.29.30 PM

Now that we know the basic structure of the page lets get started scraping!

find('div.tweet');

// loop through each tweet div and pull out the timestamp and text
foreach ($tweets as $tweet) {
	$tweetText = $tweet->find('p.tweet-text', 0)->plaintext;
	$tweetDate = $tweet->find('a.tweet-timestamp', 0);
	echo $tweetText . " : " . $tweetDate->title . "\n";
}

 
Thats is! As you can see there really isn’t much to it. To run this code locate the directory of your project in terminal and type

php index.php

or go to the url in a browser (I’m not going to tell you how to live your life) and you will start to see the glorious data we were looking for.
Screen Shot 2014-02-11 at 11.56.07 PM
PHP simple html dom parser is a pretty cool project, and has lots of features that can really help you scrape the specific data your are looking for. For the complete manual take a look at http://simplehtmldom.sourceforge.net/manual.htm
One thing I would like to also add before you go is to throttle your scrapes. You usually aren’t scraping your own websites, so keep this in mind and slow down you program to a considerate rate.

Thanks for reading and I hope you guys enjoyed this basic example. Hopefully it will lead you to scraping glory!

Active navigation link with javascript / jQuery

Navigation is something that almost every web app has to deal with, and most of the time navigation will have an active state. There are a couple of ways to do this, and I am going to demonstrate using  jQuery as well as plain javascript just in case you don’t have jQuery in your project.

Bootstrap Navigation

So lets take a look at a normal bootstrap navigation


Setting active navigation

What we want to do is get the current url, and then loop through each menu item and check to see if the href is equal to the url. We also want to check if the if the menu item is part of a dropdown menu, if it we want to find the parent menu item and set it to active as well. Here is what the javascript looks like.

$().ready(function(){
  setActiveLink();
});


function setActiveLink(){

  // get the current url
  var url = window.location.pathname;
  // decode the url
  url = decodeURIComponent(url);

  // this is incase your project isn't in the root directory of your url
  // for example localhost/ActiveNavLink/index.html
  projectPrefix = "/ActiveNavLink/";

  // loop through each nav li
  $('.nav li').each(function(){

    // get the menu a tag and get its href attribute
    var href = $(this).find('a').attr('href');

    // href can be undinded if there is a divider
    if(href === undefined)
      return;

    // add the project prefix
    href =  projectPrefix + href;
    
    // check if the menu item is equal to the current url    
    if(url.substring(0, href.length) == href){
      // set active class to li
      $(this).addClass('active');

      // check if there is a parent dropdown
      var parentDropDown = $(this).closest('.dropdown');
      // if there is a parent dropdown set it to active as well
      if(parentDropDown !== undefined){
        parentDropDown.addClass('active');
      }
    }
      
  });

}

Screen Shot 2014-02-11 at 2.49.55 PM
If you want to take a look at a working demo take a look at https://github.com/barrettbreshears/ActiveNavLink. You will probably need to change minor details to make this work in your project, but its pretty straight forward. Hope this is helpful!