Skip to content
Oct 22 12

Binary Curious?

by gnarf

Over the last few months, I have seen a lot of discussion surrounding gender equality within the tech community.  Many people have approached the gender gap and seen only across it, as if there were only male and female sides to the divide.  In reality, gender is not binary, and I feel that an entire group of people neither male nor female is being ignored.

Masculinity and femininity are each a spectrum. A person may be born physically male or female, but our minds are far more complex. It’s easiest to recognize the extremes using stereotypes: the macho man, the flamboyant guy, the girly girl, and the butch woman. Most people do not fit into a stereotype — instead, they exist in the grey areas between these extremes. It is difficult to know where a person falls on that spectrum unless they tell you.

I have never felt comfortable belonging to either gender. Even in the first grade, I didn’t feel like one of “the boys.” I was different and didn’t belong to their group, but I quickly learned the art of pretending I fit into the “male” role.  Physically, I am male — and I have no desire to change this — but I don’t believe “male” describes my gender.

As I age, I feel less inclined to maintain the facade I adopted as a young “boy.”  I don’t feel like I would fit in as one of the “girls” either, but I still explore ways to express my femininity and feel comfortable with my own gender, whatever it might be called. Growing out my hair in high school was one of my first displays of femininity. I recently started wearing feminine clothing around friends, in my home, and occasionally while out in public.  It helps me express a part of myself that hides behind the facade.

I am not alone. You might be surprised how many of “the guys” or “the girls” in our community are actually the opposite, neither, or both.  When “coming out” to small groups of friends, I am still surprised by how many say “me too.”  It is easy to incorrectly assume that they are “male” or “female”.  We think “guy/girl” naturally, and this is an especially difficult topic for most people to broach.  While there is nothing wrong with guessing “male” or “female” after your initial observation, the important part is to accept that person when you find out that your initial guess was wrong.

Discrimination Exists

I recently visited a female friend of mine who is a solid PHP developer.  She told me stories about her experience with an all male team she works with.  The men on the team repeatedly ignored her ideas in meetings, yet when they came to her for help, they took credit for her work.  I told her she needed to leave her job immediately and find a company that wasn’t filled with assholes.  Perhaps they weren’t motivated by a burning hatred of women, but it is clear she was being treated like a second-class member of her team.

While I am comfortable with my gender, I am also cautious.  “Other” gendered people are below both men and women in our society’s ‘privileged’ scale.  Many subtle comments my friends in our community have made have offended or scared me.  One member of our community labeled me “gross” after seeing pictures of me in a dress.  I have been physically threatened while out in public.  I am afraid to put these words onto my blog because they might sour someone’s opinion of me or my work.

Fighting Discrimination

A woman in our field recently interrupted a story I was telling because I used the word “guys” to describe a group of us.  She felt the need to interject with “or girls.”  It made me think “Girl, trust me, I’m not one of the guys either,” but I wasn’t comfortable discussing my gender at the time.  My word choice deserved correction; even I have trouble using gender neutral words to describe people.  If you feel the need to correct these poor word choices, please correct to “developers” or even “people.”  Otherwise, you risk making someone feel even more self-conscious about their gender, and at the very least, you continue to reinforce the notion that this is all about “guys” or “girls.”

Another reaction is to organize “all-girl” events and programs.  I love the fact that these exist.  They give women a place to go to where they can share their experiences with other women.  If these events have made even one woman more interested or comfortable being in our community, they have succeeded.

Unfortunately, whenever I read about an “all-girl” event, I feel doubly excluded.  I obviously am not a “girl”, and I am not a “guy” either.  Ladies, I wish I could express my feminine aspects and join you, but I worry that I would offend the spirit of the gathering or make you uncomfortable, or at the most cynical extreme, be seen as mocking both females and cross dressers.

The obvious corollary is to organise similar events for GLBTQ programmers, which sounds like an awesome idea.   But can we really afford to divide the community, hacking only among people who are similar to ourselves? Ultimately, if we can’t make everyone feel comfortable in the developer community at large, we risk segregating the profession.

Those of us who don’t fit nicely into the gender binary are constantly faced with choices.  Which bathroom do we use?  Which gender do we pick from the drop down on our profile?  Sara Dopp wrote an open letter to the community 4 years ago about this exact topic.  Even when filling out a profile today, I have to make a choice every time I encounter the “gender” field, Male or Female, at least until Google+ offered me “Other.”  I wanted to give Google a giant hug.  “Other” might be a terrible word to describe my gender, but at least I’m not forced to choose between male and female.  If you are designing any form that requests the user supply a gender on it, please make it a free-form text field, or take a minute and decide if you even need that bit of information for anything.

I’ve heard arguments claim we should do something to “equalize” the genders in our community.  They also seem to ignore that gender is not a binary.  This is not something we can resolve with an equality operator.  I propose that we stop concerning ourselves with balancing the number of “men” and “women” in the community and instead concentrate on making everyone feel welcome, regardless of gender.  It shouldn’t matter to any of us if we have the right number of guys, girls, trans, genderqueer, genderfluid, or any other word you’d like to use to describe your own gender.  We are all developers.

Perhaps this quote from my friend can explain it even better:

 “Gender equality is a logical fallacy, because gender doesn’t actually exist. The concept of gender is like √-1 in that we use it — so, it exists, but it’s not real. It is imaginary. It only exists in our heads, and we have to express that shit with symbols.”

— Miss Andrist,
Lover of Men

I wish there was a more even representation of all genders in our community, but I think looking beyond gender is a must to help obtain this goal.  Can you look at a group of developers and not see their gender?  If you find yourself counting the number of males and females at a gathering, stop.  Take a step back.  Your count is wrong — those numbers are all imaginary.

If anything you’ve just read resonates with you, I would suggest reading Jon maddog Hall’s excellent blog post for another point of view that explains how the issue affects sexuality and race as well.  I would also like to thank him for writing that blog, without having read it, I doubt I’d have the courage to post this one.  While thanking people, I must also thank the jQuery community members who have been very accepting of me for being myself, and not “one of the guys.”

Apr 9 12

GitHub Pro Tip: Hide red lines in a diff

by gnarf

I was looking at a diff on GitHub today and said to myself, “This would be so much easier to review if all the red lines were hidden.”

So I pulled open the console and wrote a little jQuery:

$("div.diff-view .gd").closest("tr").toggle().length;

It can take a little time to run depending on the number of lines it needs to hide. The .length is there just to stop the console from showing you all of the elements it toggled.

I’ve given up on actually making an easy to install bookmarklet in my wordpress, something keeps converting all my links to javascript:void(0) and I don’t care enough to debug it.

If you want to bookmark it – here is the code for a bookmarklet:

javascript:$("div.diff-view .gd").closest("tr").toggle();false

Edit: And just to test if bookmarklet is working again: gh:~red — Hey Look at that! You can drag that to your bookmark bar and click it on a diff in github! Thanks StackOverflow!

Oct 2 11

jQuery Conference 2011 Boston

by gnarf

Wow, I can’t begin to describe how amazing this weekend was. It was my first time giving a presentation, and it seems a lot of people enjoyed it. The breakout session I hosted went over amazingly well, and filled the room with laughter for like 40 minutes straight.

If you wanted to see my slides: http://gnarf.net/special-fx – the source for the slides and demos are available at https://github.com/gnarf37/special-fx

I’ll probably add more to this post later, but yeah… Great weekend! Thanks everyone who came to the conference!

Jun 21 11

jQuery.ajaxQueue

by gnarf

I’m starting to put together an example of using .queue(), jQuery.Deferred(), jQuery.ajax() together to create a queue for ajax requests.

It is a front-end for jQuery.ajax() and takes the same options/arguments as any standard ajax call, just makes sure that only one ajax call can be running at a time.

Take a look at the gist.

/*
* jQuery.ajaxQueue - A queue for ajax requests
*
* (c) 2011 Corey Frang
* Dual licensed under the MIT and GPL licenses.
*
* Requires jQuery 1.5+
*/
(function($) {

// jQuery on an empty object, we are going to use this as our Queue
var ajaxQueue = $({});

$.ajaxQueue = function( ajaxOpts ) {
    var jqXHR,
        dfd = $.Deferred(),
        promise = dfd.promise();

    // queue our ajax request
    ajaxQueue.queue( doRequest );

    // add the abort method
    promise.abort = function( statusText ) {

        // proxy abort to the jqXHR if it is active
        if ( jqXHR ) {
            return jqXHR.abort( statusText );
        }

        // if there wasn't already a jqXHR we need to remove from queue
        var queue = ajaxQueue.queue(),
            index = $.inArray( doRequest, queue );

        if ( index > -1 ) {
            queue.splice( index, 1 );
        }

        // and then reject the deferred
        dfd.rejectWith( ajaxOpts.context || ajaxOpts, [ promise, statusText, "" ] );
        return promise;
    };

    // run the actual query
    function doRequest( next ) {
        jqXHR = $.ajax( ajaxOpts )
            .done( dfd.resolve )
            .fail( dfd.reject )
            .then( next, next );
    }

    return promise;
};

})(jQuery);

/*
* jQuery.ajaxQueue - A queue for ajax requests
*
* (c) 2011 Corey Frang
* Dual licensed under the MIT and GPL licenses.
*
* Requires jQuery 1.5+
*/
(function(a){var b=a({});a.ajaxQueue=function(c){function g(b){d=a.ajax(c).done(e.resolve).fail(e.reject).then(b,b)}var d,e=a.Deferred(),f=e.promise();b.queue(g),f.abort=function(h){if(d)return d.abort(h);var i=b.queue(),j=a.inArray(g,i);j>-1&&i.splice(j,1),e.rejectWith(c.context||c,[f,h,""]);return f};return f}})(jQuery)
Jun 1 11

jQuery Color v2 Beta 1 Released

by gnarf

Originally posted on the official jQuery blog

Back in 2007 we released the jQuery Color Plugin, and it has been providing you with color-based animations ever since. We are now preparing a second version of this plugin which adds an API, RGBA, HSLA, and many other features. It is time for a beta! The repository for this plugin can be found at github.com/jquery/jquery-color.  There are also uncompressed and minified versions available on code.jquery.com.

New Feature Overview:

RGBA

We now support RGBA color values. In browsers that don’t support RGBA, the nearest backgroundColor to the element will be used to calculate a “blended” approximation of the color. Although this isn’t “true” alpha, it will at least provide the illusion of alpha when dealing with solid background colors.  This is a screenshot of Opera 10, Chrome 10, Firefox 3.6, and IE 6 all running this demonstration of alpha blending:

Opera 10, Chrome 10, Firefox 3.6, and IE 6  demonstrating alpha blending

HSLA

We also now support using HSLA color values across all browsers, with the execption of alpha, which uses the same techniques described above.

Easy-to-use API

Instead of a simple group of private utility methods, $.Color() now creates a new Color object. The new Color object can be initialized in a few different ways: color names, hexidecimal color codes, css style rgba/hsla, an array of rgba values, or an object with the color properties. There are now helper methods for each color property, like .red() and .hue() that can get or set the particular value. Combined with helper functions like .toRgbString(), .transition() and .is(), $.Color can now handle whatever color needs you might have. Refer to the README on github.com/jquery/jquery-color for an overview of all the new functions available. No longer is jQuery.Color just providing you with animation of simple colors, you can now use its API to do complex color calculations and animations!

Quick Examples:

// Create a red Color object:
var red = $.Color( 'rgba(255,0,0,1)' ); // using a css string

// Create a red Color object, then make orange:
var orange = $.Color( '#FF0000' ).green( 153 );

// Get the color halfway between red and blue:
var between = $.Color([ 255, 0, 0 ]).transition( "blue", 0.5 );

Animating Partial Colors

We have added support for only defining one or two properties of a color object so that you can animate using a partial color like this:

// desaturate the background of this element
elem.animate({
    backgroundColor: $.Color({ saturation: 0 })
}, 1000);

Reporting Problems / Requesting Features:

If you find any problems with the new color plugin, or would like to request a feature, please create a github issue.

Also, we’d love to see and showcase some excellent uses of the new $.Color beta, so please be sure to share it with us in the comments.

May 14 11

Messing with jQuery.color

by gnarf

So, I’ve been putting a lot of time into crafting a new API for jQuery’s color animate plugin lately, and thought I would share this quick demo usage example I just put together.

Note that this actually does some clever backgroundColor alpha blending by looking for the elements nearest parent with a backgroundColor to fake support for RGBA in older browsers.

I’m pretty interested in seeing what other (possibly more legitimate) uses people might have for a Color library.

Note: This color plugin is all in a development branch – you can use it, and please do, but the API is still subject to change…

Sep 30 10

The uses of jQuery .queue() and .dequeue()

by gnarf

This was originally posted on stack overflow.  Please go vote for it there if you are a registered user.

Queues in jQuery are used for animations. You can use them for any purpose you like. They are an array of functions stored on a per element basis, using jQuery.data(). The are First-In-First-Out (FIFO). You can add a function to the queue by calling .queue(), and you remove (by calling) the functions using .dequeue().

To understand the internal jQuery queue functions, reading the source and looking at examples helps me out tremendously. One of the best examples of a queue function I’ve seen is .delay():

$.fn.delay = function( time, type ) {
  time = jQuery.fx ? jQuery.fx.speeds[time] || time : time;
  type = type || "fx";

  return this.queue( type, function() {
    var elem = this;
    setTimeout(function() {
      jQuery.dequeue( elem, type );
    }, time );
  });
};

The default queue – fx

The default queue in jQuery is fx. The default queue has some special properties that are not shared with other queues.

  1. Auto Start: When calling $(elem).queue(function(){}); the fx queue will automatically dequeue the next function and run it if the queue hasn’t started.
  2. ‘inprogress’ sentinel: Whenever you dequeue() a function from the fx queue, it will unshift() (push into the first location of the array) the string "inprogress" – which flags that the queue is currently being run.
  3. It’s the default! The fx queue is used by .animate() and all functions that call it by default.

NOTE: If you are using a custom queue, you must manually .dequeue() the functions, they will not auto start!

Retrieving/Setting the queue

You can retrieve a reference to a jQuery queue by calling .queue() without a function argument. You can use the method if you want to see how many items are in the queue. You can use push, pop, unshift, shift to manipulate the queue in place. You can replace the entire queue by passing an array to the .queue() function.

Quick Examples:

// lets assume $elem is a jQuery object that points to some element we are animating.
var queue = $elem.queue();
// remove the last function from the animation queue.
var lastFunc = queue.pop(); 
// insert it at the beginning:    
queue.unshift(lastFunc);
// replace queue with the first three items in the queue
$elem.queue(queue.slice(0,3)); 

An animation (fx) queue example:

Run example on jsFiddle

$(function() {
    // lets do something with google maps:
    var $map = $("#map_canvas");
    var myLatlng = new google.maps.LatLng(-34.397, 150.644);
    var myOptions = {zoom: 8, center: myLatlng, mapTypeId: google.maps.MapTypeId.ROADMAP};
    var geocoder = new google.maps.Geocoder();
    var map = new google.maps.Map($map[0], myOptions);
    var resized = function() {
        // simple animation callback - let maps know we resized
        google.maps.event.trigger(map, 'resize');
    };

    // wait 2 seconds
    $map.delay(2000);
    // resize the div:
    $map.animate({
        width: 250,
        height: 250,
        marginLeft: 250,
        marginTop:250
    }, resized);
    // geocode something
    $map.queue(function(next) {
        // find stackoverflow's whois address:
      geocoder.geocode({'address': '55 Broadway New York NY 10006'},handleResponse);

      function handleResponse(results, status) {
          if (status == google.maps.GeocoderStatus.OK) {
              var location = results[0].geometry.location;
              map.setZoom(13);
              map.setCenter(location);
              new google.maps.Marker({ map: map, position: location });
          }
          // geocoder result returned, continue with animations:
          next();
      }
    });
    // after we find stack overflow, wait 3 more seconds
    $map.delay(3000);
    // and resize the map again
    $map.animate({
        width: 500,
        height: 500,
        marginLeft:0,
        marginTop: 0
    }, resized);
});

Queueing something like Ajax Calls:

Originally posted hererun jsFiddle demo

  // jQuery on an empty object, we are going to use this as our Queue
  var ajaxQueue = $({});

  $.ajaxQueue = function(ajaxOpts) {
    // hold the original complete function
    var oldComplete = ajaxOpts.complete;

    // queue our ajax request
    ajaxQueue.queue(function(next) {

      // create a complete callback to fire the next event in the queue
      ajaxOpts.complete = function() {
        // fire the original complete if it was there
        if (oldComplete) oldComplete.apply(this, arguments);

        next(); // run the next query in the queue
      };

      // run the query
      $.ajax(ajaxOpts);
    });
  };

// get each item we want to copy
$("#items li").each(function(idx) {

    // queue up an ajax request
    $.ajaxQueue({
        url: '/ajax_html_echo/',
        data: {html : "["+idx+"] "+$(this).html()},
        type: 'POST',
        success: function(data) {
            // Write to #output
            $("#output").append($("<li>", { html: data }));
        }
    });
});

Another custom queue example

Run example on jsFiddle

var theQueue = $({}); // jQuery on an empty object - a perfect queue holder

$.each([1,2,3],function(i, num) {
  // lets add some really simple functions to a queue:
  theQueue.queue('alerts', function(next) { 
    // show something, and if they hit "yes", run the next function.
    if (confirm('index:'+i+' = '+num+'\nRun the next function?')) {
      next();
    }
  }); 
});

// create a button to run the queue:
$("<button>", {
  text: 'Run Queue', 
  click: function() { 
    theQueue.dequeue('alerts'); 
  }
}).appendTo('body');

// create a button to show the length:
$("<button>", {
  text: 'Show Length', 
  click: function() { 
    alert(theQueue.queue('alerts').length); 
  }
}).appendTo('body');