• More fun with JS: Hacking away shallow copy issues

    For those of you who have ever tried to copy an array in JavaScript, you’ll know that your “copy” basically just retains references to the original array, meaning any operations you perform on the copy are also performed on the original (push()ing and pop()ing, etc.).  Generally, this type of copying is referred to as shallow copying. For example:

    var d = [];
    d.push("Woo!");
    var e = d;
    e.pop(); // Returns "Woo!"
    d.pop(); // undefined
    

    The opposite to this is a deep copy, where after the copy is done, the copy and the original are no longer dependent on each other since they are separate objects.

    Now, I could be cool and paste a bunch of code showing you how to traverse nested objects and return a new object, but I am lazy, so this has been my solution for the last little while:

    Array.prototype.clone = function() {
        return JSON.parse(JSON.stringify(this));
    }
    

    Since stringifying returns a new string object, and parsing returns another object in turn, you’re in the clear. It can be a little expensive depending on the size and complexity of the array, but with this extension, you can do some fancy stuff, like:

    var d = [];
    d.push("Woo!");
    var e = d.clone();
    e.pop(); // Returns "Woo!"
    d.pop(); // Also returns "Woo!"
    

    Caveats: this solution is not the ideal one, even though it works really well for my purposes.

    The first thing you have probably noticed is that I extended the default array object, which is generally a no-no, but for the sake the example I’m letting it be (I currently have the clone() function as a util function in my module class so as to not modify any behaviour on the rest of the page; this is really how it should be done). The second issue here is a problem i discussed in my previous post about objects not being stringifyable due to circular references.  Thus this wouldn’t work with very complex objects (that aren’t necessarily being treated as arrays).

    Having said that, enjoy the hack; hope it saves a headache or two out there.  

  • Things I learned while writing a macro plugin in JavaScript

    I’ve been writing a simple macro plugin for JavaScript (without the use of jQuery or any other frameworks) in order to learn more about the language (as well as build what I think to be a cool tool). I have already hit a few minor but itchy bumps and, while I suspect most of these issues are fairly common knowledge among experts in the community, I thought I’d discuss them anyway.

    I (firstly) discovered that HTML5’s localStorage and sessionStorage don’t actually support the storage of objects. This makes sense in retrospect, since localStorage is only meant to offer a simple key - value store; however, it can be frustrating when attempting to persist complex data, especially since (for me) direct assignment seemed to be the most intuitive thing to do at the time. Silly me, with my assumptions.

    The solution here was actually fairly straightforward:

    sessionStorage.setItem("store", JSON.stringify(store));
    

    Most browsers these days support JSON stringify() and parse(). For those who don’t know any better, these methods provide developers with the ability to serialize their objects/data structures, as well as go in the reverse direction. A fairly succinct article on JSONs can be found here.  Be warned, though! You cannot use JSON.stringify() to serialize DOM nodes. We’ll come back to this later. 

    *Unrelated to the above, I also discovered this nifty little hack for browsers that don’t support local storage. Below, I use win.name (a remnant from the paleolithic era of web-development) to persist the data. Realistically, most modern browsers are built with local storage support and, while this solution isn’t quite ideal, I feel like it’s nice to have the support anyway.

    var localStorageSupport = 
    	(typeof(Storage)!=="undefined")? true : false;
    
    var win = window.top || window;
    var store = (localStorageSupport)?
    	(sessionStorage.getItem("store") ? 
    		JSON.parse(sessionStorage.getItem("store")) : {})
    	:(win.name ? JSON.parse(win.name) : {});
    

    My second issue stemmed from the fact that, while trying to store relevant data for replaying user actions, I found (of course) that I couldn’t serialize DOM nodes by stringifying them. Till relatively recently, there was no built-in solution to do this well at all - and due to the circular references that often occur inside the tree (child/parent relationships and what have you), JSON did not support dealing with it. If you tried to stringify a DOM node at all, you’d probably see something along the lines of “TypeError: Converting circular structure to JSON” in your console. 

    This isn’t to say that getting around the problem is terribly hard, especially now. Currently, there appears to be XMLSerializer support in most browsers. I checked it out by running the following

    p = new XMLSerializer()
    p.serializeToString(myVar._body)
    

    and got back these results (at least for my simple page with a few buttons, a link, and a div):

    Huzzah! Great! Yes? No? Unfortunately, it didn’t quite suit my purposes, since I wanted a nested associative array - and not a single giant-ass string - based on the structure. Not to say that they aren’t useful to have, but the XMLSerializer and DOMParser interfaces strike me as being relevant only in cases that saved DOM structures need to be re-assessed as an XML document. My solution was relatively quick to write using the existing DOM traversal functions; some really good info on node iteration and DOM tree traversals can be found here

    var XMLSerialize = function(node, output) {
        output = (node.nodeName !== undefined)?
        	{ nodeName: node.nodeName } : {};
    
        if(node.attributes !== null) {
    	    for (var i = 0; i < node.attributes.length; i++) {
    	        output[node.attributes[i].name] = node.attributes[i].value;
    	    }
    	}
    
        if (node.hasChildNodes()) {
          output.children = [];
          var i = 0;
          for (var child=node.firstChild; child != null; child=child.nextSibling) {
            if(child.nodeType == 1) {
            	output.children[i++] = this.XMLSerialize(child, output.children);
            }
          }
        }
    	
        return output;
     }
    

    The object it returns works relatively well for me, and I am able to traverse it efficiently. By grabbing the nodeType on the child I was able to retain only element/tag children, since there are actually several node types a node itself can be. Here’s the full list of constants returned by nodeType

    Stringifying the XMLSerialize output of my document currently results in something that looks like the text below:

     {"nodeName":"#document",
     "children":[
    	{"nodeName":"HTML",
    	 "children":[
    	 	{"nodeName":"HEAD",
    	 	 "children":[
    	 	 	{"nodeName":"TITLE","children":[]},
    	 	 	{"nodeName":"LINK","type":"text/css","href":"static/css/style.css","rel":"stylesheet"},{"nodeName":"SCRIPT","type":"text/javascript","children":[]}
    	 	 ]
    	 	},
    	 	{"nodeName":"BODY",
    	 	 "children":[
    		 	{"nodeName":"BUTTON","children":[]},
    		 	{"nodeName":"BUTTON","children":[]},
    		 	{"nodeName":"BUTTON","children":[]},
    		 	{"nodeName":"A","href":"","children":[]},
    		 	{"nodeName":"DIV","class":"panel","children":[]}
    	 	 ]
    	 	}
    	 ]
    	}
     ]
    } 
    

    You know, instead of:

    Lame

    Lame. 

    Those have been my only issues so far, but as my terribly riveting adventure with JavaScript continues, I will be sure to write more captivating and emotionally wrought stories.

  • Watchdog AMS: Building from the Ground Up - Part 1

    I have always been afforded the great luxury of being surrounded by technology I could pry open, technology I could break, and technology I could make my own. I have built applications and written a bunch of software for school, for work, and for pleasure. I have mucked around with electronics kits and have an annoyingly large collection of little parts (diodes, resistors, caps, what have you) sitting in a box beside my bed. Despite much of this, I have always considered myself only a tinkerer. 

    Today is no exception. I am still a tinkerer- not special in any particular way- but I do believe am a little bit closer to being a builder. What made the difference? A God-forsaken, awful project I call:

    Watchdog AMS (tagline: A comprehensive animal monitoring system for veterinarians and owners alike!).

    Now, before I complain any more, I will say that I learned a lot. No other personal learning experience has been as comprehensive and hands-on as building WatchdogAMS has been (not even the time I tried to flush a pot of festering old chili down the toilet on residence move-out day back in first year; hint: it did not end well). And there is a reason that this project in particular was such a good teacher; it encompassed everything I had learned in my degree - and then some. I learned a lot about hardware, about embedded programming, about security and communications, about data processing, about user experience design, and, most importantly, about people.

    Let’s start at the beginning, shall we?

    A friend of mine (let’s call him Kristof… well, because that’s his name) had a dog that fell very ill and passed a little while ago. Over lunch one day, he mentioned that she had never been spayed, leaving her more susceptible to illness and disease than her neutered counterparts. Upon her passing, Kristof was left very distraught. There wasn’t much that could have been done given that she was fairly old, and they knew early on that they might have been risking her health by not having her spayed. He also commented that sometimes she had stayed overnight at the clinic, as many sick dogs are asked to do, but that she was likely monitored on an hourly basis at best.

    During the above conversation, what struck me the most weren’t his claims of veterinary neglect; although statistically probable, there often isn’t much veterinarians or nurses can do about their schedules. Truthfully, the most noticeable part of the conversation was how regretful he sounded about not being able to help her through the pain and assure her, as well as himself, that she was okay.

    I am not a pet owner myself but I love most animals, and so (Kristof and) I couldn’t help but think- what if there was a better way to know that your pet was okay? Even more - what if there was a better way to alert your pet’s attending veterinarian if something was seriously wrong? At first, we were skeptical that something of the sort didn’t already exist, so we did a little research only to find that there was nothing on the consumer market that monitored these wonderful canine creatures beyond basic GPS tracking. Bummer, right? Strangely enough, it didn’t strike us that we had the capacity to build it ourselves, the way we wanted it to be - at least not till a little while later.

    Next: Designing the system from the top down.  

  • Reputation

    • Bhavya Kashyap [11: 01 AM]: You get to try my app out yet?
    • Michael Seliske [11: 01 AM]: No
    • Michael Seliske [11: 01 AM]: I will try now , what's it called?
    • Bhavya Kashyap [11: 01 AM]: 8 Ball, tough there are a bunch
    • Michael Seliske [11: 01 AM]: I will look for one with a pretty icon
  • Device Events with Javascript: Detecting a Shake

    My most recent endeavours have been greatly associated with mobile web development. It’s fun stuff, especially looking at the kinds of support provided by HTML5 and a lot of the new Javascript interfaces. In an attempt to test the waters, I was trying to write a mobile Eight Ball application, and so I was looking at the Device Motion Event API supplied by W3 to give me some insight on how to detect a “shake” event. 

    Their API spec was useful, but I did end up running into a problem where nearly any change in acceleration would trigger my eightBall() event. I finally realised that the better way to go about it would be this:

    if (typeof window.DeviceMotionEvent != 'undefined') {
      	// Shake sensitivity (a lower number is more)
      	var sensitivity = 16;
    
      	// Position variables
      	var x1 = 0, y1 = 0, z1 = 0, x2 = 0, y2 = 0, z2 = 0;
    
      	// Listen to motion events and update the position
      	window.addEventListener('devicemotion', function (e) {
      		x1 = e.accelerationIncludingGravity.x;
      		y1 = e.accelerationIncludingGravity.y;
      		z1 = e.accelerationIncludingGravity.z;
      	}, false);
    
      	// Periodically check the position and fire
      	// if the change is greater than the sensitivity
      	setInterval(function () {
      		var change = Math.abs(x1-x2+y1-y2+z1-z2);
    
      		if (change > sensitivity) {
      		  eightBall();
      		}
    
      		// Update new position
      		x2 = x1;
      		y2 = y1;
      		z2 = z1;
      	}, 200);
      }
    

    This works rather effectively in most established mobile browsers (mobile IE does not count). I find a lower sensitivity and a longer time interval to be more accurate to how vigorously and how long a human would actually shake a mobile device. Now, I’m not entirely sure where I found this snippet of code but the majority of it isn’t mine. If I find the author I shall cite him here.

  • Step by Step: Getting your WebWorks App Up and Running on Windows

    With all the recent news about the PlayBook’s SDK, I thought I’d attempt to go through the installation process myself, never having had experience with RIM’s application dev tools before. As mentioned in the title, this tutorial is for Windows. I have an iMac and will probably write about the installation process for it at some point, but for now I shall be running the installation on my Windows 7 64-bit machine. 

    What is WebWorks?

    The WebWorks SDK allows developers to write applications for RIM’s Blackberry and Playbook using HTML, CSS, and Javascript. It supports HTML5 and the all the commonly used Javascript libraries and frameworks, such as JQuery, seem to work with it. The great thing about this is that really anyone who knows anything about web development can get started on writing apps. This tutorial is targeted at setting up an environment for the Playbook, but everything just said about the WebWorks SDK still stands for the Blackberry version of the tool.

    Assumptions

    Hopefully by this point you have completed all the necessary forms and have associated your PayPal account with your vendor account. I also assume that you have procured the necessary tools and executables for the process. If not, here are the things you need:

    1. An Intel® Pentium® 4 or AMD Athlon™ desktop processor 2 GHz or faster
    2. 1 GB or more available hard disk space (this is from the site… I am assuming you have more than this).
    3. 2 GB RAM or more
    4. Computer monitor with resolution of 1024 x 768 or higher
    5. Windows® XP SP3, Windows Vista® Ultimate or Enterprise, or Windows® 7
    6. VMWare Player, which is currently free
    7. The Adobe Air SDK.
    8. The Blackberry Playbook WebWorks SDK
    9. The Blackberry simulator image (which you get after extracting the the simulator download)

    You should have 1 archive and 3 execution files. 

    Installation

    This part is pretty straightforward initially… but then gets a liiittle funky. With a little luck and a lot of guidance, however, you should be okay. So! Grab your favourite brand of snacks and your favourite drink (Coffee? Tea? Tequila?) and let’s get cracking. 

    Read More

  • Beyoncé and the Blackface Case

    I usually steer clear from very opinion driven posts. This time, I couldn’t stay away. 

    Far from the glamorous Sasha Fierce, the beauty posed for the magazine with amazing fashion designers clothes, but also in a dress created by her mother. [It is] A return to her African roots, as you can see on the picture, on which her face was voluntarily darkened. All the pictures will be available in the collector edition, on sell at the end of this month.

    This is a quote from French fashion magazine L’Officiel regarding the recent shoot they did with R&B superstar Beyoncé Knowles. The shoot involved the painting of her face (i.e. causing it to appear darker than her original skin-tone, as well as dressing her up in African tribal clothing of ambiguous origin. The whole piece was meant to be a tribute to Nigerian musician and human rights activist Fela Kuti, although not the “inspiration” for the shoot. 

    A few more-commonly-frequented blogs, such as Jezebel, got a hold of the story and used it as a basis for a discussion on “Blackface" - the idea that the fashion industry uses blackness as an accessory rather than accepting blackness into itself. 

    Being a person of colour myself (I’m of East Indian descent, if you haven’t figured out from my name; no one would ever look at me and tell me I appeared to be anything otherwise) I understand the sentiment… on the surface. Unfortunately, in the context of the whole situation, I find the amount of protest this has garnered to be irrational and unnecessary. 

    I) Blackness as an accessory in fashion

    Jezebel writer Dodai Stewart mentions:  ”It’s one thing to feel moved by Fela Kuti, and quite another to treat blackness as a fashion accessory, like a pair of glittery heels you put on because it looks cool." I have to ask- what is wrong with treating dark skin as a fashion accessory? There is no correlation between this shoot’s usage of "Blackface" and any sort of discrimination. There is nothing demeaning about the shoot’s usage of blackness, especially when the focus of and inspiration for the shoot are women of African descent (as opposed to many shoots where the focus of the piece is someone of Caucasian descent and surrounded by darker skinned models- which can be perceived as racially insensitive).

     Dodai also received a belligerent, anonymous response to her first article on the subject. While some of the content wasn’t really necessary, he/she made the point that “Its no different from a whi[t]e girl powdering her face to look like fucking marilyn monroe.”

     This is absolutely true.  It isn’t. Beyoncé is (as mentioned earlier) already black, and while accentuating her blackness is, in this case, an accessory- it is not done in a way that mocks her blackness or uses her blackness to promote a non-black concept/agenda. Context absolutely matters. Her blackness here is meant to be art, and this shoot is meant to encapsulate an aesthetic readers would not ordinarily see. That is what [high] fashion is. 

    Read More

  • Salt & Fat: Sectioning a citrus →

    saltandfat:

    There are two reasons to section1 a citrus. The first is for presentation, an elegant way to use lemons, oranges and grapefruit pieces in all kinds of recipes, from salads to cakes. The second is to remove the tough, often bitter, pith and inner membrane so that the flavor of the fruit can…