AngularJS Navigation Menu

March 10th, 2013 kmussel No comments

Once again I’m in need of creating a navigation menu with drop downs. This time I’ve been working with Angular and using Foundation 4 for styling.

The Final Output

Because who doesn’t like dessert first

Here is the fiddle. http://jsfiddle.net/kmussel/evXFZ/

The Styling

The good news is Foundation basically has all the styles already done for you under the class of “top-bar” and “top-bar-section”. But since I needed to have this nav under the top bar I just copied most of the top-bar styles and put it under the “nav-menu” class. You can see some of the styles I copied over at the bottom of the css panel in the fiddle.

You can also test out using only foundation’s top-bar styling by uncommenting out the html in the fiddle and commenting out the other “nav” element. And then change the directive name from “navMenu” to “anavMenu”. Make sure the result panel is wide enough though cause foundation changes the css on small screen sizes when it comes to the top-bar.
Basically if all you do is include foundation’s css the only thing you have to make sure you do is change your html to have a “top-bar” class and then a nested “top-bar-section” class.

The AngularJS Goodness

If you’ve never worked with angular I definitely recommend it. But it can be frustrating especially dealing with directives (which is what we will be doing here). I think this guy is spot on with how learning angular will make you feel.

So I basically knew what I wanted to be able to do and that is in html write this:

<nav menu-data="menu"></nav>

and it spit out my entire navigation.

And so I could resuse the directive with other controllers I added an attribute to it that would reference the scope variable where the menu data would be which led me to have this:

<nav menu-data="menu" menu-data="menu"></nav>

The first directive I create then is the navMenu one.


app.directive('navMenu', ['$parse', '$compile', function($parse, $compile)
{
    return {
        restrict: 'E', //Element
        scope:true,
        link: function (scope, element, attrs)
        {
            scope.$watch( attrs.menuData, function(val)
            {
                var template = angular.element('<ul id="parentTreeNavigation"><li ng-repeat="node in ' + attrs.menuData + '" ng-class="{active:node.active && node.active==true, \'has-dropdown\': !!node.children && node.children.length}"><a ng-href="{{node.href}}" ng-click="{{node.click}}" target="{{node.target}}" >{{node.text}}</a><sub-navigation-tree></sub-navigation-tree></li></ul>');
               var linkFunction = $compile(template);
               linkFunction(scope);
               element.html(null).append( template );
            }, true );
      }

}]);

In here i create the initial template. The template contains 2 other directives. Angular’s built-in “ng-repeat” and my other “sub-navigation-tree”. This is put inside a watch statement so if the menu changes it will be updated. The template is then compiled and linked to current scope and then appended to the current element.
This then compiles and links all the directives within that.

The Inner Directive handles the actual drop down part.



.directive('subNavigationTree', ['$compile', function($compile)
{
    return {
        restrict: 'E', //Element
        scope:true,
        link: function (scope, element, attrs)
        {
            scope.tree = scope.node;

            if(scope.tree.children && scope.tree.children.length )
            {
                var template = angular.element('<ul class="dropdown "><li ng-repeat="node in tree.children" node-id={{node.' + attrs.nodeId + '}}  ng-class="{active:node.active && node.active==true, \'has-dropdown\': !!node.children && node.children.length}"><a ng-href="{{node.href}}" ng-click="{{node.click}}" target="{{node.target}}" ng-bind-html-unsafe="node.text"></a><sub-navigation-tree tree="node"></sub-navigation-tree></li></ul>');

                var linkFunction = $compile(template);
                linkFunction(scope);
                element.replaceWith( template );
            }
            else
            {
                element.remove();
            }
        }
     };
}]);

Here you see the same thing with the template but it’s referencing itself now. The template is being linked to the current scope. This means that the directives within the template will be run using that scope. So ng-repeat=”node in tree.children” will be looping over scope.tree.children.
The ng-repeat then creates new scopes for each item and gives that scope access to the object through whatever you called it in your ng-repeat. In our case “node”. The scope that is created in the ng-repeat is the one that is passed to our directive.
Then if the current scope has children it does it all again with linking the template up with the current scope. It then replaces the current element with the template or removes it all together if there are no children.

Categories: Uncategorized Tags:

Asynchronous Request within UITableViewCell

June 16th, 2011 kmussel No comments

The Problem:
I have an image that needs to be loaded for each table cell. Unfortunately this causes the UI to become unresponsive for a couple seconds when you click to go to that table view.

The Solution:
Make the call to get the image data asynchronous.

First in our tableview delegate method, cellForRowAtIndexPath, we’ll use NSURLConnection to create the connection.


NSURLRequest *req = [[NSURLRequest alloc] initWithURL:[NSURL URLWithString:@"http://www.test.com/image_url"]];
NSURLConnection *imgCon = [NSURLConnection alloc];
..... /** Code added later  **/
[imgCon initWithRequest:req delegate:self startImmediately:YES];


There are 2 delegate methods that you need to have to make this work. (There are others that you’ll probably want to implement as well. Apple Docs)


-(void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data;
-(void)connectionDidFinishLoading:(NSURLConnection *)connection;



The didReceiveData method will probably be called multiple times. So we need to create a variable to keep on appending the data to it. Since we are creating multiple connections we need to map each connection to the data. But we also need to know which table cell we need to update once we have all the data.
So we create 2 NSMutableDictionary objects. One to map the table cells indexPath to the data and one to map the connection to the indexPath.


NSMutableDictionary *indexPathImgData;
NSMutableDictionary *connectionIndexPath;



The problem that arrises from trying to map the connection to the indexPath is that NSURLConnection doesn’t conform to the NSCopying Protocol. To get around this we need to use CFMutableDictionary. When adding values to a CFMutableDictionary “the keys and values are not copied—they are retained” (Apple Docs on CFMutableDictionary)

So to add the values to our NSMutableDictionary we will use the CFDictionaryAddValue function.

Now our cellForRowAtIndexPath method will look like this:


NSURLRequest *req = [[NSURLRequest alloc] initWithURL:[NSURL URLWithString:@"http://www.test.com/image_url"]];
NSURLConnection *imageCon = [NSURLConnection alloc];

CFDictionaryAddValue((CFMutableDictionaryRef)self.connectionIndexPath, imageCon, indexPath);
NSMutableData *imageData = [NSMutableData dataWithCapacity:0];
CFDictionaryAddValue((CFMutableDictionaryRef)self.indexPathImgData, indexPath, imageData);

[imageCon initWithRequest:req delegate:self startImmediately:YES];



And our NSURLConnection Delegate methods will look something like this:


- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {

    [[self.indexPathImgData objectForKey:[self.connectionIndexPath objectForKey:connection]] appendData:data];
}

-(void)connectionDidFinishLoading:(NSURLConnection *)connection
{
    NSIndexPath *temp = [self.connectionIndexPath objectForKey:connection];
    [self.tableView reloadRowsAtIndexPaths:[NSArray arrayWithObject:temp] withRowAnimation:UITableViewRowAnimationNone];

}



Now in your cellForRowAtIndexPath method you’ll want to do a check if the dictionary object has data for that indexPath and if so display it otherwise you’ll want to create a new connection.

Categories: Tutorial Tags: ,

iPhone Push Notifications

June 16th, 2011 kmussel No comments

iPhone Push Notification Testing:

Testing out the interaction after receiving a remote push notifications on the iphone can be very annoying. Apple does not make it easy to setup remote push notifications. Plus development time is much slower if you try to build and test this interaction while waiting for remote notifications. And unfortunately Apple doesn’t provide a way to test out remote notifications on the simulator.

So instead of using a remote notification I used a local notification for testing this interaction.
In your UIApplication delegate instead of using this delegate method:


- (void)application:(UIApplication *)application
     didReceiveRemoteNotification:(NSDictionary *)userInfo

I used this:


- (void)application:(UIApplication *)application
        didReceiveLocalNotification: (UILocalNotification *)notification

You can then schedule a local notification (Apple Docs). This will then simulate receiving a notification when you are in the app.

To simulate the notification when the app isn’t in the foreground I created a local notification inside the delegate method:


-(void)applicationDidEnterBackground:(UIApplication *)application.

I set it up so as soon as you closed the app the notification would fire showing the default alert box.

Here is the code I used to create the local notification inside the DidEnterBackground method.


NSDate *nowDate = [NSDate date];
NSTimeInterval seconds = 0;
NSDate *newDate = [nowDate dateByAddingTimeInterval:seconds];

UILocalNotification *localNotif = [[UILocalNotification alloc] init];
if (localNotif != nil)
{
  localNotif.fireDate = newDate;
  localNotif.timeZone = [NSTimeZone defaultTimeZone];

  localNotif.alertBody = @"You have new notifications";
  localNotif.alertAction = NSLocalizedString(@"View", nil);

  localNotif.soundName = UILocalNotificationDefaultSoundName;
  localNotif.applicationIconBadgeNumber = 2;

  NSDictionary *infoDict = [NSDictionary dictionaryWithObject:@"2"
       forKey:@"NewNotifications"];
  localNotif.userInfo = infoDict;

  [[UIApplication sharedApplication] scheduleLocalNotification:localNotif];
  [localNotif release];
}


When you click the “View” button on the alert box, the application will come to the foreground and the didReceiveLocalNotification will be called. You can then do what you need to do based on what data you passed to it via the NSDictionary object in the local notification.

So the main difference in your code between the local and remote notification is that in the local notification you’ll have to access the data you sent to it with [notification userInfo] and in the remote notification, the dictionary object is what is passed to it.

Categories: Development Tags: ,

CoreJS

January 17th, 2011 kmussel No comments

Server-side Javascript using Google’s V8 Engine.

Recently I started working on an open source project with my good friend, Wess Cope, who is more passionate about javascript than anyone I’ve ever met. It was this that drove the want to be able to use javascript for everything. So we built CoreJS which you can find at https://github.com/frenzylabs/CoreJS.

We used http://wiki.commonjs.org/wiki/CommonJS#Low-level_APIs for a reference on what should be implemented in CoreJS.


Aren’t there already server-side javascript frameworks?

The main one out there is nodejs. Overall it’s pretty good but the main issue we had with it is that it forces everything to be asynchronous. Having it be asynchronous is great but we wanted to have the flexibility to be both. There are definitely times when you don’t want something to be asynchronous.

So what we ended up doing is setting up our functions to be asynchronous when there was a callback and synchronous otherwise.

For example our HTTP post request:


//Synchronous
var data = Http.post("/path/to/file", {arg:"arg1", arg2:"arg2"});
//Asynchronously
Http.post("/path/to/file", {arg:"arg1", arg2:"arg2"}, function(data){
                     print(data);
           });

CoreJS also utilizes the event based model, using LibEvent, and threading.

It’s definitely new and not complete yet but check it out and give us some feedback. We tried to add some decent documentation on how it all works cause we know it was very annoying to even try and build this with the lack of documentation. https://github.com/frenzylabs/CoreJS/wiki



Categories: Development Tags: , ,

Crawling Web Pages and Creating Sitemaps

November 29th, 2009 kmussel 1 comment

Creating a Sitemap Based on all the Links within a Website

I built this web crawler because I wanted a way to create a sitemap of this website I was building. I know there are a few websites out there that will do this for you but I didn’t want to rely on someone else and I wanted to change a few things. So in order to do this I used php and cURL.
I started out creating a class for the crawler. When I create a new crawler class I pass in the url of the website I want to start with. This also uses cURL to access the webpage and get the content and headers. Inside this class are also methods to get all the links of a page, the page title, the entire content, just the body content, and the headers. But you could easily add more to say grab all the images on a page.

The Crawler Class

  

class Crawler {
  protected $markup='';
  protected $httpinfo='';

  public function __construct($uri, $justheaders=0){
    $output = $this->getMarkup($uri, $justheaders);
    $this->markup = $output['output'];
    $this->httpinfo = $output['code'];
  }

  public function getMarkup($uri, $justheaders) {
    $ch = curl_init($uri);
    curl_setopt($ch, CURLOPT_HEADER, 1);
    if($justheaders){
      curl_setopt($ch, CURLOPT_NOBODY, 1);
      curl_setopt($ch, CURLOPT_BINARYTRANSFER, 1);
      curl_setopt($ch, CURLOPT_FAILONERROR, 1);
    }
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
    curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 30);
    curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
    curl_setopt($ch, CURLOPT_MAXREDIRS, 5);

    $output['output'] = curl_exec($ch);
    $output['code'] = curl_getinfo($ch);
    curl_close($ch);
    return $output;
  }

  public function get($type){
    $method = "_get_{$type}";
    if (method_exists($this, $method)){
      return call_user_method($method, $this);
    }
  }

  protected function _get_info(){
    return $this->httpinfo;
  }

  protected function _get_links(){
    if(!empty($this->markup)){
      preg_match_all('/<a(?:.*?)href=(["|\'].*?["|\'])(.*?)>(.*?)\<\/a\>/i',
                               $this->markup, $links);
      return !empty($links[1]) ? array_flip(array_flip($links[1])) : FALSE;
    }
  }

  protected function _get_body(){
    if(!empty($this->markup)){
      preg_match('/\<body\>(.*?)\<\/body\>/msU', $this->markup, $body);
      return $body[1];
    }
  }
  protected function _get_content(){
    if(!empty($this->markup)){
      return $this->markup;
    }
  }

  protected function _get_pagetitle() {
    if (!empty($this->markup)){
     preg_match_all('/<title>(.*?)\<\/title\>/si', $this->markup, $pagetitles);
     return !empty($pagetitles[1]) ? $pagetitles[1] : FALSE;
    }
  }
}




After this I create a recursive function that will follow each of the links. Each time I call this function I create a new instance of the Crawler class. If the url isn’t valid I just return. If the url is redirected curl has an option to follow links, the CURLOPT_FOLLOWLOCATION option. Since this is set to on, you need to get the actual url which is contained in the header information. After this I call the get links function. This will return all the unique links on a page. (Calling the array_flip twice makes them unique).


I then get the title tag for each page. This is used when creating the sitemap. I remove all the script tags and all the html tags. The next thing I do is get a base url. Since I’m creating a sitemap of just one website I don’t need any links to external pages. So if any of the links don’t contain this base url I wont follow it.


Now I begin looping through all the links on the page. If its an external link I return. If it is an absolute link and it contains a “/” I replace the whole thing with a slash. If it doesn’t have the slash but is an absolute link then the new val is “”. I do this because I am prepending the base url that we got earlier to it.


I then explode on the “/”. If the first element is empty then I put the base url in there. Otherwise I prepend the url to it. This is done to get the correct link no matter if it is a relative link, root relative, or absolute.

The complete link is formed and checked to see if it already exist in the globallinkarr. If it doesn’t I add it and then begin getting the different levels. Basically everytime there is a “/” in the url then that is a different level. This is used when I am creating the html sitemap. Also to create this array of levels, I have to call array_merge_recursive. Well the regular php function didn’t quite work. If a url has numbers as one of its levels for example blog/2009/12/post then that function would turn the 2009 to its own key. So I needed it to keep the keys the same so I just got another function off of php.net.

The Function to Get all the Links


$dontfollow = array('pdf', 'jpg', 'png', 'jpeg','zip', 'gz', 'tar', 'txt');

function findAllLinks($url){
  global $globallinkarr;
  global $depthlinks;
  global $dontfollow;
  global $pagetitles;
  global $contentarr;

  $crawl = new Crawler($url);
  $info = $crawl->get('info');

  $validcodes = array(200,301,302);
  if(!in_array($info['http_code'], $validcodes))
    return;
  $url = $info['url'];
  $links = $crawl->get('links');
  $title = $crawl->get('pagetitle');
  $title = $title[0];
  $body = $crawl->get('body');
  $count++;

  $content = strip_tags(preg_replace('//msU', '', $body));

  if(!array_key_exists($url, $contentarr))
    $contentarr[$url] = array('title'=>"$title", 'pagecontent'=>"$content");

  if(!count($links) || !is_array($links)) return;
  else{
    if(preg_match('/http(?:s)?:\/\/(.*?)\/(.*)/', $url, $pattern)){
      $baseurl = $pattern[1];
    }else{
      $baseurl = $url;
    }

    foreach($links as $val){
      if(preg_match('/.*?javascript:void\(0\)/', $val) || ereg('#', $val)){
        continue;
      }
      if(!preg_match('/[0-9a-zA-Z]/', $val)) continue;
      $val = trim($val, '"\'');

      /**
       * CHECK IF LINK IS GOING TO ANOTHER DOMAIN.  IF SO DONT FOLLOW IT.
      */

      if(preg_match('/^http(s)?:\/\//', $val) &&
               !strpos($val, preg_replace('/http(s)?:\/\//', '', $baseurl))){
        continue;
      }

      if(ereg('http', $val) && preg_match('/^http(s)?:\/\/.*?\//', $val)){
        $val = preg_replace('/^http(s)?:\/\/.*?\//', '/', $val);
      }else if(ereg('http', $val)){
        $val = '';
      }

      $sl = explode('/', $val);

      if(!preg_match('/[0-9a-zA-Z]/', $sl[0])){
        $sl[0] = preg_replace('/^http(s)?:\/\//', '', $baseurl);
        $complink = implode('/', $sl);
        $sl = explode('/', $complink);

      }else{
        $prepend = explode('/', preg_replace('/^http(s)?:\/\//', '', $url));
        if(count($prepend)>1){
          array_pop($prepend);
          $prep = implode('/', $prepend);
        }else $prep = $prepend[0];
        $sl[0] = $prep.'/'.$sl[0];
        $complink = implode('/', $sl);

        $sl = explode('/', $complink);

      }
      if(!end($sl)) array_pop($sl);

      if(!in_array($complink, $globallinkarr)){
        $globallinkarr[] = $complink;
        $pagetitles[$complink] = $title;

        $depth = count($sl);
        $templinks = array();
        $newlinks = array();
        if($depth > 1){
           if(!$sl[$depth-1]) $sl[$depth-1] = 'index';
           $templinks[$sl[$depth-2]][] = $sl[$depth-1];

           if($depth > 2){
	     for($i=$depth-2; $i>0; $i--){
               $hold = $templinks;
               $templinks = array();
               $templinks[$sl[$i-1]] = $hold;

             }
          }

          $temp = $templinks[$sl[0]];
          $newlinks[$sl[0]] = $temp;

        }
        $depthlinks = array_merge_recursive2($newlinks,$depthlinks);
        $end = strtolower(end(explode(".", $complink)));

        if(!preg_match('/^http(s)?:\/\//', $complink))
          $complink = 'http://'.$complink;
          if(!in_array($end, $dontfollow) && !ereg("sitemap", $complink)){
            findAllLinks($complink);
          }
       }
    }
    return;
  }
}


The Array Merge Recursive Function I Used From php.net

function array_merge_recursive2($array1, $array2){
  $arrays = func_get_args();
  $narrays = count($arrays);

  // check arguments
  // comment out if more performance is necessary
  //   (in this case the foreach loop will trigger a warning if the argument is not an array)
  for ($i = 0; $i < $narrays; $i ++) {
   if (!is_array($arrays[$i])) {
   // also array_merge_recursive returns nothing in this case
     trigger_error('Argument #' . ($i+1) . ' is not an array - trying to merge array with scalar! Returning null!', E_USER_WARNING);
     return;
    }
  }

    // the first array is in the output set in every case
  $ret = $arrays[0];

  // merege $ret with the remaining arrays
  for ($i = 1; $i < $narrays; $i ++) {
    foreach ($arrays[$i] as $key => $value) {
     /***  KEEP THIS COMMENTED OUT TO KEEP THE ORIGINAL KEYS
     //if (((string) $key) === ((string) intval($key))) { // integer or string as integer key - append
     //   $ret[] = $value;
    // }
    // else { // string key - merge
      if (is_array($value) && isset($ret[$key])) {
        // if $ret[$key] is not an array you try to merge an scalar
        // value with an array - the result is not defined (incompatible arrays)
        // in this case the call will trigger an E_USER_WARNING and the $ret[$key] will be null.
        $ret[$key] = array_merge_recursive2($ret[$key], $value);
      }
      else {
        $ret[$key] = $value;
      }
           // }
    }
  }
  return $ret;
}


So after I created the arrays with all the links I create the sitemaps. The first one here is an xml sitemap used for the robots.txt file.
Its really simple and used the globallinkarr array.

XML Sitemap

function createXMLSiteMap($globallinkarr){
  $xml = '<?xml version="1.0" encoding="UTF-8"?>
    <urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">';
   if(count($globallinkarr)){
   foreach($globallinkarr as $val){
     if(!preg_match('/http(s)?:\/\//', $val)){
       $val = 'http://'.$val;
     }
     $xml .= '
       <url>
          <loc>'.str_replace('&', '&amp',$val).'</loc>
       </url>';
    }
  }
  $xml .= '</urlset>';
  return $xml;
}


The html sitemap is created using a recursive function that goes through depthlinkarr. Also it checks if the link is valid if it isn't in the globallinkarr since all those are already checked. When it does check it only needs the headers so to speed things up I set the curl option CURLOPT_NOBODY to true. The page was timing out on me a lot but with this option set and checking to see if it already existed in the globallinkarr helped stop it from timing out. But if you have a whole lot of links there is a good chance this will cause your page to timeout.

The HTML Sitemap

function createSiteMap($depthlinks, $before = ''){
  global $globallinkarr;
  global $pagetitles;
  $validcodes = array(200,301,302);
  if(count($depthlinks)){
  $sitetree = '<ul style="padding:5px; margin:5px;">';
  foreach($depthlinks as $key=>$val){
    if(is_array($val)){
      if($before) $newbefore = $before.'/';
      $newbefore .= $key;

      $newkey = preg_replace('/^http(s)?:\/\//', '', $newbefore);

    $title = ($pagetitles[$newkey] != "") ? $pagetitles[$newkey] : $newbefore;
      if(!preg_match('/^http(s)?:\/\//', $newbefore))
         $newbefore = 'http://'.$newbefore;
      $exist = 0;
      if(in_array($newbefore, $globallinkarr)){
        $exist = 1;
      }else{
        $test = new Crawler($newbefore, 1);
        $info = $test->get('info');
        if(in_array($info['http_code'], $validcodes))
          $exist = 1;
        }
        if($exist){
          $sitetree .= '
           <li><a style="display:block;" href="'.$newbefore.'"
           target="_blank" title="'.$title.'" />'.$title.'</a></li>';
        }else{
          $sitetree .= '
             <li>'.$title;
        }
        $temp = createSiteMap($val, $newbefore);
        if($temp){
          $sitetree .= $temp;
          $sitetree .= '</li>';
        }
      }else{
        if($before != '') $newval = $before.'/'.$val;
        else $newval = $val;
        $newkey = preg_replace('/^http(s)?:\/\//', '',$newval);
        $title = $pagetitles[$newkey] ? $pagetitles[$newkey] : $newval;
        if(!preg_match('/^http(s)?:\/\//', $newval))
           $newval = 'http://'.$newval;

        $exist = 0;
        if(in_array($newval, $globallinkarr)){
            $exist = 1;
        }else{
          $test = new Crawler($newval, 1);
          $info = $test->get('info');
          if(in_array($info['http_code'], $validcodes))
            $exist = 1;
        }

        if($exist){
          $sitetree .= '
            <li><a href="'.$newval.'" title="'.$title.'"
                target="_blank">'.$title.'</a></li>';
        }
      }
    }
  $sitetree .= '</ul>';
  return $sitetree;
  }
}


Categories: Tutorial Tags: ,

Execute Code After Browser Finishes Loading

November 25th, 2009 kmussel 1 comment

How to execute a script after the browser stops loading

Recently I needed to execute a bit of code but the browser was timing out. I was actually using the php exec function to tar up some files. The browser kept showing a time out page. So in order to make the browser think it was done loading and then execute this bit of script, I put everything in the buffer with ob_start(). Then when I’m ready to stop the browser I get the size of the buffer. I then set the header content-length equal to this size and flush out the buffer. Now the browser will no longer show that its loading, since it has received all the content it is going to receive. So now you can execute any script.

Here is the code


<?php
ob_end_clean();
header("Connection: close");
ignore_user_abort();  // optional
ob_start();

echo "some content";

$size = ob_get_length();
 header("Content-Length: $size");
 ob_end_flush();
 flush();
//Browser done loading

//put your script here

?>

Categories: Tutorial Tags:

Round Robin Algorithm

November 17th, 2009 kmussel No comments

Generating a Schedule Automatically

I need to create a way for every team to play each other in each round of games. I first started out creating a chart of who each team will play. After I created a chart that worked I built an algorithm to build that chart.

The Game Schedule

The Teams: Team 1 Team 2 Team 3 Team 4 Team 5 Team 6
Rounds: Round 1 Team 6 Team 5 Team 4 Team 3 Team 2 Team 1
Round 2 Team 4 Team 6 Team 5 Team 1 Team 3 Team 2
Round 3 Team 2 Team 1 Team 6 Team 5 Team 4 Team 3
Round 4 Team 5 Team 3 Team 2 Team 6 Team 1 Team 4
Round 5 Team 3 Team 4 Team 1 Team 2 Team 6 Team 5



Now you just need to figure out the pattern and we can code it up. I was told there is a name for this pattern but I didn’t know it, so if you know it let me know.

The Variables

$gamearr AND $tempgamearr are both an array of all the teams. The array would look like this: $gamearr[0] = “firstteam”, $gamearr[1] = “secondteam” and so on.


$numteamspadded is the number of teams. If the number was odd I add another team to the end of $gamearr and $tempgamearr as a “byteam”.


$gamenumperteam is however many number of games you want each team to play.

The Logic

As you can see at the beginning I set the variable $firstteam. You realize why I did this if you figured out the pattern above. The pattern above being that I have an array of teams playing the array of teams in reverse order. After each round I decrement the reverse order array and move the last one to the front. So we would have 654321 and then 165432 and then 216543. This would cause teams to play themselves though which is where the $firstteam comes in. Every time a team would play itself we switch it out with the firstteam.


I start out by looping through the number of games and then looping through just half of the teams since I’m setting both the home and away team in there. If I looped through all the teams I would have 1 vs 6 and then 6 vs 1 but I just want the unique games.


I then loop through all the games and set the $gamearr to the values that it would be had I been just decrementing the array and moving the last item to the beginning. Meaning the gamearr will look like this after each round 234561, 345612, 456123, etc. I use the $tempgamearr because I need to know the original order of the teams since we have to switch the first team out when there is a game playing itself.

After this I remove the first team from the array. I then loop through the game to find if one of the teams will be playing itself and get its value and position. This is one of the reasons why I remove the first team from the array. If I left it in there then 1 would play itself and overwrite the fact that another team was playing itself.

I then switch the team that is playing itself with the $firstteam.


After this you have an array of the games for each round.

I then create an array of all the games and check to see if the “byweek” is playing. If it is I don’t add it to the array cause we don’t want a byweek taking up a game slot.

The Round Robin Algorithm


$bottom = $numteamspadded-1;
$half = $numteamspadded/2;

$firsteam = $gamearr[0];
for($i=0; $i<$gamenumperteam; $i++){
    for($j=0; $j<$half; $j++){
         if($numteamspadded==4)
           $rrarr[$i][$j]['home'] = $tempgamearr[$j];
        else $rrarr[$i][$j]['home'] = $gamearr[$j];
        $rrarr[$i][$j]['away'] = $gamearr[$bottom-$j];
    }

    for($j=1; $j<=$bottom+1; $j++){
        $start = ($i+$j)%$numteamspadded;
        $gamearr[$j-1] = $tempgamearr[$start];
    }

    array_splice($gamearr, array_search($firsteam, $gamearr), 1);
    foreach($gamearr as $key=>$val){
        if($tempgamearr[$bottom-$key] == $val){
              $TempGameValue = $val;
              $switch = $key;
          }
    }

    $gamearr[$bottom] = $TempGameValue;
    $gamearr[$switch] = $firsteam;
}
foreach($rrarr as $key=>$val){
  foreach($val as $gkey=>$games){
    if($games['home'] != 'byweek' && $games['away'] != 'byweek'){
      $allgames[] = $games;
    }
  }
}



UPDATE: I came across another good implementation of the round robin here at http://phpbuilder.com/board/showthread.php?p=10935200

Categories: Tutorial Tags: ,

Sorting with Umlauts

November 15th, 2009 kmussel No comments

Recently I needed to have a drop down box for countries. In english I just simply order by name but when you look at the german translation, ordering by name puts all the countries that have an umlaut character at the bottom. For example, I know the German translation for Austria is Österreich. So when I sort the translated names I now want this name to appear after the country named Oman. I know that the german umlaut html entity for ö is &ouml. I use that to get the character to sort the countries with.
Here is the code using PHP.

foreach($country as $val){
  $charset = htmlentities(utf8_decode($val['country_name']));
  if(substr($charset, 0,1)== '&'){
    $newcharset = str_replace(substr((html_entity_decode($charset)), 0,1),
                substr($charset, 1,1), html_entity_decode($charset));
    $origcountry[$val['country_id']] = $val['country_name'];
    $testarr[$val['country_id']]= $newcharset;
    $swap[$val['country_id']] = $newcharset;
  }else{
    $testarr[$val['country_id']] = $val['country_name'];
  }
}

asort($testarr);
foreach($testarr as $ckey=>$val){
  if($key= array_search($val, $swap)){
    $newcountryarr[$ckey] = $origcountry[$key];
  }else{
    $newcountryarr[$ckey] = $val;
  }
}
Categories: Tutorial Tags:

Scrolling Text using jQuery

October 30th, 2009 kmussel 1 comment


Animating Text using jQuery Examples

Scroll Text Up
+++First Lorem ipsum dolor sit amet, consectetur adipiscing elit.
+++Second Lorem ipsum dolor sit amet, consectetur adipiscing elit.

Scroll Text to Left mouseover to stop the animation
+++Lorem ipsum dolor sit amet, consectetur adipiscing elit.     

A client of mine recently wanted the option to have scrolling text for breaking news type items. For the most part I think that scrolling text isn’t the greatest thing to use but there are certain situations where its good. The real simple and fast way to do it is to simply use a <marquee> tag like this <marquee width=”100%;” behavior=”SCROLL” direction=”left” scrollamount=”10″> Lorem ipsum doler </marquee>

The problem with this is it doesn’t do a continuous loop. What I mean by this is that it doesn’t start over till the text has completely finished scrolling. This means you see a lot of white space. Also jQuery seems to be a smoother animation. I knew jQuery had the animate function, so I used that. I found some plugins and examples where they had images being repeated but said they couldn’t do text cause they didn’t know the width. I guess they didn’t know css. So lets start with the css/html part of it.

Scrolling Text to the Left

The first thing we need to do is to get the width of the text that is being scrolled. So we need to create a div wrapper and set the width to be really big. This way the text wont be wrapped because of parent elements. We also set the display to none and visibility to hidden. This is done so that we don’t ever see this text. The display none keeps the browser from rendering the div in the browser, otherwise with just the visibility set to hidden we would see a big white space. Then we add another element inside with the text.


<div id="textwrapper" style="width:5000px; display:none; visibility:hidden;">
  <span id="textwidth" style="disply:none;">
    +++Lorem ipsum dolor sit amet,  consectetur adipiscing elit.
    Sed magna  ligula, tempus feugiat pellentesque et,pulvinar
    eu tellus. &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
  </span>
</div>
;


Now the html for the actual text being scrolled. We have a scrollwrapper element which contains the width of the the text being scrolled. We also need to set the position to relative so that the text being scrolled will be absolutely positioned relative to this element and not the page. The next element is used to make sure the text doesn’t wrap just like we did previously, we set the width to an arbitrarily large number. Then we have the scrollcontent element. This is the element that is going to be moving. This is positioned absolutely and we set the left position to the width of the scrollwrapper element to make sure it starts on the far right. Then we need one more wrapper inside.


<div id="scrollwrapper" style="overflow:hidden; border:1px solid #004F72;
      position:relative; width:500px; height:20px;">
  <div style="width:5000px;">
     <span id="scrollcontent" style="position:absolute; left:500px;">
       <span id="firstcontent" style="float:left; text-align:left;">
             +++Lorem ipsum dolor sit amet, consectetur adipiscing elit.
               Sed magna ligula, tempus feugiat pellentesque et, pulvinar
             eu tellus.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
       </span>
    </span>
  </div>
</div>



Here is the javascript but first let me explain how I am using the jquery animation function. The first object passed to it is what I’m animating. I am changing the property “left” to go to the negative of the scrollwidth. The next thing I pass to it is an object of some of the properties. The first property I am setting is “step”. This is a function that will get called everytime the animation runs. The next property is “duration” which is the amount of time it will take to finish the animation in milliseconds. The next is “easing” which is the equation used to do the animation. jQuery comes with 2 equations: linear and swing. Default is swing but we’ll set it to linear. The last property we’ll set is “complete” which is a function that’ll be called when the animation is done.


$("#textwrapper").css({"display":"block"});
var scrollwidth = $("#textwidth").width();
$("#textwrapper").remove();

var scrollwrapperwidth = $("#scrollwrapper").width();
if(scrollwidth < scrollwrapperwidth) scrollwidth = scrollwrapperwidth;
$("#scrollcontent").css({"width":scrollwidth});
$("#firstcontent").css({"width":scrollwidth});

var appending = scrollwrapperwidth-scrollwidth;
var noappend = 0;

function animatetext(rate){
  var dist = scrollwidth+parseFloat($("#scrollcontent").css("left"));
  if(!rate)rate = 1;
  var duration = Math.abs(dist/(rate/100));
  $("#scrollcontent").animate({"left":"-"+scrollwidth},{
    step: function() {
      if(parseFloat($("#scrollcontent").css("left"))< parseFloat(appending)
          && !noappend){
          noappend = 1;
          $("#scrollcontent").css({"width":scrollwidth+scrollwidth});
          $("#scrollcontent").append("<span style='float:left; text-align:left;
               width:"+scrollwidth+"px;'>"
               +$("#scrollcontent").children(":first").html()+"</span>");
      }
    },
    duration: duration,
    easing: "linear",
    complete:function(){
      $("#scrollcontent").children(":first").remove();
      $("#scrollcontent").css({"left":0});
      $("#scrollcontent").css({"width":scrollwidth});
      noappend=0;
      animatetext(6);
    }
  });
}
$("#scrollcontent").mouseover(function(e){
	$("#scrollcontent").stop();
});
$("#scrollcontent").mouseout(function(e){
	animatetext(6);
});

$(document).ready(function(){
	animatetext(6);
});


First in the javascript we will get the width of the text. We first need to set the css of the textwrapper to "block" so that it will render the child elements width. Then we will get the width of the inner element "textwidth" and then delete the textwrapper element.
If the javascript variable "scrollwidth" is less than the width that we want it to scroll we need to set it. Then we set 2 variables, appending and noappend. These variables are used in the "step" function. So when the position of the scrolling text is less than the position "appending" and we haven't already appended text (the noappend flag), then we'll set the width of the scrollcontent to double the width since we are appending the same text in there again. Then when the animation is completed we will remove the first element, change the left position to 0, change the width of the scrolling content back to the scrollwidth and then call this function again. Also if we want to stop the animation on mouseover as I have it, we simply call the .stop().

NOTE: since the .animate function takes a duration and not a speed, to keep the same speed we need to calculate the duration. That way if you are dynamically changing the text the speed wont change just because you have more or less text. To do this it is pretty straight forward. Since we are using linear as our easing property, the equation is simply d=rt, where d is the distance we need to travel and r is the rate and t is the time. So we get the distance by taking the scrollwidth and adding it to the current left position of the scrollcontent. Then we simple pass in a rate of 1- whatever and calcuate the time in milliseconds.

Scrolling Text Up

Scolling text up is even easier. The html looks like this. We need a wrapper with position relative and height equal to whatever you want. Then we need the child element which will be the element being moved. Then we need at least one element inside that to contain the text but can have more if you want. Also the line-height needs to be set to whatever the height is of the outerwrapper.


<div id="scrolltextup" style="border:1px ridge #004F72; overflow:hidden;
     position:relative; width:500px; height:20px;">
  <div id="textup" style="text-align:center; position:absolute; top:0;
      left:0; width:500px;">
    <div style="line-height:20px;">
      +++First Lorem ipsum dolor sit amet, consectetur adipiscing elit.
      +++Second Lorem ipsum dolor sit amet, consectetur adipiscing elit.
    </div>
  </div>
</div>



Here is the javascript to do it. We get height of the entire thing. This time we are change the "top" property. Since the distance to animate will always be the same we don't need to calculate duration and can just pass in the duration.


var scrollheight = $("#textup").height();

function scrolltextup(dur){
  $("#textup").animate({"top":"-=20"},{
    duration: dur,
    easing: "linear",
    complete:function(){
      $("#textup").children(":last").after("<div style='line-height:20px;'>"+
          $("#textup").children(":first").html()+"</div>");
      if($("#textup").children(":first").height() <=
           (parseInt($("#textup").css("top"))*-1)){
        $("#textup").children(":first").remove();
        $("#textup").css({"top":0});
      }
      setTimeout("scrolltextup(3000)", 500);
    }
  });
}



And thats it!

Categories: Tutorial Tags: , ,

Create Images From HTML

August 15th, 2009 kmussel No comments

The Problem:

I want a simple way to create an image from dynamically generated html.

So Recently I’ve been working a lot inside tinymce, a javascript html WYSIWYG editor. I’ve wrote a couple plugins to manage/upload files and images utilizing my flash uploader. Tinymce has a couple plugins you can buy, but if you’re a developer seems like a waste of money. Maybe I’ll write a basic tutorial on how to upload pics and insert them into tinymce next time. Anyway on top of that I wanted tinymce to work like word in that it would have paging. Once I got that paging working, for the most part, I wanted to have thumbnails of each page. This is where my problem comes in. Basically each page in tinymce is wrapped in a div with a unique id. Therefore I have access to the html of each page, but how can I create an image from just a string of html? I looked all over the web and there were tools to do it but all of them cost some money and seemed more complicated than it should be. I knew I needed some way to render the html server side. There are tools out there that are open source like Gecko and Webkit, but this just seemed more complicated than it should be to create an image.
So I started thinking of other ways and I knew specifically that php has built in pdf support. I ended up finding dompdf. The rendering engine for this seemed to be really accurate and supports both inline styles and css. After creating the pdf I found that ImageMagick can convert pdfs to an image using GhostScript, an interpreter for the PostScript language and portable document format.
After those are installed, it is really simple. In my situation I’m updating the thumbnails via ajax to keep them up to date. I’m also using jQuery to make the ajax call. I pass the id of the page and the content of the page. I then return the id of the page with the name of the image separated by a colon. Also if you were wondering, the id of the actual page is the same as the id of the thumbnail. This can be done because tinymce is actually in an iframe so technically there is only one id per page. Side Note: “Apparently a lot of people don’t realize that ids are supposed to be unique per page. If you want to style more than one element use classes not ids. People then tell me, ‘But I’ve never had a problem with using the same id.’ It’ll render just fine but if you ever use javascript and use document.getElementById(‘someid’) then you’ll have a problem. Anyway I digress, back to creating images.” Here is the code to make the ajax call.


   $.post('ajax/test.php', {id:pageid, content:str}, function(data){
	var d = data.split(':');
	$('#'+d[0]).html('<img src="'+d[1]+'" alt="thumbnail" />');
  });



Now here is the ajax page that actually does the conversion. I first create the pdf from the content I passed to it. I have to add the <html> <body> tags for this to work correctly. There is also a lot of things you can do when creating the pdf, just look at the documentation to learn more. I catch the output of the pdf and then put the content into a file called test.pdf. I then use the time() function to create a unique image name so the browser wont display a cached version of the image. Finally I call the system function which is used to execute an external command. In this case the command is ImageMagick’s convert function. Side Note: When trying to run “convert” in Windows without the path in front it will possibly fail because it is trying to execute Windows convert program. There are a couple ways to get around it. One way being to look in the PATH environment variables and set the ImageMagick path closer to the front in the PATH system variables so that it comes before the Windows convert program. Some people also said that changing ImageMagick’s convert.exe name to imconvert.exe and call that instead will solve the issue.

   
require_once("../dompdf-0.5.1/dompdf_config.inc.php");

 $id = $_POST['id'];
 $html = '<html><body>'.html_entity_decode($_POST['content']).'</body></html>';

 $paper = 'letter';
 $orientation = 'portrait';

 $old_limit = ini_set("memory_limit", "32M");

 $dompdf = new DOMPDF();
 $dompdf->load_html($html);
 $dompdf->set_paper($paper, $orientation);
 $dompdf->render();
 $pdf = $dompdf->output();
 file_put_contents("test.pdf", $pdf);

$imagesample =  'sample'.time().'.jpg';

$source = 'C:\\your\\director\\here\\test.pdf';
$dest = 'C:\\your\\directory\\here\\'.$imagesample;
system("C:\\ImageMagick-6.5.4-Q16\\convert.exe $source $dest", $ret);

echo $id.':'.$imagesample;

And that is it! Cheers!

Categories: Tutorial Tags: ,