Click or scroll down Circle me on Google+ Fork me on GitHub Follow me on Twitter Ask me on Stack Overflow Gild me on Reddit Code Ninja, Entrepreneur, Idiot ChalkHQ — consulting, prototyping, mentoring HighF.in — resolve innefficiencies in your startup's workflow DearDrum.org — online open-mic / creative space The Dirac Equation (click to WikiPedia) A maxim Sun Tzu references in his magnum opus The Art of War

If you know the enemy and know yourself, you need not fear the result of a hundred battles.
If you know yourself but not the enemy, for every victory gained you will also suffer a defeat.
If you know neither the enemy nor yourself, you will succumb in every battle.
Fork me on GitHub

Tags

actionscript ad-hoc networks Adobe AIR anonymous Apple array Browsing convert Debugger Error Facebook file permissions Flash Flex fonts function future Google Google Plus grid hackers html javascript logs loop network p2p php privacy regexp Security Server social ssl technology terminal time Twitter upgrade Web 2.0 Web 3.0 Web 4.0 Web 5.0 wordpress

Featured Posts

  • Javascript: Undefined parameters
  • The Web, A Look Forward
  • Let Postfix send mail through your Gmail Account – Snow Leopard
  • Archives

  • April 2013
  • December 2011
  • July 2011
  • June 2011
  • March 2011
  • February 2011
  • January 2011
  • November 2010
  • October 2010
  • September 2010
  • July 2010
  • May 2010
  • Categories

  • Code
  • Design
  • Opinion
  • Security
  • Tools
  • Uncategorized
  • Latest Posts

    Flex: Variables, Anonymous Functions, and For Loops

    I just ran into some weird behaviour involving a for loop, some variables, and a bunch ofanonymous functions. This is in Actionscript 3.0 using Flex SDK 3.4 and current Google Maps API(as of the date of this post&mdash I read somewhere they're rolling out a new version although it's not really relevant for this post)

    So below I have a function that loops through the xml result of an http service, for each item in the result it creates a marker on a map and gives that marker a click event. When you click on a given marker I want a window to pop up with the name and description of that location, so the following is the code you'd expect to write. For simplicity sake you can keep an eye on the i:int variable which will help clarify the issue.

     
    //trace(i) will always output total items in the xml result
    private function processResult(event:ResultEvent):void {
    
      var total:int = event.result.data.item.length;
    
      for (var i:int = 0; i<total; i++) {
        var item:Object = event.result.data.item[i];
        //this will create the marker object
        var marker = new Marker(new LatLng(item.lat, item.lng), new MarkerOptions({fillStyle: {color: 0xEE9C21}, radius: 7, tooltip: item.name}));
    
        marker.addEventListener(MapMouseEvent.CLICK, function():void {
          //this will open an info window when the marker is clicked
          map.openInfoWindow(map.getCenter(), new InfoWindowOptions({hasTail: true, tailHeight: 5, hasShadow: true, title:item.name, contentHTML:item.description}));
          trace(i);
        	});
      map.addOverlay(marker);
      }
    }

    Now what you'll find with the above code is that no matter which placemark you click on, they will all show the same name and description. Say that there are 5 items in the xml result, tracing i will output the number 5.

    If you're new to programming, yes i will be 0 during the for loop's first run. Yes having 5 items and starting at 0 means it should be 4 for the last run, but the value of i increments one last time to make the i<totalcondition false before it exits the loop, so essentially it uses the final value of i for all the placemarks which is 5.

    I can't see any reason why this should be happening other than language or framework immaturity.

    The solution; or I should say the easiest, quickest solution, is to create an external function for marker creation that is called by the for loop, which for clarity's sake will only contain the part that's required to explain the concept and make it work ie: adding an event listener to the marker, but in the real world should have all the code necessary for creating a marker - that way you'd have an independent marker creation function you could call from anywhere in the application. Below is the working code:

     
    //trace(i) will output the correct index depending on the placemark clicked
    private function processResult(event:ResultEvent):void {
    
      var total:int = event.result.data.item.length;
    
      for (var i:int = 0; i<total; i++) {
    
        var item:Object = event.result.data.item[i];
        var marker = new Marker(new LatLng(item.lat, item.lng), new MarkerOptions({fillStyle: {color: 0xEE9C21}, radius: 7, tooltip: item.name}));
    
        //call external function and pass variables to it
        placeMarkerAddClickEventListener(marker, item.name, item.description);
        map.addOverlay(marker);
      }
    }
    
    //external function
    private function placeMarkerAddClickEventListener(marker:Marker, name:String, description:String):void {
    
      marker.addEventListener(MapMouseEvent.CLICK, function():void {
    
        map.openInfoWindow(map.getCenter(), new InfoWindowOptions({hasTail: true, tailHeight: 5, hasShadow: true, title:name, contentHTML:description}));
        });
    }

     

    Disable Flash Debugger Error Messages

    If you have Adobe CS, Flex Builder, Flash Builder or otherwise use the Debuggerversion of Flash Player you quickly realize that a lot of sites out there don't bother with error handling in their apps and widgets.  This sucks because everywhere you go you get these error messages and all you can do is click them away and contact the developers, who if they cared would have dealt with the errors in the first place.

    You can easily disable these error messages and then just re-enable them when you're debugging something. So here's how to do that:

    1. Find or create a file called mm.cfg in the following folder:
      OS X: /Library/Application Support/Macromedia
      Win XP: C:\Documents and Settings\username
      Win Vista: C:\Users\username
      Linux: /home/username
    2. Add the following line to the file and save it:
      SuppressDebuggerExceptionDialogs=1
    3. That's it, to turn debugging back on change that value to 0

     

    The Web, A Look Forward

    The internet is beginning to fold in onto itself, everything is integrating with everything else, and content is becoming redundantly accessible – in a good way. Rss, PubSubHubub, Wave, the Twitter Api, etc. Twitter is a great example because it's open and almost ahead of it's time in that respect. You can get Twitter data in many different formats using intermediate servers and networks, and you can use 100's of interfaces and devices not just to read content but publish and interact with your account. This is happening all over the web, from Google Wave to self hosted WordPress blogs.

    Web 2.0 was about web applications escaping the page refresh model, and having customized content aggregated for and pushed to you. The next big step moving forward is going to be about collaboration amongst users, which is going to skyrocket and permeate everything – if you think of Wikipedia as a seed the tree grown from it is about to release millions of spores, think social networks and comment systems everywhere, and other new forms of user created and collaborated content; and networks and web servers are going to collaborate with each other as well to make each other's content more available and redundantly rooted in the network. The integration between online and offline will be further refined so that the mainstream notion of connection is no longer binary, but rather a matter of time and network penetration. It'll be taken for granted that when connections are possible it will be made by the application and the user will be extracted from the process of managing or thinking about the connection.

    You'll post to Twitter, if Twitter is unreachable the message will be queued while the application attempts a direct connection with your Twitter followers bypassing the central network until it's back online. Or it may push the message to a 2nd server, which will queue it up to be synced when Twitter comes back online allowing you to power off your device. The same way we use graceful degradation in web design, we will adopt and apply the practice of graceful degradation to Networking.

    Web 3.0 will be coloured by independent video and audio content and all that goes with it as a result of technology becoming cheaper and improving quality; and dinosaur mindset, ill-equipped organizations like the RIAA and traditional tv, news, and print networks having to open up or face a painful collapse. But the essence of Web 3.0 will be about collaborative abundance and ubiquitous-automatic-self healing-graceful degrading networks. Web 3.0 will also be about the soft walls of compatibility, language and connection dissolving.

    Web 4.0 will be about hard walls dissolving. If you think of the mobile web browser as the seed – our phones, our desks, our wallpapers, the solar panels on our roofs, our cars, dishwashers, fishbowls, and house plants will be tightly integrated into the network. There are lots of products out already that do all of the above, but a mindset of the masses will need to be adopted of, "Well why shouldn't I have the time left till my dishes are ready, or the pH balance of my fish bowl accessible from my phone/laptop/bedroom/car, why shouldn't all my relevant data be pushed to me live wherever I am, and why shouldn't I be able to respond to the event using whatever interface I have handy?"

    Web 5.0 will be about redundancy of the physical nodes in the network. Having an instant message conversation with your neighbour won't require a round trip to your ISP. You'll just connect directly via the networking equipment local to your devices, homes, or apartment buildings. The physical network will adopt graceful degradation. If your iPhone switching from WiFi to 3G as you walk down the street is the seed – You'll be stuck in traffic out of cell phone range and instead of having no signal as it tries to ping a tower your device will connect to a device in the car behind you etc. in a relay to the central network, or bypassing the network entirely if the destination can be reached before or without the central nervous system of the network. This kind of ad-hoc relay tech is already being worked on by Cisco and others.

    The web is the backbone that will provide the content, integration, and the motive to move through these cultural and infrastructural changes. Those that say Web 2.0 is about mere gradient designs, html specifications, and tags are missing the point. The web n.0 naming convention is about cultural shifts centered around the use of the web, and the 'web' is really just an affectionate term we use for an array of networking activities as they all become integrated with each other. www is now just another subdomain of the web.

     

    WordPress Automatic Upgrade

    For a few versions now WordPress has let you automatically upgrade it and your plugins. Every time an update would come around I'd try figure out how to activate it and fail. As a last resort you can specify ftp/ftps details and have it upgrade that way, but who wants to setup an ftp server right?

    Anyway, it turns out that aside from setting file permissions like everyone tells you to do to setup the automatic upgrade feature, the actual missing piece of the pie was to give ownership of the entire wordpress directory to the owner of the apache process.

    So, step 1: open up terminal and ssh to your server(use your ip address instead of all those 9s)

    # ssh root@99.99.999.999

    # [password]

    step 2: Now you're running a remote session to your server, open top

    # top

    step 3: Expand the window and look for processes name httpd or apache2, chances are they're owned by the user www-data. Say you have wordpress installed in /var/www/, enter in:

    # chown -R www-data /var/www

    The above command changes the ownership of /var/www, which is a folder, recursively so it goes through and changes ownership of all the files and folders below it, and it's changing ownership to the user www-data.

    Now log into wordpress and try auto upgrade.

     

    Flex 3-RegExp: Find Urls In Text And Html

    There are a number of situations where you'd want to grab the urls from a block of text. For example you may be loading in some external or dynamic data and want to make the links clickable, or change their colour. Regular expressions are used in a multitude of languages; they define patterns that can be matched against a string, thus certain key characters used in defining a RegExp have to be escaped so they are interpreted as special characters like \d matches any digit. In Actionscript, you can define a RegExp by either wrapping it in double quotes "", or forward slashes//. In each case you would have to escape any characters that match the wrapping in addition to the characters that need to be escaped in the actual pattern. Further more Actionscript requires you to separate out the last part of the regular expression, called flags, and insert it as the second argument when defining a new RegExp object.

    Here's how you find a url in text or html:

    var str:String = new String('This is a url www.fightskillz.com, and this is another one: <a href="http://chalk-it-out.com">Chalk It Out</a>');
    var reg:RegExp = new RegExp("\\b(((https?)://)|(www.))([a-z0-9-_.&amp;=#/]+)", 'i');
    var result:Object = reg.exec(str);
    trace(result[0]);

    First off if you're new to Flex/Actionscript you have to copy and paste this into a function and the variables created will only be accessable within that function while it's running as they are created and destroyed as it runs. If you wanted more permanence you'd just define the variables outside the function.

    Now Let's break it down. The first \ is used as a character escape for Actionscript. In actionscript when defining a string within double quotes you'd escape a double that's part of the string like this "Look at this double quote \""\b searches for a word boundary ie: a whitespace, or the beginning or end of a string.The next part ((https?)://)|(www.))defines the first part of a 'word' that passes for a url. It's made up of two substrings, the first looks for http, the question mark deems the preceding character optional, so it'll match to https as well. It then looks to see if the protocol is followed by ://. The |character means OR, so if there is no protocol specified, it checks for (www.). Next we have [a-z0-9-_.&=#/] which is a list of characters a to z, 0 to 9, and various others commonly found in urls. This is followed by a + which instructs the pattern to match the preceding list of characters until it can't anymore. It can't anymore when it reaches whitespace, a single or double quote, brackets, or any other non-url character. Finally the RegExp flag i informs the pattern to be case insensitive.

    reg.exec(str); executes the pattern on the specified string and returns the results as an array. Since the example is only designed to match the first url it encounters and then stop, the array will only have one result. The method reg.exec(str) is interchangable withstr.match(reg)

     

    Convert Milliseconds to Time (H:M:S)

    Converting milliseconds to a time string can be a pain, especially when you're measuring something dynamic. In most languages I've come accross the Date object is calculated by the number of milliseconds that have passed since Jan 1, 1970. Because the different parts of a date are based on different bases ie: 60 minutes in an hour, 24 hours in a day etc. It's a lot easier to get the milliseconds passed since Jan1, 1970 and work with that value. This only works if you want to get the difference between two dates. If you were to subtract two dates(expressed as milliseconds) and get 432000000 milliseconds(5 days), then convert that to a Date object, the code would interpret 432000000 as Jan 6, 1970.

    In another scenario I was just writing a podcast player in Flex 3/AIR and wanted to convert the Sound.length and SoundChannel.position values, both of which are measured in milliseconds, and display the length and current position of the episode in formats that would make sense. So I wrote a generic function that accepts millisecondsas an argument and returns the formatted time string.

      /**    Milliseconds to Time String in Flex 3              **/
      /**    Author: Yoav Givati [http://fightskillz.com]       **/
    
    public function fnMillisecondsToTimeCountUp(time:Number):String {
    
    	//calculate playtime from milliseconds
    	var h:Number = new Number(Math.floor(time/1000/60/60));
    	//minutes left shows total minutes left plus hours, 1h5m = 65mins
    	//so we subtract the amount of 60's added by the hours to get just minutes
    	var m:Number = new Number(Math.floor(time/1000/60)-(h*60));
    	//seconds left
    	var s:Number = new Number(Math.floor(time/1000)-(m*60));
    
    	//create string variables
    	var hours:String;
    	var minutes:String;
    	var seconds:String
    
    	//make sure minutes and seconds are always two digits
    	if(m.toString().length == 1) {
    		 minutes = "0"+m;
    	} else {
    		 minutes = m.toString();
    	}
    
    	if(s.toString().length == 1) {
    		seconds = "0"+s;
    	} else {
    		seconds = s.toString();
    	}
    
    	//if hours or minutes are 0 we don't need to see them
    	if(h == 0) {
    		hours = '';
    		if(m == 0) {
    			minutes = '';
    		} else {
    			minutes = minutes+":";
    		}
    	} else {
    		hours = h+":"
    		minutes = minutes+":";
    	}
    
    	// after 1 hour passes the seconds become 4 digits long
    	// the last two of those digits represent the actual seconds
    	seconds = seconds.slice(seconds.length-2, seconds.length);
    	return hours+minutes+seconds;
    
    }

    You'll notice that I'm using Math.floor(), it's crucial that you round down, because the way the hours are being calculated for example, rounding up would show one hour had passed after only a fraction of an hour, just rounding up the minutes or seconds would cause everything to be out of sync and the math would be concussed. For those of you who are confused I should clarify that Math.floor(1.8) would return a value of 1 and Math.ceil(1.3) would return a value of 2, the term 'round' is probably a misleading. If you were using this function to count down instead of up, you would useMath.ceil()(although still not for the hour value), you essentially want to stay on the 'other side' of the minute or second for as long as possible.

     

    Passing a Multi-dimensional Array Between Javascript And Php.

    Passing data between client and server is pretty straight forward, we use HTML structured forms and AJAX calls to put data up, and echo/print methods to bring it down. The data types transmitted are usually strings and numbers. Unfortunately Javascript and Php don't have built in conventions for you to pass arrays or objects between one another. This article shows you how to pass an array from server to client, and then from client to server. Looking around Google there are a number of other developers who've found ways to do this, but the methods they use tend to limit the number of tiers in the array being passed from client to server, use up unwarranted resources for multiple form items and variables to hold each array item, and limit your overall control of the task. This method focuses on getting your data from an array to a string and back again using 1 hidden input, 1 variable, and allows you to have as many tiers to yourarray as you have characters to use as delimiters.

    Passing an array from Php to Javascript is quite simple, because our array starts in Php, and Php is parsed first by the server. The whole process can be done in one block of code. Loop through the array in Php echoing it into Javascript code, which when parsed by the clients browser will generate a Javascript array.

    Say we have a Php array:

     array("model" => "Prophecy Les Paul Ex", "neck" => "Mahogany"),
         "Fender" => array("model" => "Lite Ash Telecaster", "neck" => "Birdseye Maple" ),
         "Washburn" => array("model" => "Idol WI15", "neck" => "Rosewood")
         );
    ?>

    On the page to be served add the following Php which will loop through the arraygenerating the Javascript code to re-create the array on the client-side. You may also want to wrap the generated Javascript in a function if you don't want thearray to be generated on page load, or want to be able to refresh/reset the array:

     
    var Guitars = new Array();

    That's it.

    Now if you want to pass the array back from Javascript to Php it's a bit more complex. We'll use the Javascript array Guitars that we just created. First we'll need an HTML form:

     
    <form method="post" action="/example.php">
    </form>

    Note the use of both id and name. Name will be assigned to the posted variables we'll need to pick up on the server, as for referring to the input in Javascript you could use the getElementByName(); but I find it to be less reliable and harder to keep track of which elements have a name and which have an id. Using id throughout your application is more uniform.

    Anyway remember we still have the array Guitars from before, now we need to write the function called by the Submit button:

     
    function fn_SubmitForm() {
         arr_Guitars = document.getElementById('arr_Guitars'); //get the element
         arr_Guitars.value = ""; //make sure the value is empty in case the user double clicked
         //loop through the array Guitars concatenating the values into a formatted string
         for(var i in Guitars) {
              arr_Guitars.value += Guitars[i]['model'] + ':' + Guitars[i]['neck'];
              /*
              //Nest this for(){} loop within itself for every tier of your array
              //for each nesting move the delimiters over, if you used a ; next, the
              //nested loop would look like the following:
              for(var ii in Guitars[i]['avail_colours']) {
              arr_Guitars.value += Guitars[i]['avail_colours'][ii]['colour'] + ';';
              }
    
              //to add more array items to this Guitar[i] replace the last delimiter of
              //the output of the last nested loop with that of the tier above it
              arr_Guitars.value = arr_Guitars.value.replace(/;$/,":");
              //or if you're finished with this Guitar[i] remove it
              arr_Guitars.value = arr_Guitars.value.repalce(/;$/,"");
              */
    
              arr_Guitars.value += ',';
              //the preceding line could be added to the end of the first line of the
              //loop if you're only passing a two tiered array
         }
         //remove the last , from the formatted string
         arr_Guitars.value = arr_Guitars.value.replace(/,$/,"");
    
         document.form_Decision.submit();  //submit the form
    }

    Note the formatted string uses the following structure model:neck,model:neck. Also for those new to regular expressions the expression used in the value.replace(); method in plain english means "the comma before the end of the string". Forward slashes mark the beginning and end of the expression, the comma represents a comma and the dollar sign represents the end of the string being analyzed.

    Now on the server:

    <?php
    //get the formatted string
    $Guitars = mysql_real_escape_string($_POST["arr_Guitars"]);
    //make sure the array being passed is not empty
    if($Guitars != ""){
         //Php's explode function breaks apart the string into an array of strings based on the delimiter
         //Here we break apart the string into it's sub-strings <em>model:neck</em>
         $Guitars = explode(",", $Guitars);
    
         //for each exploded array item separate the model and neck values and elaborate the array
         foreach($Guitars as $key=>$row) {
              $row = explode(":",$row);
              $Guitars[$key] = array(
                   "model" => $row[0],
                   "neck" => $row[1]
                   );
         }
    }
    ?>

    And that's it, you now have $Guitars again on the server. This method of passing arrays is extensible in that each level of the array can have unlimited values, and the arrayitself can have unlimited dimensions. For every dimension added to the array you need a new delimiter and you have to run a variation on the second foreach() statement above based on that delimiter.

     

    Embedding fonts in Flex 3

    Fonts are the creative content of the font designer or foundry, so if you don't have a collection of fonts you've paid for, and aren't planning on purchasing some, you should stick to free fonts. A good place to start is Google, you'll find plenty of foundries who make a few free fonts, and several sites like [http://www.fonts.com/]. You may choose to embed a particular font that came with your operating system for the sake of cross-platform uniformity as well, however you still need to make sure that it is either an OTF (Open Type Font) or TTF (True Type Font), as Flex works with these file types. There are ways to convert postscript and other font formats to OTF/TTF but it's tedious and you're better off finding a different compatible font

    You can also load fonts as an external resource in your apps similar to just calling a system font, however embedding them is the way to go. Embedded fonts can be anti-aliased, take part in effects, and are handled as a true asset and thus with a higher regard in your application.

    There are a number of ways to embed fonts in your Flex applications. If you'reembedding a font that's active in your system you can specify the system name as in the following example:

    @font-face {
    src: local("Arial");
    fontFamily: MyFont;
    }

    Likely however you'll not want to keep a whole bunch of fonts active or have to think about activating your project fonts every time you compile, in which case you can copy the font file to your project directory. In the example below the Arial font is in a 'fonts' sub-directory of my project:

    @font-face {
    src: url("/fonts/Arial.ttf");
    fontFamily: MyFont;
    }

    Note: If you use spaces in the font family as in "My Font" you'll run into an issue where the font appears in Design View but isn't compiled with the app.

    There are other options that can be specified to customize your font-face:

    fontStyle: normal | italic | oblique;
    fontWeight: normal | bold | heavy;
    advancedAntiAliasing: true | false;

    These style declarations are placed within the mxml <mx:Style> tag. The above code uses CSS, which is best for styling and skinning your application, but if you prefer you can do the same thing in actionscript.

    For more information on how to, and why you should/shouldn't embed a font in your applications refer to [http://livedocs.adobe.com...fonts_09.html]

    Keep in mind that font files can be quite large, in the 5-12MB+ range and that size will be added to the weight of your application. It's best to use lighter fonts when creating online apps, in which case try to find one's under 200KB.